Skip to content

feat(wallet-lib): do not sync transactions if mnemonic is absent#7

Merged
shumkov merged 1 commit into
v0.22-devfrom
feat/do-not-sync-in-abscence-of-mnemonic
Nov 3, 2021
Merged

feat(wallet-lib): do not sync transactions if mnemonic is absent#7
shumkov merged 1 commit into
v0.22-devfrom
feat/do-not-sync-in-abscence-of-mnemonic

Conversation

@jawid-h

@jawid-h jawid-h commented Nov 3, 2021

Copy link
Copy Markdown
Contributor

Issue being fixed or feature implemented

This change eliminates unnecessary synchronization of transactions in case wallet has been generated from the new mnemonic

What was done?

Check if the wallet has been generated from the new mnemonic and sync transactions from the best block (instead of block 1 or the one provided via unsafeOptions: { skipSynchronizationBeforeHeight: <n> })

How Has This Been Tested?

  • Passed no mnemonic to the Wallet initialization arguments
  • Ensured quick initialization time
  • Hooked on account events and ensured that synchronization of the new blocks works properly

Breaking Changes

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

@jawid-h jawid-h added this to the v0.22.0 milestone Nov 3, 2021
@shumkov
shumkov merged commit 7d14553 into v0.22-dev Nov 3, 2021
@shumkov
shumkov deleted the feat/do-not-sync-in-abscence-of-mnemonic branch November 3, 2021 15:08
shumkov pushed a commit that referenced this pull request Nov 23, 2022
feat: type deserialization + encoding
QuantumExplorer added a commit that referenced this pull request Mar 16, 2026
- Delete fake tests in make_sure_core_is_synced_to_chain_lock/v0 that
  never called the production method (CRITICAL #1)
- Delete fake tests in verify_chain_lock_through_core/v0 that only
  exercised mock wiring, never the production method (CRITICAL #2)
- Add real tree verification in protocol_upgrade tests: v12 now checks
  shielded pool, notes, nullifiers, and anchors trees (MAJOR #3)
- Fix get_contract_with_fetch_info_and_fee assertion to verify the
  contract is Some, not just Ok (MEDIUM #4)
- Rename test_transition_from_version_10 and add actual verification
  of v11/v12 artifacts (LOW #5)
- Replace bare .unwrap() with .expect() in choose_quorum tests (LOW #6)
- Remove empty-input smoke test for store_address_balances (LOW #7)
- Fix test_decode_state_transition_at_exact_max_size to assert the
  correct property (not rejected as oversized) rather than incorrectly
  assuming zeros cannot decode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request May 14, 2026
…iagrams

New chapter under "Drive" that walks through the bench fixture's
widget contract and shows what each count-query proof actually
proves — both the path query the prover signs AND the verified
element the verifier extracts. Every example is reproducible
against the existing bench at
`packages/rs-drive/benches/document_count_worst_case.rs`.

Seven worked examples (the `group_by = []` proof surface):

1. `(empty)` — primary-key CountTree fast path, 585 B.
2. `brand == X` — PointLookup over byBrand (plain countable),
   1,041 B post-v12 (the value-tree-direct shape now activates
   for any countable terminator, not just rangeCountable).
3. `color == X` — PointLookup over byColor (rangeCountable),
   1,327 B. Same shape as #2 — the rangeCountable flag is only
   relevant for #7.
4. `brand == X AND color == Y` — PointLookup over byBrandColor;
   the proof descends through the byBrand value tree's
   `NonCounted`-wrapped `color` continuation to the byBrandColor
   terminator, 1,911 B.
5. `brand IN [b0, b1]` — outer Keys per In value, no subquery
   (the value-tree-direct shape on the In axis), 1,102 B.
6. `color IN [c0, c1]` — identical shape to #5, surfacing the
   v12 generalization at a glance: byBrand (plain countable)
   and byColor (rangeCountable) produce structurally identical
   proofs, 1,381 B.
7. `color > floor` — AggregateCountOnRange over byColor's
   ProvableCountTree; different verifier
   (`verify_aggregate_count_query`), single u64 result, 2,072 B.

Each section has three parts:

- **Path query** (decoded path + items + subquery), the prover's
  spec.
- **Verified element / payload** (the structured output of
  `verify_query`/`verify_aggregate_count_query`).
- **Mermaid diagram** with:
  - The tree element wrapper for the relevant GroveDB subtree.
  - Blue arrows tracing the descent.
  - A cyan target node for the verified element.
  - Faded nodes for context.

A "GroveDB Layout" diagram up front shows the storage shape for
the whole contract (doctype CountTree primary key, byBrand
NormalTree property-name with CountTree value trees and
NonCounted-wrapped byBrandColor continuations, byColor
ProvableCountTree property-name with CountTree value trees).
Each per-query diagram is a focused slice of this overview.

An at-a-glance comparison table at the end summarizes primitive
choice, verified shape, and proof size across all seven examples
to make the structural symmetry between #2/#3 and #5/#6 (post-v12
generalization) and the asymmetry of #7 (AggregateCountOnRange)
visually obvious.

Registered under `Drive` in `SUMMARY.md` immediately after the
existing `Document Count Trees` chapter, which it complements
(that chapter explains the tree variants in the abstract; this
one shows how queries traverse the resulting layout). Builds
cleanly via `mdbook build` against the existing
`mdbook-mermaid` preprocessor configuration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shumkov added a commit that referenced this pull request May 19, 2026
Five MEDIUM findings batched into a single commit:

F6 (correctness) — `submit()` silently no-op'd when the selected
recipient address was no longer in `recipientCandidates` (the row
flipped to `isUsed = true` between user-tap and submit body). Now
surfaces a typed `submitError` so the user sees "the address is no
longer available; pick a fresh one" instead of an unresponsive
button.

F4 (correctness) — IS-rejection branch left the tracked asset-lock
status at `InstantSendLocked` even after building a fresh CL
proof. If the second `submit_with_cl_height_retry` then failed,
the persisted status was stale (CL proof was attached internally
but discarded; the row carried the rejected IS proof). The
storage explorer + Resume UI both misreported the recovery state.
Now calls `advance_asset_lock_status(ChainLocked, Some(chain_proof))`
between the upgrade and the second submit so the row accurately
reflects the lock's CL-attached state regardless of which way the
submit goes.

swift-ios #7 — "No funded Core (BIP44 standard) accounts on this
wallet" empty-state copy fired even when zero-balance accounts
existed. The picker shows all BIP44 standard accounts (incl. zero
balance) so the "funded" qualifier was a lie. Dropped it; the
picker's balance column tells the user what's spendable.

rust-quality #3 — `drive-proof-verifier` Cargo dep was missing
`default-features = false`. Consistency with every other path-dep
in this crate; harmless today (default feature set is empty) but
insulates from upstream feature additions.

blockchain-security M2 — `decode_funding_addresses` zero-count
short-circuit. The FFI's `slice::from_raw_parts(ptr, 0)` contract
is technically sound even with a dangling non-null sentinel, but
the explicit early-return makes the safety doc trivially
satisfied + skips a function call.

Side change: `AssetLockManager::queue_asset_lock_changeset`
visibility widened from `pub(super)` to `pub(crate)` so the
orchestrated funding flow can pair an `advance_asset_lock_status`
call with a flush without going through the asset-lock module
boundary. Still crate-private; no consumer-facing API change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jun 15, 2026
…, contactInfo index allocation (review P0s/Critical)

Multi-reviewer pass found three serious bugs in the M3 rotation code
that the live UAT missed (UAT only exercised the pending-sent rotation
path, which the reject-tombstone masked). All fixed with red→green
regression tests.

P0 #1 — rotation re-send to an ESTABLISHED contact reset the version
to 0. The version bump unmasked the prior sent request's
accountReference, but the lookup only consulted `sent_contact_requests`
— empty once established (the outgoing request moves into
`established_contacts.outgoing_request`). So every real re-key read
None, reset version to 0, reproduced the original reference, and was
rejected by the contract's `(ownerId, toUserId, accountReference)`
unique index. New `ManagedIdentity::prior_sent_account_reference`
checks both maps. Test: prior_sent_account_reference_falls_back_to_established_outgoing.

P0 #2 — multi-doc sweep thrash. Immutable contactRequest docs are
never deleted, so after any accepted rotation a sender has two
non-tombstoned docs that BOTH return every sweep. The per-doc dedup
compared each against a single tracked reference, so the other doc
always triggered apply_rotated — flipping stored state 0↔7, tearing
down + rebuilding the external account, and writing changesets every
60s forever. New `newest_received_per_sender` collapses to the newest
doc per sender before ingest (a sweep fixpoint); apply_rotated also
gains an identical-request idempotency guard. Tests:
newest_received_per_sender_collapses_rotated_sender_to_latest_doc,
apply_rotated_incoming_request_is_idempotent.

Critical (C1) — swallowed persist errors → memory/disk divergence.
~8 state methods mutated in-memory then only logged a store() failure.
Worst case: reject() returned Ok even when the tombstone didn't
persist → the rejected contact resurrects on next launch with no
signal. New PlatformWalletError::Persistence; reject_contact_request
and the user-initiated send_payment path now PROPAGATE the error
(self-healing sweep writes still log — the immutable on-chain doc /
UTXO reconcile re-derives them). Test: reject_propagates_persist_failure
(toggle-fail persister, RED→GREEN).

Plus:
- #6: send-path encryptedPublicKey extraction returns a hard Err
  instead of a release-no-op debug_assert + zero-fill (would persist a
  valid-looking all-zero ciphertext if SDK encoding drifts).
- #7: contactInfo derivation-index allocated from a high-water mark
  over ALL owned docs (incl. skipped/undecryptable), not just the
  decryptable subset — a skipped doc's slot would otherwise collide on
  the unique index.
- #5 (Rust half): set_contact_info returns a 3-state
  ContactInfoPublishOutcome (Published / DeferredUntilTwoContacts /
  SkippedWatchOnly) so the UI can stop claiming an unconditional sync.
- crypto LOW: documented the account_index/accountReference
  consistency invariant at the send boundary.

230/230 platform-wallet lib tests green.
shumkov added a commit that referenced this pull request Jun 23, 2026
…orrect discovery over-scope

Spec gains a Q2 status+completion-criteria banner: #1-6 (contact-request
flow) done; remaining = #7 contactInfo + discovery ResidentWallet-fallback
removal + Swift drain-on-unlock + delete attach_wallet_seed; done-when =
git grep empty + builds + testnet on-device acceptance. Corrects the prior
over-scoping of discovery: the carry-scalar fix is KEPT (per spec §1/§2/§7),
not a rewrite target.

TODO gains the Q2 checklist + the out-of-Q2 findings: §6b queue restore
(upstream-blocked), §4.2 wipe hardening, §4.8 zero-keys import caveat.
auto_accept already tracked separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jun 23, 2026
Multi-agent review (feasibility/security/scope-dedup/adversarial) corrected
two over-optimistic items and added must-fixes:

- Discovery: DROP the 'remove ResidentWallet variants' step — it was wrong.
  External-signable wallets already route through discover_from_master; the
  ResidentWallet variants are the live path for genuine resident-key wallet
  TYPES and stay. No library change; the deep verified_scalar-drop rewrite is
  NOT needed (carry-scalar kept). Fix the §2 'exhaustive' overclaim.
- contactInfo (#7) is the load-bearing item: publish must DECRYPT (open), not
  just seal (doc<->contact binding is in ciphertext); refactor the shared
  resident-hardcoded fetch helper; build the root path in Rust + pin the parity
  test to the REAL auth path (silent-undecryptable hazard); high-water FRESH or
  refuse; implement the ContactInfoDecrypt drain (stub today, testnet-validated);
  confused-deputy re-validation.
- Atomic: wire verify_binds_to_xpub (zero callers) in the SAME change that
  deletes the dual gate. Port WipingXprv to the sibling FFI (§4.2). Delete the
  dead dash_sdk_dashpay_* surface. Add negative + cross-device acceptance cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jun 23, 2026
… (Q2 #7)

Add contact_info_seal + contact_info_open to ContactCryptoProvider (+ result
structs ContactInfoSealed/Opened, re-exported), implemented by the glue over
the signer's parity-tested primitives and by the SeedCryptoProvider test
harness; UnusedProvider gets stubs (not exercised by its drain test).

Security MUST-FIX pinned: the new test
contact_info_seal_open_matches_resident_derivation_at_real_auth_path proves
the provider's seal/open is byte-identical to the resident derive_contact_info_keys
at the REAL identity-auth root path (built via identity_auth_derivation_path_for_type),
not an arbitrary test path — contactInfo is self-encrypted, so a wrong root
would silently write undecryptable data with no on-chain oracle.

The signer derives both hardened-child AES keys in-process (wiped); only
ciphertext crosses back. Foundation for the publish/sweep/drain conversion.

platform-wallet lib 293/293; platform-wallet-ffi builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jun 23, 2026
…(Q2 #7)

Convert set_contact_info_with_external_signer to route all key material
through ContactCryptoProvider instead of the resident wallet:
- split the shared fetch_decrypted_contact_infos into a key-free public scan
  (fetch_contact_info_docs, single-sourced fetch) + the resident-decrypt
  wrapper (still used by the signerless sweep);
- publish now does find-existing via crypto.contact_info_open (decrypt-to-match,
  per the review — the doc<->contact binding is in ciphertext) over the public
  scan, then crypto.contact_info_seal to encrypt; the resident wallet snapshot
  + derive_contact_info_keys call are gone from publish;
- the FFI gains core_signer_handle (ABI break, like send/accept).

De-dup (per the user ask): the 4 inline ResolverContactCryptoProvider
constructions (send/accept/drain/contactInfo) collapse to one
resolver_contact_crypto_provider helper. DecryptedContactInfo trimmed to the
fields the sweep actually reads.

The sweep still decrypts resident for now (its deferral + the ContactInfoDecrypt
drain op is the next step). platform-wallet lib 293/293; glue builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jun 23, 2026
…#7)

The signerless sweep can't decrypt contactInfo, so sync_contact_infos now
branches: a resident-key wallet TYPE decrypts inline (the kept resident path,
like discovery's ResidentWallet variant); a seedless/external-signable wallet
ENQUEUES a per-owner ContactInfoDecrypt op (idempotent, no payload) for the
signer-backed drain.

Implement the ContactInfoDecrypt drain op (was a no-op stub): re-fetch the
owner's contactInfo docs via the single-sourced key-free scan, decrypt + apply
each via the provider's contact_info_open, latest-published-wins. Encapsulated
as drain_contact_info_decrypt in contact_info.rs (RawContactInfoDoc stays
private there).

Security MUST-FIX (review): confused-deputy guard — the drain resolves the
entry's owner_identity_id as a wallet-owned identity and errors before any
fetch/decrypt if it isn't, so a poisoned entry can't decrypt under the wrong
identity. Root path built in Rust.

Tests: contact_info_decrypt_drain_rejects_non_owned_identity (the guard) +
seedless_sweep_enqueues_contact_info_decrypt (the defer) — both network-free.
The full re-fetch+decrypt+apply is testnet-validated (cross-device contactInfo).
platform-wallet lib 295/295; glue builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jun 23, 2026
… cascade

#7 contactInfo seedless (publish + sweep-defer + drain), the discovery
no-change confirmation, and the dead dash_sdk_dashpay_* de-dup are DONE this
turn. Records the measured §4.9 deletion cascade: removing the make_wallet
attach calls fails 5 tests (resident register_contact_account / resident xpub
in setup) — the remaining §4.9 work is reworking those onto Wallet-from-seed/
Some + the register_contact_account None-path C3 + the atomic verify_binds_to_xpub
wiring + Swift drain-on-unlock.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov added a commit that referenced this pull request Jul 14, 2026
…st proof assembly

Second-pass review fixes on #4041.

#1 (blocking): persist the invitation record immediately after funding, BEFORE the
InstantSend check — a ChainLock-confirmed voucher is rejected as a *link* but is
still a funded, reclaimable lock, so it must be recorded rather than orphaned. My
earlier fix put the persist after the IS/CL check, which still orphaned it.

#2 (blocking): claim-by-fetch now retries the funding-tx lookup (both byte orders)
with a bounded backoff (5 x 3s). InstantSend/ChainLock finality doesn't guarantee
the invitee's DAPI node has indexed the tx, so a freshly shared invitation could
fail on ordinary propagation lag with no retry.

#5: extract the post-fetch proof reconstruction into a pure `assemble_asset_lock_proof`
and unit-test its guards (txid mismatch, chainlock-required, chainlock-success,
islock-locks-wrong-tx) — previously zero coverage on funds-adjacent logic.

#6: `encode_invitation_uri` now rejects a final URI over `MAX_INVITATION_URI_LEN`
(percent-encoding can expand fields past the per-field raw cap) — the exact length
its own parser enforces, so it can't emit a self-unparseable link.

#7: correct the preview FFI `inviter_username` doc — a null username no longer
implies has_inviter==false (metadata-only links set has_inviter with a null username).

invitation tests: 28/28 (+4 assemble_*) platform-wallet, 10/10 ffi. fmt + clippy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants