Skip to main content

WalletWrite

Trait WalletWrite 

Source
pub trait WalletWrite: WalletRead + OutputLockStore<AccountId = <Self as WalletRead>::AccountId, Error = <Self as WalletRead>::Error> {
    type UtxoRef;

Show 29 methods // Required methods fn create_account( &mut self, account_name: &str, seed: &SecretVec<u8>, birthday: &AccountBirthday, key_source: Option<&str>, ) -> Result<(<Self as WalletRead>::AccountId, UnifiedSpendingKey), <Self as WalletRead>::Error>; fn import_account_hd( &mut self, account_name: &str, seed: &SecretVec<u8>, account_index: AccountId, birthday: &AccountBirthday, key_source: Option<&str>, ) -> Result<(Self::Account, UnifiedSpendingKey), <Self as WalletRead>::Error>; fn import_account_ufvk( &mut self, account_name: &str, unified_key: &UnifiedFullViewingKey, birthday: &AccountBirthday, purpose: AccountPurpose, key_source: Option<&str>, ) -> Result<Self::Account, <Self as WalletRead>::Error>; fn delete_account( &mut self, account: <Self as WalletRead>::AccountId, ) -> Result<(), <Self as WalletRead>::Error>; fn set_account_name( &mut self, account: <Self as WalletRead>::AccountId, name: &str, ) -> Result<(), <Self as WalletRead>::Error>; fn get_next_available_address( &mut self, account: <Self as WalletRead>::AccountId, request: UnifiedAddressRequest, ) -> Result<Option<(UnifiedAddress, DiversifierIndex)>, <Self as WalletRead>::Error>; fn get_address_for_index( &mut self, account: <Self as WalletRead>::AccountId, diversifier_index: DiversifierIndex, request: UnifiedAddressRequest, ) -> Result<Option<UnifiedAddress>, <Self as WalletRead>::Error>; fn update_chain_tip( &mut self, tip_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error>; fn prune_scan_queue_below( &mut self, height: BlockHeight, retain_with_priority: Option<ScanPriority>, ) -> Result<u64, <Self as WalletRead>::Error>; fn queue_rescan( &mut self, range: Range<BlockHeight>, ) -> Result<(), <Self as WalletRead>::Error>; fn put_blocks( &mut self, from_state: &ChainState, blocks: Vec<ScannedBlock<<Self as WalletRead>::AccountId>>, ) -> Result<(), <Self as WalletRead>::Error>; fn put_received_transparent_utxo( &mut self, output: &WalletTransparentOutput<<Self as WalletRead>::AccountId>, ) -> Result<Self::UtxoRef, <Self as WalletRead>::Error>; fn store_decrypted_tx( &mut self, received_tx: DecryptedTransaction<'_, Transaction, <Self as WalletRead>::AccountId>, ) -> Result<(), <Self as WalletRead>::Error>; fn set_tx_trust( &mut self, txid: TxId, trusted: bool, ) -> Result<(), <Self as WalletRead>::Error>; fn store_transactions_to_be_sent( &mut self, transactions: &[SentTransaction<'_, <Self as WalletRead>::AccountId>], ) -> Result<(), <Self as WalletRead>::Error>; fn truncate_to_height( &mut self, max_height: BlockHeight, ) -> Result<BlockHeight, <Self as WalletRead>::Error>; fn truncate_to_chain_state( &mut self, chain_state: ChainState, ) -> Result<(), <Self as WalletRead>::Error>; fn rewind_to_chain_state( &mut self, chain_state: ChainState, reset_account_birthdays: HashSet<<Self as WalletRead>::AccountId>, ) -> Result<(), RewindError<<Self as WalletRead>::AccountId, <Self as WalletRead>::Error>>; fn set_transaction_status( &mut self, _txid: TxId, _status: TransactionStatus, ) -> Result<(), <Self as WalletRead>::Error>; // Provided methods fn import_standalone_transparent_address( &mut self, _account: <Self as WalletRead>::AccountId, _address: TransparentAddress, ) -> Result<(), <Self as WalletRead>::Error> { ... } fn import_standalone_transparent_pubkey( &mut self, _account: <Self as WalletRead>::AccountId, _pubkey: PublicKey, ) -> Result<(), <Self as WalletRead>::Error> { ... } fn import_standalone_transparent_pubkeys( &mut self, account: <Self as WalletRead>::AccountId, pubkeys: &[PublicKey], ) -> Result<(), <Self as WalletRead>::Error> { ... } fn import_standalone_transparent_script( &mut self, _account: <Self as WalletRead>::AccountId, _script: Redeem, ) -> Result<(), <Self as WalletRead>::Error> { ... } fn reserve_next_n_ephemeral_addresses( &mut self, _account_id: <Self as WalletRead>::AccountId, _n: usize, ) -> Result<Vec<(TransparentAddress, TransparentAddressMetadata)>, <Self as WalletRead>::Error> { ... } fn reserve_next_n_internal_addresses( &mut self, _account_id: <Self as WalletRead>::AccountId, _n: usize, ) -> Result<Vec<(TransparentAddress, TransparentAddressMetadata)>, <Self as WalletRead>::Error> { ... } fn schedule_next_check( &mut self, _address: &TransparentAddress, _offset_seconds: u32, ) -> Result<Option<SystemTime>, <Self as WalletRead>::Error> { ... } fn mark_transparent_addresses_exposed( &mut self, _exposures: &[(TransparentAddress, BlockHeight)], ) -> Result<(), <Self as WalletRead>::Error> { ... } fn notify_address_checked( &mut self, _request: TransactionsInvolvingAddress, _as_of_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error> { ... } fn notify_output_verified_unspent( &mut self, _outpoint: OutPoint, _as_of_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error> { ... }
}
Expand description

