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:
- If only
WalletWrite::create_accountis used, the resulting accounts will have sequential ZIP 32 account indices within each given seed. - If
WalletWrite::import_account_hdis used to import accounts with non-sequential ZIP 32 account indices from the same seed, a call toWalletWrite::create_accountwill use the ZIP 32 account index just after the highest-numbered existing account. - If an account is added to the wallet, and then a later call to one of the methods
would produce a UFVK that collides with that account on any FVK component (i.e.
Sapling, Orchard, or transparent), an error will be returned. This can occur in the
following cases:
- An account is created via
WalletWrite::create_accountwith an auto-selected ZIP 32 account index, and that index is later imported explicitly via eitherWalletWrite::import_account_ufvkorWalletWrite::import_account_hd. - An account is imported via
WalletWrite::import_account_ufvkorWalletWrite::import_account_hd, and then the ZIP 32 account index corresponding to that account’s UFVK is later imported either implicitly viaWalletWrite::create_account, or explicitly via a call toWalletWrite::import_account_ufvkorWalletWrite::import_account_hd.
- An account is created via
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:
- Generate a new BIP 39 mnemonic phrase, using a crate like
bip0039. - Derive the corresponding seed from the mnemonic phrase.
- Use
WalletWrite::create_accountwith the resulting seed.
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_hdonce 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, useWalletWrite::import_account_hdto create the accountindex_max + 1. WalletWrite::create_accountcan 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§
Required Methods§
Sourcefn 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 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.
Sourcefn 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_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.
Sourcefn 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 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.
Sourcefn delete_account(
&mut self,
account: <Self as WalletRead>::AccountId,
) -> Result<(), <Self as WalletRead>::Error>
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(orOvkPolicy::Customwith 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.
Sourcefn set_account_name(
&mut self,
account: <Self as WalletRead>::AccountId,
name: &str,
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn get_next_available_address(
&mut self,
account: <Self as WalletRead>::AccountId,
request: UnifiedAddressRequest,
) -> Result<Option<(UnifiedAddress, DiversifierIndex)>, <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>
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.
Sourcefn get_address_for_index(
&mut self,
account: <Self as WalletRead>::AccountId,
diversifier_index: DiversifierIndex,
request: UnifiedAddressRequest,
) -> Result<Option<UnifiedAddress>, <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>
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.
Sourcefn update_chain_tip(
&mut self,
tip_height: BlockHeight,
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn prune_scan_queue_below(
&mut self,
height: BlockHeight,
retain_with_priority: Option<ScanPriority>,
) -> Result<u64, <Self as WalletRead>::Error>
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.
Sourcefn queue_rescan(
&mut self,
range: Range<BlockHeight>,
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn put_blocks(
&mut self,
from_state: &ChainState,
blocks: Vec<ScannedBlock<<Self as WalletRead>::AccountId>>,
) -> 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>
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_statemust be the chain state for the block height prior to the first block inblocks.blocksmust be sequential, in order of increasing block height.
Sourcefn put_received_transparent_utxo(
&mut self,
output: &WalletTransparentOutput<<Self as WalletRead>::AccountId>,
) -> Result<Self::UtxoRef, <Self as WalletRead>::Error>
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.
Sourcefn store_decrypted_tx(
&mut self,
received_tx: DecryptedTransaction<'_, Transaction, <Self as WalletRead>::AccountId>,
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn set_tx_trust(
&mut self,
txid: TxId,
trusted: bool,
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn store_transactions_to_be_sent(
&mut self,
transactions: &[SentTransaction<'_, <Self as WalletRead>::AccountId>],
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn truncate_to_height(
&mut self,
max_height: BlockHeight,
) -> Result<BlockHeight, <Self as WalletRead>::Error>
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.
Sourcefn truncate_to_chain_state(
&mut self,
chain_state: ChainState,
) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn 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 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_birthdayshas its birthday metadata updated tochain_state.block_height() + 1(with corresponding tree sizes taken fromchain_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_birthdaysare 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_birthdaysis empty and every account in the wallet has a birthday greater thanchain_state.block_height() + 1(the value to which a reset birthday would be lowered), this method returnsRewindError::RewindBeyondBirthdaysand no other state is modified. So long as at least one account in the wallet already has a birthday at or belowchain_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 inreset_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.
Sourcefn set_transaction_status(
&mut self,
_txid: TxId,
_status: TransactionStatus,
) -> Result<(), <Self as WalletRead>::Error>
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§
Sourcefn 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.
fn import_standalone_transparent_address( &mut self, _account: <Self as WalletRead>::AccountId, _address: TransparentAddress, ) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn 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.
fn import_standalone_transparent_pubkey( &mut self, _account: <Self as WalletRead>::AccountId, _pubkey: PublicKey, ) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn 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.
fn import_standalone_transparent_pubkeys( &mut self, account: <Self as WalletRead>::AccountId, pubkeys: &[PublicKey], ) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn 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.
fn import_standalone_transparent_script( &mut self, _account: <Self as WalletRead>::AccountId, _script: Redeem, ) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn 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.
fn reserve_next_n_ephemeral_addresses( &mut self, _account_id: <Self as WalletRead>::AccountId, _n: usize, ) -> Result<Vec<(TransparentAddress, TransparentAddressMetadata)>, <Self as WalletRead>::Error>
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.
Sourcefn 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.
fn reserve_next_n_internal_addresses( &mut self, _account_id: <Self as WalletRead>::AccountId, _n: usize, ) -> Result<Vec<(TransparentAddress, TransparentAddressMetadata)>, <Self as WalletRead>::Error>
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.
Sourcefn schedule_next_check(
&mut self,
_address: &TransparentAddress,
_offset_seconds: u32,
) -> Result<Option<SystemTime>, <Self as WalletRead>::Error>
Available on crate feature transparent-inputs only.
fn schedule_next_check( &mut self, _address: &TransparentAddress, _offset_seconds: u32, ) -> Result<Option<SystemTime>, <Self as WalletRead>::Error>
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.
Sourcefn mark_transparent_addresses_exposed(
&mut self,
_exposures: &[(TransparentAddress, BlockHeight)],
) -> Result<(), <Self as WalletRead>::Error>
Available on crate feature transparent-inputs only.
fn mark_transparent_addresses_exposed( &mut self, _exposures: &[(TransparentAddress, BlockHeight)], ) -> Result<(), <Self as WalletRead>::Error>
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.
Sourcefn notify_address_checked(
&mut self,
_request: TransactionsInvolvingAddress,
_as_of_height: BlockHeight,
) -> Result<(), <Self as WalletRead>::Error>
Available on crate feature transparent-inputs only.
fn notify_address_checked( &mut self, _request: TransactionsInvolvingAddress, _as_of_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error>
transparent-inputs only.Notifies the wallet backend that the given query for transactions involving a particular address has completed evaluation.
§Arguments
request: theTransactionsInvolvingAddressrequest that was executed.as_of_height: The maximum height among blocks that were inspected in the process of performing the requested check.
Sourcefn notify_output_verified_unspent(
&mut self,
_outpoint: OutPoint,
_as_of_height: BlockHeight,
) -> Result<(), <Self as WalletRead>::Error>
Available on crate feature spend-index only.
fn notify_output_verified_unspent( &mut self, _outpoint: OutPoint, _as_of_height: BlockHeight, ) -> Result<(), <Self as WalletRead>::Error>
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.
impl WalletWrite for MockWalletDb
test-dependencies only.