@@ -28,16 +28,16 @@ var (
2828 systemAddress = common .HexToAddress ("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001" )
2929 receiptReferencePath = "userDepositData"
3030 //go:embed userDepositData/*.gob
31- receiptReference embed.FS
32- userDepositNoncesAlreadySearched = map [uint64 ]bool {}
33- userDepositNoncesReference = map [uint64 ]userDepositNonces {}
31+ receiptReference embed.FS
32+ userDepositNoncesInitialized = map [uint64 ]bool {}
33+ userDepositNoncesReference = map [uint64 ]userDepositNonces {}
3434)
3535
3636// lazy load the reference data for the requested chain
3737// if this chain data was already requested, returns early
3838func initReceiptReferences (chainID uint64 ) {
3939 // if already loaded, return
40- if userDepositNoncesAlreadySearched [chainID ] {
40+ if userDepositNoncesInitialized [chainID ] {
4141 return
4242 }
4343 // look for a file prefixed by the chainID
@@ -48,7 +48,7 @@ func initReceiptReferences(chainID uint64) {
4848 return
4949 }
5050 // mark as loaded so we don't try again, even if no files match
51- userDepositNoncesAlreadySearched [chainID ] = true
51+ userDepositNoncesInitialized [chainID ] = true
5252 for _ , file := range files {
5353 // skip files which don't match the prefix
5454 if ! strings .HasPrefix (file .Name (), fPrefix ) {
@@ -67,8 +67,11 @@ func initReceiptReferences(chainID uint64) {
6767 continue
6868 }
6969 userDepositNoncesReference [udns .ChainID ] = udns
70+ log .Info ("Receipt Correction: Reference data initialized" , "file" , fpath ,
71+ "chainID" , chainID , "count" , len (udns .Results ), "first" , udns .First , "last" , udns .Last )
7072 return
7173 }
74+ log .Info ("Receipt Correction: No reference data for chain" , "chainID" , chainID )
7275}
7376
7477// correctReceipts corrects the deposit nonce in the receipts using the reference data
@@ -77,13 +80,19 @@ func initReceiptReferences(chainID uint64) {
7780// This function inspects transaction data for user deposits, and if it is found to be incorrect, it is corrected.
7881// The data used to correct the deposit nonce is stored in the userDepositData directory,
7982// and was generated with the receipt reference tool in the optimism monorepo.
80- func correctReceipts (receipts types.Receipts , transactions types.Transactions , blockNumber uint64 , chainID uint64 ) types.Receipts {
83+ func correctReceipts (receiptsRLP rlp.RawValue , transactions types.Transactions , blockNumber uint64 , chainIDBig * big.Int ) rlp.RawValue {
84+ if chainIDBig == nil || ! chainIDBig .IsUint64 () {
85+ // Known chains that need receipt correction have uint64 chain IDs
86+ return receiptsRLP
87+ }
88+ chainID := chainIDBig .Uint64 ()
8189 initReceiptReferences (chainID )
90+
8291 // if there is no data even after initialization, return the receipts as is
8392 depositNoncesForChain , ok := userDepositNoncesReference [chainID ]
8493 if ! ok {
8594 log .Trace ("Receipt Correction: No data source for chain" , "chainID" , chainID )
86- return receipts
95+ return receiptsRLP
8796 }
8897
8998 // check that the block number being examined is within the range of the reference data
@@ -92,48 +101,48 @@ func correctReceipts(receipts types.Receipts, transactions types.Transactions, b
92101 "blockNumber" , blockNumber ,
93102 "start" , depositNoncesForChain .First ,
94103 "end" , depositNoncesForChain .Last )
95- return receipts
104+ return receiptsRLP
96105 }
97106
98107 // get the block nonces
99108 blockNonces , ok := depositNoncesForChain .Results [blockNumber ]
100109 if ! ok {
101110 log .Trace ("Receipt Correction: Block does not contain user deposits" , "blockNumber" , blockNumber )
102- return receipts
111+ return receiptsRLP
112+ }
113+
114+ // Decode RLP receipts to Receipt structs
115+ var receipts []* types.ReceiptForStorage
116+ if err := rlp .DecodeBytes (receiptsRLP , & receipts ); err != nil {
117+ log .Warn ("Receipt Correction: Failed to decode RLP receipts" , "err" , err )
118+ return receiptsRLP
103119 }
104120
105- signer := types .LatestSignerForChainID (big .NewInt (int64 (chainID )))
106121 // iterate through the receipts and transactions to correct the deposit nonce
107122 // user deposits should always be at the front of the block, but we will check all transactions to be sure
108123 udCount := 0
109- for i := 0 ; i < len ( receipts ); i ++ {
110- r := receipts [i ]
124+ for i , r := range receipts {
125+ tx := transactions [i ]
111126 // break as soon as a non deposit is found
112- if r .Type != types .DepositTxType {
127+ if tx .Type () != types .DepositTxType {
113128 break
114129 }
115130
116- tx := transactions [i ]
117- from , err := types .Sender (signer , tx )
118- if err != nil {
119- log .Warn ("Receipt Correction: Failed to determine sender" , "err" , err )
120- continue
121- }
122131 // ignore any transactions from the system address
123- if from != systemAddress {
132+ if from := tx . From (); from != systemAddress {
124133 // prevent index out of range (indicates a problem with the reference data or the block data)
125134 if udCount >= len (blockNonces ) {
126135 log .Warn ("Receipt Correction: More user deposits in block than included in reference data" , "in_reference" , len (blockNonces ))
127136 break
128137 }
129138 nonce := blockNonces [udCount ]
130139 udCount ++
131- log .Trace ("Receipt Correction: User Deposit detected" , "address " , from , "nonce" , nonce )
140+ log .Trace ("Receipt Correction: User Deposit detected" , "from " , from , "nonce" , nonce )
132141 if nonce != * r .DepositNonce {
133142 // correct the deposit nonce
134143 // warn because this should not happen unless the data was modified by corruption or a malicious peer
135144 // by correcting the nonce, the entire block is still valid for use
136- log .Warn ("Receipt Correction: Corrected deposit nonce" , "nonce" , * r .DepositNonce , "corrected" , nonce )
145+ log .Warn ("Receipt Correction: Corrected deposit nonce" , "from" , from , " nonce" , * r .DepositNonce , "corrected" , nonce )
137146 r .DepositNonce = & nonce
138147 }
139148 }
@@ -144,29 +153,12 @@ func correctReceipts(receipts types.Receipts, transactions types.Transactions, b
144153 }
145154
146155 log .Trace ("Receipt Correction: Completed" , "blockNumber" , blockNumber , "userDeposits" , udCount , "receipts" , len (receipts ), "transactions" , len (transactions ))
147- return receipts
148- }
149-
150- // correctReceiptsRLP corrects the deposit nonce in the receipts using the reference data
151- // This function works with RLP encoded receipts, decoding them to Receipt structs,
152- // applying corrections, and re-encoding them back to RLP.
153- func correctReceiptsRLP (receiptsRLP rlp.RawValue , transactions types.Transactions , blockNumber uint64 , chainID uint64 ) rlp.RawValue {
154- // Decode RLP receipts to Receipt structs
155- var receipts types.Receipts
156- if err := rlp .DecodeBytes (receiptsRLP , & receipts ); err != nil {
157- log .Warn ("Receipt Correction: Failed to decode RLP receipts" , "err" , err )
158- return receiptsRLP
159- }
160-
161- // Apply corrections using existing correctReceipts function
162- correctedReceipts := correctReceipts (receipts , transactions , blockNumber , chainID )
163156
164157 // Re-encode to RLP
165- encoded , err := rlp .EncodeToBytes (correctedReceipts )
158+ encoded , err := rlp .EncodeToBytes (receipts )
166159 if err != nil {
167160 log .Warn ("Receipt Correction: Failed to encode corrected receipts to RLP" , "err" , err )
168161 return receiptsRLP
169162 }
170-
171163 return encoded
172164}
0 commit comments