This trait encapsulates the write capabilities required to update stored wallet data.

§Adding accounts

This trait provides several methods for adding accounts to the wallet data:

All of these methods take an AccountBirthday. The birthday height is defined as the minimum block height that will be scanned for funds belonging to the wallet. If birthday.height() is below the current chain tip, the account addition operation will trigger a re-scan of the blocks at and above the provided height.

The order in which you call these methods will affect the resulting wallet structure:

Note that an error will be returned on an FVK collision even if the UFVKs do not match exactly, e.g. if they have different subsets of components.

An account is treated as having a single root of spending authority that spans the shielded and transparent rules for the purpose of balance, transaction listing, and so forth. However, transparent keys imported via WalletWrite::import_standalone_transparent_pubkey or WalletWrite::import_standalone_transparent_script (available with the transparent-key-import feature) break this abstraction slightly, so wallets using this API need to be cautious to enforce the invariant that the wallet either maintains access to the keys required to spend ALL outputs received by the account, or that it DOES NOT offer any spending capability for the account, i.e. the account is treated as view-only for all user-facing operations.

A future change to this trait might introduce a method to “upgrade” an imported account with derivation information. See zcash/librustzcash#1284 for details.

Users of the WalletWrite trait should generally distinguish in their APIs and wallet UIs between creating a new account, and importing an account that previously existed. By convention, wallets should only allow a new account to be generated for a seed after confirmed funds have been received by the newest existing account for that seed; this allows automated account recovery to discover and recover all funds within a particular seed.

§Creating a new wallet

To create a new wallet:

Callers should construct the AccountBirthday using AccountBirthday::from_treestate for the block at height chain_tip_height - 100. Setting the birthday height to a tree state below the pruning depth ensures that reorgs cannot cause funds intended for the wallet to be missed; otherwise, if the chain tip height were used for the wallet birthday, a transaction targeted at a height greater than the chain tip could be mined at a height below that tip as part of a reorg.

§Restoring a wallet from backup

To restore a backed-up wallet:

  • Derive the seed from its BIP 39 mnemonic phrase.
  • Use WalletWrite::import_account_hd once for each ZIP 32 account index that the user wants to restore.
  • If the highest previously-used ZIP 32 account index was not restored by the user, remember this index separately as index_max. The first time the user wants to generate a new account, use WalletWrite::import_account_hd to create the account index_max + 1.
  • WalletWrite::create_account can be used to generate subsequent new accounts in the restored wallet.

