@@ -451,17 +451,20 @@ impl<D> Wallet<D> {
451451 Ok ( changed)
452452 }
453453
454- /// Add a transaction to the wallet's internal view of the chain.
455- /// This stages but does not [`commit`] the change.
456- ///
457- /// There are a number reasons `tx` could be rejected with an `Err(_)`. The most important one
458- /// is that the transaction is at a height that is greater than [`latest_checkpoint`]. Therefore
459- /// you should use [`insert_checkpoint`] to insert new checkpoints before manually inserting new
460- /// transactions.
454+ /// Add a transaction to the wallet's internal view of the chain. This stages but does not
455+ /// [`commit`] the change.
461456 ///
462457 /// Returns whether anything changed with the transaction insertion (e.g. `false` if the
463458 /// transaction was already inserted at the same position).
464459 ///
460+ /// A `tx` can be rejected if `position` has a height greater than the [`latest_checkpoint`].
461+ /// Therefore you should use [`insert_checkpoint`] to insert new checkpoints before manually
462+ /// inserting new transactions.
463+ ///
464+ /// **WARNING:** If `position` is confirmed, we anchor the `tx` to a the lowest checkpoint that
465+ /// is >= the `position`'s height. The caller is responsible for ensuring the `tx` exists in our
466+ /// local view of the best chain's history.
467+ ///
465468 /// [`commit`]: Self::commit
466469 /// [`latest_checkpoint`]: Self::latest_checkpoint
467470 /// [`insert_checkpoint`]: Self::insert_checkpoint
@@ -473,25 +476,28 @@ impl<D> Wallet<D> {
473476 where
474477 D : PersistBackend < ChangeSet > ,
475478 {
476- let tip = self . chain . tip ( ) ;
477-
478479 let ( anchor, last_seen) = match position {
479480 ConfirmationTime :: Confirmed { height, time } => {
480- let tip_height = tip. map ( |b| b. height ) ;
481- if Some ( height) > tip_height {
482- return Err ( InsertTxError :: ConfirmationHeightCannotBeGreaterThanTip {
483- tip_height,
481+ // anchor tx to checkpoint with lowest height that is >= position's height
482+ let anchor = self
483+ . chain
484+ . blocks ( )
485+ . range ( height..)
486+ . next ( )
487+ . ok_or ( InsertTxError :: ConfirmationHeightCannotBeGreaterThanTip {
488+ tip_height : self . chain . tip ( ) . map ( |b| b. height ) ,
484489 tx_height : height,
485- } ) ;
486- }
487- (
488- Some ( ConfirmationTimeAnchor {
489- anchor_block : tip. expect ( "already checked if tip_height > height" ) ,
490+ } )
491+ . map ( |( & anchor_height, & anchor_hash) | ConfirmationTimeAnchor {
492+ anchor_block : BlockId {
493+ height : anchor_height,
494+ hash : anchor_hash,
495+ } ,
490496 confirmation_height : height,
491497 confirmation_time : time,
492- } ) ,
493- None ,
494- )
498+ } ) ? ;
499+
500+ ( Some ( anchor ) , None )
495501 }
496502 ConfirmationTime :: Unconfirmed { last_seen } => ( None , Some ( last_seen) ) ,
497503 } ;
0 commit comments