[wallet_redesign] Modified insert_tx to use lowest checkpoint

Also updated the documentation.
This commit is contained in:
志宇 2023-05-28 15:57:46 +08:00
parent ac80829caa
commit a7668a2f3e
No known key found for this signature in database
GPG Key ID: F6345C9837C2BDE8

View File

@ -451,17 +451,20 @@ impl<D> Wallet<D> {
Ok(changed) Ok(changed)
} }
/// Add a transaction to the wallet's internal view of the chain. /// Add a transaction to the wallet's internal view of the chain. This stages but does not
/// This stages but does not [`commit`] the change. /// [`commit`] the change.
///
/// There are a number reasons `tx` could be rejected with an `Err(_)`. The most important one
/// is that the transaction is at a height that is greater than [`latest_checkpoint`]. Therefore
/// you should use [`insert_checkpoint`] to insert new checkpoints before manually inserting new
/// transactions.
/// ///
/// Returns whether anything changed with the transaction insertion (e.g. `false` if the /// Returns whether anything changed with the transaction insertion (e.g. `false` if the
/// transaction was already inserted at the same position). /// transaction was already inserted at the same position).
/// ///
/// A `tx` can be rejected if `position` has a height greater than the [`latest_checkpoint`].
/// Therefore you should use [`insert_checkpoint`] to insert new checkpoints before manually
/// inserting new transactions.
///
/// **WARNING:** If `position` is confirmed, we anchor the `tx` to a the lowest checkpoint that
/// is >= the `position`'s height. The caller is responsible for ensuring the `tx` exists in our
/// local view of the best chain's history.
///
/// [`commit`]: Self::commit /// [`commit`]: Self::commit
/// [`latest_checkpoint`]: Self::latest_checkpoint /// [`latest_checkpoint`]: Self::latest_checkpoint
/// [`insert_checkpoint`]: Self::insert_checkpoint /// [`insert_checkpoint`]: Self::insert_checkpoint
@ -473,25 +476,28 @@ impl<D> Wallet<D> {
where where
D: PersistBackend<ChangeSet>, D: PersistBackend<ChangeSet>,
{ {
let tip = self.chain.tip();
let (anchor, last_seen) = match position { let (anchor, last_seen) = match position {
ConfirmationTime::Confirmed { height, time } => { ConfirmationTime::Confirmed { height, time } => {
let tip_height = tip.map(|b| b.height); // anchor tx to checkpoint with lowest height that is >= position's height
if Some(height) > tip_height { let anchor = self
return Err(InsertTxError::ConfirmationHeightCannotBeGreaterThanTip { .chain
tip_height, .blocks()
.range(height..)
.next()
.ok_or(InsertTxError::ConfirmationHeightCannotBeGreaterThanTip {
tip_height: self.chain.tip().map(|b| b.height),
tx_height: height, tx_height: height,
}); })
} .map(|(&anchor_height, &anchor_hash)| ConfirmationTimeAnchor {
( anchor_block: BlockId {
Some(ConfirmationTimeAnchor { height: anchor_height,
anchor_block: tip.expect("already checked if tip_height > height"), hash: anchor_hash,
},
confirmation_height: height, confirmation_height: height,
confirmation_time: time, confirmation_time: time,
}), })?;
None,
) (Some(anchor), None)
} }
ConfirmationTime::Unconfirmed { last_seen } => (None, Some(last_seen)), ConfirmationTime::Unconfirmed { last_seen } => (None, Some(last_seen)),
}; };