Automated account recovery has not yet been implemented by this crate. A wallet app that supports multiple accounts can implement it manually by tracking account balances relative to WalletSummary::fully_scanned_height, and creating new accounts as funds appear in existing accounts.

If the number of accounts is known in advance, the wallet should create all accounts before scanning the chain so that the scan can be done in a single pass for all accounts.

Required Associated Types§

Source

type UtxoRef

The type of identifiers used to look up transparent UTXOs.

Required Methods§

Source

fn create_account( &mut self, account_name: &str, seed: &SecretVec<u8>, birthday: &AccountBirthday, key_source: Option<&str>, ) -> Result<(<Self as WalletRead>::AccountId, UnifiedSpendingKey), <Self as WalletRead>::Error>

Tells the wallet to track the next available account-level spend authority for the provided seed value, given the current set of ZIP 316 account identifiers known to the wallet database.

The “next available account” is defined as the ZIP-32 account index immediately following the highest existing account index among all accounts in the wallet that share the given seed. Users of the WalletWrite trait that only call this method are guaranteed to have accounts with sequential indices.

Returns the account identifier for the newly-created wallet database entry, along with the associated UnifiedSpendingKey. Note that the unique account identifier should not be assumed equivalent to the ZIP 32 account index. It is an opaque identifier for a pool of funds or set of outputs controlled by a single spending authority.

The ZIP-32 account index may be obtained by calling WalletRead::get_account with the returned account identifier.

The WalletWrite trait documentation has more details about account creation and import.

§Arguments
  • account_name: A human-readable name for the account.
  • seed: The 256-byte (at least) HD seed from which to derive the account UFVK.
  • birthday: Metadata about where to start scanning blocks to find transactions intended for the account.
  • key_source: A string identifier or other metadata describing the source of the seed. This is treated as opaque metadata by the wallet backend; it is provided for use by applications which need to track additional identifying information for an account.
§Implementation notes

Implementations of this method MUST NOT “fill in gaps” by selecting an account index that is lower than any existing account index among all accounts in the wallet that share the given seed.

§Panics

Panics if the length of the seed is not between 32 and 252 bytes inclusive.

Source

fn import_account_hd( &mut self, account_name: &str, seed: &SecretVec<u8>, account_index: AccountId, birthday: &AccountBirthday, key_source: Option<&str>, ) -> Result<(Self::Account, UnifiedSpendingKey), <Self as WalletRead>::Error>

Tells the wallet to track a specific account index for a given seed.

Returns details about the imported account, including the unique account identifier for the newly-created wallet database entry, along with the associated UnifiedSpendingKey. Note that the unique account identifier should not be assumed equivalent to the ZIP 32 account index. It is an opaque identifier for a pool of funds or set of outputs controlled by a single spending authority.

Import accounts with indices that are exactly one greater than the highest existing account index to ensure account indices are contiguous, thereby facilitating automated account recovery.

The WalletWrite trait documentation has more details about account creation and import.

§Arguments
  • account_name: A human-readable name for the account.
  • seed: The 256-byte (at least) HD seed from which to derive the account UFVK.
  • account_index: The ZIP 32 account-level component of the HD derivation path at which to derive the account’s UFVK.
  • birthday: Metadata about where to start scanning blocks to find transactions intended for the account.
  • key_source: A string identifier or other metadata describing the source of the seed. This is treated as opaque metadata by the wallet backend; it is provided for use by applications which need to track additional identifying information for an account.
§Panics

Panics if the length of the seed is not between 32 and 252 bytes inclusive.

Source

fn import_account_ufvk( &mut self, account_name: &str, unified_key: &UnifiedFullViewingKey, birthday: &AccountBirthday, purpose: AccountPurpose, key_source: Option<&str>, ) -> Result<Self::Account, <Self as WalletRead>::Error>

Tells the wallet to track an account using a unified full viewing key.

