@@ -61,15 +61,27 @@ func (bl *blockListener) reconcileConfirmationsForTransaction(ctx context.Contex
6161func (bl * blockListener ) compareAndUpdateConfirmationQueue (ctx context.Context , reconcileResult * ffcapi.ConfirmationMapUpdateResult , txBlockInfo * ffcapi.MinimalBlockInfo , targetConfirmationCount uint64 ) (* ffcapi.ConfirmationMapUpdateResult , error ) {
6262 var err error
6363 // Build new confirmations from the canonical chain and get existing confirmations
64- newConfirmationsWithoutTxBlock , existingConfirmations , returnResult := bl .buildConfirmationQueueUsingCanonicalChain (ctx , reconcileResult , txBlockInfo , targetConfirmationCount )
64+ newConfirmationsWithoutTxBlock , lastValidatedBlock , returnResult := bl .buildConfirmationQueueUsingCanonicalChain (ctx , reconcileResult , txBlockInfo , targetConfirmationCount )
6565 if returnResult {
6666 return reconcileResult , nil
6767 }
6868
69+ // Initialize confirmation map and get existing confirmations
70+ // the init must happen after the canonical chain check to avoid
71+ // confirming blocks that are not yet validated in the canonical chain
72+ existingConfirmations := bl .initializeConfirmationMap (reconcileResult , txBlockInfo )
73+
74+ // Special case: if targetConfirmationCount is 0, transaction is immediately confirmed
75+ if targetConfirmationCount == 0 {
76+ reconcileResult .Confirmed = true
77+ reconcileResult .Confirmations = []* ffcapi.MinimalBlockInfo {txBlockInfo }
78+ return reconcileResult , nil
79+ }
80+
6981 // Validate existing confirmations and fill gaps in the confirmation queue
7082 var confirmations []* ffcapi.MinimalBlockInfo
7183 var newFork bool
72- confirmations , newFork , err = bl .checkAndFillInGap (ctx , newConfirmationsWithoutTxBlock , existingConfirmations , txBlockInfo , targetConfirmationCount )
84+ confirmations , newFork , err = bl .checkAndFillInGap (ctx , newConfirmationsWithoutTxBlock , existingConfirmations , txBlockInfo , targetConfirmationCount , lastValidatedBlock )
7385 if err != nil {
7486 return reconcileResult , err
7587 }
@@ -81,7 +93,7 @@ func (bl *blockListener) compareAndUpdateConfirmationQueue(ctx context.Context,
8193// buildConfirmationQueueUsingCanonicalChain builds the confirmation queue using the in-memory canonical chain.
8294// It does not modify the canonical chain itself, only reads from it.
8395// This function holds a read lock on the canonical chain, so it should not make long-running queries.
84- func (bl * blockListener ) buildConfirmationQueueUsingCanonicalChain (ctx context.Context , reconcileResult * ffcapi.ConfirmationMapUpdateResult , txBlockInfo * ffcapi.MinimalBlockInfo , targetConfirmationCount uint64 ) (newConfirmationsWithoutTxBlock []* ffcapi.MinimalBlockInfo , existingConfirmations [] * ffcapi.MinimalBlockInfo , returnResult bool ) {
96+ func (bl * blockListener ) buildConfirmationQueueUsingCanonicalChain (ctx context.Context , reconcileResult * ffcapi.ConfirmationMapUpdateResult , txBlockInfo * ffcapi.MinimalBlockInfo , targetConfirmationCount uint64 ) (newConfirmationsWithoutTxBlock []* ffcapi.MinimalBlockInfo , lastValidatedBlock * ffcapi.MinimalBlockInfo , returnResult bool ) {
8597 bl .mux .RLock ()
8698 defer bl .mux .RUnlock ()
8799 txBlockNumber := txBlockInfo .BlockNumber .Uint64 ()
@@ -94,16 +106,6 @@ func (bl *blockListener) buildConfirmationQueueUsingCanonicalChain(ctx context.C
94106 return nil , nil , true
95107 }
96108
97- // Initialize confirmation map and get existing confirmations
98- existingConfirmations = bl .initializeConfirmationMap (reconcileResult , txBlockInfo )
99-
100- // Special case: if targetConfirmationCount is 0, transaction is immediately confirmed
101- if targetConfirmationCount == 0 {
102- reconcileResult .Confirmed = true
103- reconcileResult .Confirmations = []* ffcapi.MinimalBlockInfo {txBlockInfo }
104- return nil , existingConfirmations , true
105- }
106-
107109 // Build new confirmations from blocks after the transaction block
108110
109111 newConfirmationsWithoutTxBlock = []* ffcapi.MinimalBlockInfo {}
@@ -114,6 +116,12 @@ func (bl *blockListener) buildConfirmationQueueUsingCanonicalChain(ctx context.C
114116 // If we've reached the target confirmation count, mark as confirmed
115117 if currentBlockInfo .BlockNumber .Uint64 () > targetBlockNumber {
116118 reconcileResult .Confirmed = true
119+ // if the canonical chain contains the next block after the target block number,
120+ // and the new confirmations queue is empty,
121+ // we set the last validated block to the next block, so the downstream function can use it validate blocks before it
122+ if len (newConfirmationsWithoutTxBlock ) == 0 && currentBlockInfo .BlockNumber .Uint64 () == targetBlockNumber + 1 {
123+ lastValidatedBlock = currentBlockInfo
124+ }
117125 break
118126 }
119127
@@ -131,7 +139,7 @@ func (bl *blockListener) buildConfirmationQueueUsingCanonicalChain(ctx context.C
131139 })
132140 currentBlock = currentBlock .Next ()
133141 }
134- return newConfirmationsWithoutTxBlock , existingConfirmations , false
142+ return newConfirmationsWithoutTxBlock , lastValidatedBlock , false
135143}
136144
137145// initializeConfirmationMap initializes the confirmation map with the transaction block
@@ -162,7 +170,7 @@ func (bl *blockListener) initializeConfirmationMap(reconcileResult *ffcapi.Confi
162170// checkAndFillInGap validates existing confirmations, detects forks, and fills gaps
163171// in the confirmation queue using existing confirmations or fetching missing blocks from the blockchain.
164172// It ensures the confirmation chain is valid and connected to the transaction block.
165- func (bl * blockListener ) checkAndFillInGap (ctx context.Context , newConfirmationsWithoutTxBlock []* ffcapi.MinimalBlockInfo , existingConfirmations []* ffcapi.MinimalBlockInfo , txBlockInfo * ffcapi.MinimalBlockInfo , targetConfirmationCount uint64 ) ([]* ffcapi.MinimalBlockInfo , bool , error ) {
173+ func (bl * blockListener ) checkAndFillInGap (ctx context.Context , newConfirmationsWithoutTxBlock []* ffcapi.MinimalBlockInfo , existingConfirmations []* ffcapi.MinimalBlockInfo , txBlockInfo * ffcapi.MinimalBlockInfo , targetConfirmationCount uint64 , lastValidatedBlock * ffcapi. MinimalBlockInfo ) ([]* ffcapi.MinimalBlockInfo , bool , error ) {
166174 var hasNewFork bool
167175
168176 // Detect forks by comparing new confirmations with existing ones
@@ -180,7 +188,6 @@ func (bl *blockListener) checkAndFillInGap(ctx context.Context, newConfirmations
180188
181189 // Determine the range of blocks to validate and fill gaps
182190 blockNumberToReach := txBlockInfo .BlockNumber .Uint64 () + targetConfirmationCount
183- var lastValidatedBlock * ffcapi.MinimalBlockInfo
184191 if len (newConfirmationsWithoutTxBlock ) > 0 {
185192 // Start from the block before the first new confirmation
186193 blockNumberToReach = newConfirmationsWithoutTxBlock [0 ].BlockNumber .Uint64 () - 1
0 commit comments