Returns details about the imported account, including the unique account identifier for the newly-created wallet database entry. Unlike the other account creation APIs (Self::create_account and Self::import_account_hd), no spending key is returned because the wallet has no information about how the UFVK was derived.

Certain optimizations are possible for accounts which will never be used to spend funds. If spending_key_available is false, the wallet may choose to optimize for this case, in which case any attempt to spend funds from the account will result in an error.

The WalletWrite trait documentation has more details about account creation and import.

§Arguments
  • account_name: A human-readable name for the account.
  • unified_key: The UFVK used to detect transactions involving the account.
  • birthday: Metadata about where to start scanning blocks to find transactions intended for the account.
  • purpose: Metadata describing whether or not data required for spending should be tracked by the wallet.
  • key_source: A string identifier or other metadata describing the source of the seed. This is treated as opaque metadata by the wallet backend; it is provided for use by applications which need to track additional identifying information for an account.
Source

fn delete_account( &mut self, account: <Self as WalletRead>::AccountId, ) -> Result<(), <Self as WalletRead>::Error>

Deletes the specified account, and all transactions that exclusively involve it, from the wallet database.

WARNING: This is a destructive operation and may result in the permanent loss of potentially important information that is not recoverable from chain data, including:

  • Data about transactions sent by the account for which OvkPolicy::Discard (or OvkPolicy::Custom with random OVKs) was used;
  • Data related to transactions that the account attempted to send that expired or were otherwise invalidated without having been mined in the main chain;
  • Data related to transactions that were observed in the mempool as having inputs or outputs that involved the account, but that were never mined in the main chain;
  • Data related to transactions that were received by the wallet in a mined block, where that block was later un-mined in a chain reorg and the transaction was either invalidated or was never re-mined.
Source

fn set_account_name( &mut self, account: <Self as WalletRead>::AccountId, name: &str, ) -> Result<(), <Self as WalletRead>::Error>

Sets the human-readable name of the specified account, replacing any existing name.

Only the account’s name is changed; its keys, birthday, and all other wallet state are left unchanged. The new name is subsequently returned by Account::name.

Account names carry no uniqueness guarantee: the wallet does not reject a name that is already used by another account. Applications that require distinct names must enforce that themselves.

Returns an error if the specified account is not known to the wallet.

Source

fn get_next_available_address( &mut self, account: <Self as WalletRead>::AccountId, request: UnifiedAddressRequest, ) -> Result<Option<(UnifiedAddress, DiversifierIndex)>, <Self as WalletRead>::Error>

Generates, persists, and marks as exposed the next available diversified address for the specified account, given the current addresses known to the wallet.

Returns Ok(None) if the account identifier does not correspond to a known account.

Source

fn get_address_for_index( &mut self, account: <Self as WalletRead>::AccountId, diversifier_index: DiversifierIndex, request: UnifiedAddressRequest, ) -> Result<Option<UnifiedAddress>, <Self as WalletRead>::Error>

Generates, persists, and marks as exposed a diversified address for the specified account at the provided diversifier index.

Returns Ok(None) in the case that it is not possible to generate an address conforming to the provided request at the specified diversifier index. Such a result might arise from the diversifier index not being valid for a ReceiverRequirement::Require’ed receiver. Some implementations of this trait may return Err(_) in some cases to expose more information, which is only accessible in a backend-specific context.

Address generation should fail if an address has already been exposed for the given diversifier index and the given request produced an address having different receivers than what was originally exposed.

§WARNINGS

If an address generated using this method has a transparent receiver and the chosen diversifier index would be outside the wallet’s internally-configured gap limit, funds sent to these address are likely to not be discovered on recovery from seed. It up to the caller of this method to either ensure that they only request transparent receivers with indices within the range of a reasonable gap limit, or that they ensure that their wallet provides backup facilities that can be used to ensure that funds sent to such addresses are recoverable after a loss of wallet data.

Source

fn update_chain_tip( &mut self, tip_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error>

Updates the wallet’s view of the blockchain.

This method is used to provide the wallet with information about the state of the blockchain, and detect any previously scanned data that needs to be re-validated before proceeding with scanning. It should be called at wallet startup prior to calling WalletRead::suggest_scan_ranges in order to provide the wallet with the information it needs to correctly prioritize scanning operations.

Source

fn prune_scan_queue_below( &mut self, height: BlockHeight, retain_with_priority: Option<ScanPriority>, ) -> Result<u64, <Self as WalletRead>::Error>

Drops the scan work queued below height, except where retained by retain_with_priority. Returns the number of queue entries removed or altered.

If retain_with_priority is None, no entries below height are retained, irrespective of their priority. If it is Some(priority), entries with that priority and greater are retained (left untouched, even where they straddle height), as are entries with the bookkeeping priorities ScanPriority::Scanned and ScanPriority::Ignored — those record which regions of the chain the backend has already covered or deliberately skips, and removing them would cause the backend to forget coverage state it maintains itself (use the None form when that full reset is the intent). Entries with priorities between the bookkeeping ones and the retained threshold are pruned.

Pruning must not leave a gap in the queue’s coverage: implementations are required to preserve contiguity across whatever remains below height, which in general means demoting pruned ranges to ScanPriority::Ignored rather than deleting them outright. Only coverage below the lowest retained entry may be deleted, since that merely raises the floor of the queue. A caller may therefore observe that the total span of the queue is unchanged and that the pruned region is now Ignored.

This is a queue-hygiene operation. The primary use case is discarding historic scan ranges that no remaining account justifies: WalletWrite::delete_account does not modify the scan queue, so the deep ranges queued for a since-deleted account’s birthday would otherwise still be scanned even though no remaining account can have notes below its own birthday. In that case, pass the wallet birthday (WalletRead::get_wallet_birthday) as height and retain ScanPriority::OpenAdjacent and greater — the priorities that may legitimately reach below the wallet birthday in service of note witnesses.

Source

fn queue_rescan( &mut self, range: Range<BlockHeight>, ) -> Result<(), <Self as WalletRead>::Error>

Queues range to be scanned again, overriding the record of any part of it that has already been scanned.

The range is queued at ScanPriority::Historic, so it is scanned only once no higher-priority work remains. Queue entries within range whose priority exceeds ScanPriority::Historic are left as they are, since they already require the blocks they cover to be scanned at least as urgently; entries recording the range as ScanPriority::Scanned or ScanPriority::Ignored are overridden.

This destroys nothing: no block, transaction, note, note commitment tree state, or witness is removed, and no account birthday is altered. It records only that the blocks in range must be processed again. Re-scanning a block that was already scanned is idempotent with respect to the wallet’s contents.

Scanning is performed against every account’s viewing keys, so this re-scans range for the whole wallet.

Neither end of range is clamped; it is queued exactly as given. Below the wallet’s birthday, blocks that no account can hold notes in are queued and scanned to no effect. Above the wallet’s view of the chain tip, a ScanPriority::Historic entry is left covering heights that do not yet exist, and WalletRead::suggest_scan_ranges will offer it. Neither case is destructive, and the second self-corrects as the chain grows into the queued heights. A caller that wants neither should clamp range itself, against WalletRead::get_wallet_birthday and WalletRead::chain_height.

An empty range queues nothing and is not an error.

In contrast to truncate_to_chain_state and rewind_to_chain_state, this does not require a ChainState: a range that re-enters the queue is scanned from a frontier supplied at scan time, so the wallet needs no note commitment tree state at the range’s start in order to queue it.

Source

fn put_blocks( &mut self, from_state: &ChainState, blocks: Vec<ScannedBlock<<Self as WalletRead>::AccountId>>, ) -> Result<(), <Self as WalletRead>::Error>

Updates the state of the wallet database by persisting the provided block information, along with the note commitments that were detected when scanning the block for transactions pertaining to this wallet.

Each scanned transaction’s shielded outputs and transparent outputs that pay a wallet account are recorded as received. Outputs the wallet sent to an external recipient are not; those are recorded when complete transaction data reaches wallet::decrypt_and_store_transaction.

The operation is atomic: implementations must apply the whole batch or none of it. After an error the caller may assume that no part of any block in blocks was persisted, and that the call may be retried.

§Arguments
  • from_state must be the chain state for the block height prior to the first block in blocks.
  • blocks must be sequential, in order of increasing block height.
Source

fn put_received_transparent_utxo( &mut self, output: &WalletTransparentOutput<<Self as WalletRead>::AccountId>, ) -> Result<Self::UtxoRef, <Self as WalletRead>::Error>

Adds a transparent UTXO received by the wallet to the data store.

Source

fn store_decrypted_tx( &mut self, received_tx: DecryptedTransaction<'_, Transaction, <Self as WalletRead>::AccountId>, ) -> Result<(), <Self as WalletRead>::Error>

Caches a decrypted transaction in the persistent wallet store.

Source

fn set_tx_trust( &mut self, txid: TxId, trusted: bool, ) -> Result<(), <Self as WalletRead>::Error>

Sets the trust status of the given transaction to either trusted or untrusted.

The outputs of a trusted transaction will be available for spending with ConfirmationsPolicy::trusted confirmations even if the output is not wallet-internal.

Source

fn store_transactions_to_be_sent( &mut self, transactions: &[SentTransaction<'_, <Self as WalletRead>::AccountId>], ) -> Result<(), <Self as WalletRead>::Error>

Saves information about transactions constructed by the wallet to the persistent wallet store.

This must be called before the transactions are sent to the network.

Transactions that have been stored by this method should be retransmitted while it is still possible that they could be mined.

Implementations must unlock any locked outputs that are recorded as spent by the stored transactions. Once spend records exist, the outputs are protected from double-selection by the spend tracking mechanism, so the explicit locks are no longer needed.

Implementations must be idempotent: storing a transaction the wallet has already recorded replaces that record rather than failing, so that a caller which stores a transaction and then dies before transmitting it can store the same transaction again when it resumes.

Source

fn truncate_to_height( &mut self, max_height: BlockHeight, ) -> Result<BlockHeight, <Self as WalletRead>::Error>

Truncates the wallet database to at most the specified height.

Implementations of this method may choose a lower block height to which the data store will be truncated if it is not possible to truncate exactly to the specified height. Upon successful truncation, this method returns the height to which the data store was actually truncated.

This method assumes that the state of the underlying data store is consistent up to a particular block height. Since it is possible that a chain reorg might invalidate some stored state, this method must be implemented in order to allow users of this API to “reset” the data store to correctly represent chainstate as of at most the requested block height.

After calling this method, the block at the returned height will be the most recent block and all other operations will treat this block as the chain tip for balance determination purposes.

There may be restrictions on heights to which it is possible to truncate. Specifically, it will only be possible to truncate to heights at which is is possible to create a witness given the current state of the wallet’s note commitment tree.

Source

fn truncate_to_chain_state( &mut self, chain_state: ChainState, ) -> Result<(), <Self as WalletRead>::Error>

Truncates the wallet database to the specified chain state.

In contrast to truncate_to_height, this method allows the caller to truncate the wallet database to a precise height by providing additional chain state information needed for note commitment tree maintenance after the truncation.

Source

fn rewind_to_chain_state( &mut self, chain_state: ChainState, reset_account_birthdays: HashSet<<Self as WalletRead>::AccountId>, ) -> Result<(), RewindError<<Self as WalletRead>::AccountId, <Self as WalletRead>::Error>>

Rewinds the wallet to the specified chain state, preserving wallet data which has been confirmed beyond the pruning depth, and lowering the birthday height of selected accounts to the block following the chain state.

In contrast to truncate_to_chain_state, which unconditionally removes wallet state above chain_state.block_height(), this rewinds the scan queue to the target height but only rewinds blocks, note commitment trees, transactions, transparent UTXO observations, and nullifier-map entries as far back as the implementation’s pruning floor; data at or below that floor is preserved.

reset_account_birthdays selects which accounts (if any) may have their birthday metadata lowered as a result of this rewind. The semantics are:

  • Every account in reset_account_birthdays has its birthday metadata updated to chain_state.block_height() + 1 (with corresponding tree sizes taken from chain_state) if and only if the new birthday is less than the account’s existing birthday. Existing birthdays are never raised by this method.
  • Accounts that are not in reset_account_birthdays are never modified, regardless of the rewind target. Note that this only governs per-account birthday metadata: rescanning of blocks that re-enter the scan queue applies to all accounts in the wallet, since scanning is performed against all viewing keys.
  • If reset_account_birthdays is empty and every account in the wallet has a birthday greater than chain_state.block_height() + 1 (the value to which a reset birthday would be lowered), this method returns RewindError::RewindBeyondBirthdays and no other state is modified. So long as at least one account in the wallet already has a birthday at or below chain_state.block_height() + 1, this error is not returned — such an account already provides the wallet with an anchor at or below the new birthday floor, so no reset is required. The reported map contains every account in the wallet along with its existing birthday height; the caller may re-invoke the method with any subset of those accounts included in reset_account_birthdays.

Implementations may also return an Err (typically via RewindError::DataSource) if reset_account_birthdays contains identifiers that do not correspond to accounts in the wallet.

Source

fn set_transaction_status( &mut self, _txid: TxId, _status: TransactionStatus, ) -> Result<(), <Self as WalletRead>::Error>

Updates the wallet backend with respect to the status of a specific transaction, from the perspective of the main chain.

Fully transparent transactions, and transactions that do not contain either shielded inputs or shielded outputs belonging to the wallet, may not be discovered by the process of chain scanning; as a consequence, the wallet must actively query to determine whether such transactions have been mined.

Provided Methods§

Source

fn import_standalone_transparent_address( &mut self, _account: <Self as WalletRead>::AccountId, _address: TransparentAddress, ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature transparent-key-import only.

Imports the given transparent address into the account as a watch-only address, without any associated key material.

The imported address will contribute to the balance of the account, but the wallet holds neither the public key (P2PKH) nor the redeem script (P2SH) from which the address was derived, so funds received by it cannot be spent — its outputs are excluded from spendable input selection, and it must not be included in the addresses passed to propose_shielding. Subsequently importing the corresponding key material with import_standalone_transparent_pubkey or import_standalone_transparent_script upgrades the address in place, after which the spending limitations of those methods apply instead.

Source

fn import_standalone_transparent_pubkey( &mut self, _account: <Self as WalletRead>::AccountId, _pubkey: PublicKey, ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature transparent-key-import only.

Imports the given pubkey into the account without key derivation information, and adds the associated transparent p2pkh address.

The imported address will contribute to the balance of the account (for UFVK-based accounts), but spending funds held by this address requires the associated spending keys to be provided explicitly when calling create_proposed_transactions. By extension, calls to propose_shielding must only include addresses for which the spending application holds or can obtain the spending keys.

Source

fn import_standalone_transparent_pubkeys( &mut self, account: <Self as WalletRead>::AccountId, pubkeys: &[PublicKey], ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature transparent-key-import only.

Imports a batch of standalone transparent pubkeys into the account, adding the associated transparent p2pkh addresses. See import_standalone_transparent_pubkey for the semantics and spending limitations that apply to each imported pubkey.

This is equivalent to calling import_standalone_transparent_pubkey once per pubkey, but implementations may validate the target account a single time for the whole batch. The default implementation calls import_standalone_transparent_pubkey for each pubkey; a pubkey whose receiver address is already known to the wallet is skipped.

Source

fn import_standalone_transparent_script( &mut self, _account: <Self as WalletRead>::AccountId, _script: Redeem, ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature transparent-key-import only.

Imports the given redeem script into the account without key derivation information, and adds the associated transparent p2sh address.

The imported address will contribute to the balance of the account (for UFVK-based accounts), but spending funds held by this address requires the associated spending keys to be provided explicitly when calling create_proposed_transactions. By extension, calls to propose_shielding must only include addresses for which the spending application holds or can obtain the spending keys.

§Spending limitations

P2PKH-in-P2SH scripts are unsupported by PCZT at this time, so the only way to spend from such an address is to use the create_proposed_transactions signing path.

Source

fn reserve_next_n_ephemeral_addresses( &mut self, _account_id: <Self as WalletRead>::AccountId, _n: usize, ) -> Result<Vec<(TransparentAddress, TransparentAddressMetadata)>, <Self as WalletRead>::Error>

Available on crate feature transparent-inputs only.

Reserves the next n available ephemeral addresses for the given account. This cannot be undone, so as far as possible, errors associated with transaction construction should have been reported before calling this method.

To ensure that sufficient information is stored on-chain to allow recovering funds sent back to any of the used addresses, a “gap limit” of 20 addresses should be observed as described in BIP 44.

Returns an error if there is insufficient space within the gap limit to allocate the given number of addresses, or if the account identifier does not correspond to a known account.

Source

fn reserve_next_n_internal_addresses( &mut self, _account_id: <Self as WalletRead>::AccountId, _n: usize, ) -> Result<Vec<(TransparentAddress, TransparentAddressMetadata)>, <Self as WalletRead>::Error>

Available on crate feature transparent-inputs only.

Reserves the next n available internal-scope (change) transparent addresses for the given account, as described in BIP 44 under the change path level. This cannot be undone, so as far as possible, errors associated with transaction construction should have been reported before calling this method.

Internal-scope transparent addresses are used to receive change for transactions having fully-transparent value flows, when the change strategy in use is configured with TransparentChangePolicy::TransparentChangeAllowed.

To ensure that funds sent to internal-scope addresses are recoverable, implementations of this method should observe a gap limit as described in BIP 44; change addresses receive funds immediately upon reservation, so a smaller gap limit than the one used for external addresses may be observed.

Returns an error if there is insufficient space within the gap limit to allocate the given number of addresses, or if the account identifier does not correspond to a known account.

Source

fn schedule_next_check( &mut self, _address: &TransparentAddress, _offset_seconds: u32, ) -> Result<Option<SystemTime>, <Self as WalletRead>::Error>

Available on crate feature transparent-inputs only.

Schedules a UTXO check for the given address at a random time that has an expected value of offset_seconds from the current system time.

Returns the time at which the check has been scheduled, or None if the address is not being tracked by the wallet.

Source

fn mark_transparent_addresses_exposed( &mut self, _exposures: &[(TransparentAddress, BlockHeight)], ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature transparent-inputs only.

Informs the wallet backend that the given transparent addresses are known to have been exposed externally at or before the block height paired with each address.

This method is intended for use when a wallet has learned, through means outside the observation of the chain by this backend, that addresses under the wallet’s control have been disclosed to an external party. Calling this method ensures that the wallet’s exposure metadata accounts for the earlier disclosures.

If the wallet already tracks an earlier exposure for an address, the earlier height is retained.

The operation is atomic: if any address in exposures is not known to the wallet, implementations must roll back all updates performed during the call and return an implementation-defined error identifying the first unrecognized address. Passing an empty slice is a no-op.

Source

fn notify_address_checked( &mut self, _request: TransactionsInvolvingAddress, _as_of_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature transparent-inputs only.

Notifies the wallet backend that the given query for transactions involving a particular address has completed evaluation.

§Arguments
  • request: the TransactionsInvolvingAddress request that was executed.
  • as_of_height: The maximum height among blocks that were inspected in the process of performing the requested check.
Source

fn notify_output_verified_unspent( &mut self, _outpoint: OutPoint, _as_of_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error>

Available on crate feature spend-index only.

Notifies the wallet backend that a specific transparent output was confirmed unspent as of the given height, in response to a TransactionDataRequest::GetSpendingTx request.

§Arguments
  • outpoint: the transparent outpoint whose spend status was checked.
  • as_of_height: the maximum height among blocks that were inspected, and through which the outpoint is confirmed to remain unspent.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl WalletWrite for MockWalletDb

Available on crate features test-dependencies only.