Skip to content

Commit

Permalink
Merge pull request #99 from testinprod-io/pcw109550/canyon/deposit-tx…
Browse files Browse the repository at this point in the history
…-receipt-hashing-fix

[Canyon Hard Fork] Receipt Root Deposit Nonce Hashing Bug Fix
  • Loading branch information
pcw109550 committed Nov 7, 2023
2 parents 88a18c0 + 3e319d2 commit a1b6e0b
Show file tree
Hide file tree
Showing 18 changed files with 536 additions and 205 deletions.
4 changes: 2 additions & 2 deletions cmd/rpcdaemon/commands/erigon_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ func buildBlockResponse(br services.FullBlockReader, db kv.Tx, blockNum uint64,
additionalFields["totalDifficulty"] = (*hexutil.Big)(td)
}

depositNonces := rawdb.ReadDepositNonces(db, blockNum)
response, err := ethapi.RPCMarshalBlockEx(block, true, fullTx, nil, common.Hash{}, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(db, blockNum)
response, err := ethapi.RPCMarshalBlockEx(block, true, fullTx, nil, common.Hash{}, additionalFields, receipts)

if err == nil && rpc.BlockNumber(block.NumberU64()) == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
Expand Down
12 changes: 9 additions & 3 deletions cmd/rpcdaemon/commands/eth_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,12 +403,14 @@ type RPCTransaction struct {
SourceHash *common.Hash `json:"sourceHash,omitempty"`
Mint *hexutil.Big `json:"mint,omitempty"`
IsSystemTx *bool `json:"isSystemTx,omitempty"`
// deposit-tx post-Canyon only
DepositReceiptVersion *hexutil.Uint64 `json:"depositReceiptVersion,omitempty"`
}

// newRPCTransaction returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available).
func newRPCTransaction(tx types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int,
depositNonce *uint64) *RPCTransaction {
receipt *types.Receipt) *RPCTransaction {
// Determine the signer. For replay-protected transactions, use the most permissive
// signer, because we assume that signers are backwards-compatible with old
// transactions. For non-protected transactions, the homestead signer signer is used
Expand Down Expand Up @@ -464,8 +466,12 @@ func newRPCTransaction(tx types.Transaction, blockHash common.Hash, blockNumber
if t.IsSystemTransaction {
result.IsSystemTx = &t.IsSystemTransaction
}
if depositNonce != nil {
result.Nonce = hexutil.Uint64(*depositNonce)
if receipt != nil && receipt.DepositNonce != nil {
result.Nonce = hexutil.Uint64(*receipt.DepositNonce)
if receipt.DepositReceiptVersion != nil {
result.DepositReceiptVersion = new(hexutil.Uint64)
*result.DepositReceiptVersion = hexutil.Uint64(*receipt.DepositReceiptVersion)
}
}
result.GasPrice = (*hexutil.Big)(common.Big0)
// must contain v, r, s values for backwards compatibility.
Expand Down
8 changes: 4 additions & 4 deletions cmd/rpcdaemon/commands/eth_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ func (api *APIImpl) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber
}
}

depositNonces := rawdb.ReadDepositNonces(tx, b.NumberU64())
response, err := ethapi.RPCMarshalBlockEx(b, true, fullTx, borTx, borTxHash, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(tx, b.NumberU64())
response, err := ethapi.RPCMarshalBlockEx(b, true, fullTx, borTx, borTxHash, additionalFields, receipts)
if err == nil && number == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
Expand Down Expand Up @@ -291,8 +291,8 @@ func (api *APIImpl) GetBlockByHash(ctx context.Context, numberOrHash rpc.BlockNu
}
}

depositNonces := rawdb.ReadDepositNonces(tx, number)
response, err := ethapi.RPCMarshalBlockEx(block, true, fullTx, borTx, borTxHash, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(tx, number)
response, err := ethapi.RPCMarshalBlockEx(block, true, fullTx, borTx, borTxHash, additionalFields, receipts)

if chainConfig.Bor != nil {
response["miner"], _ = ecrecover(block.Header(), chainConfig.Bor)
Expand Down
9 changes: 7 additions & 2 deletions cmd/rpcdaemon/commands/eth_receipts.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,8 +773,13 @@ func marshalReceipt(receipt *types.Receipt, txn types.Transaction, chainConfig *
fields["l1GasUsed"] = hexutil.Big(*receipt.L1GasUsed)
fields["l1Fee"] = hexutil.Big(*receipt.L1Fee)
fields["l1FeeScalar"] = receipt.FeeScalar
} else if receipt.DepositNonce != nil {
fields["depositNonce"] = hexutil.Uint64(*receipt.DepositNonce)
} else {
if receipt.DepositNonce != nil {
fields["depositNonce"] = hexutil.Uint64(*receipt.DepositNonce)
}
if receipt.DepositReceiptVersion != nil {
fields["depositReceiptVersion"] = hexutil.Uint64(*receipt.DepositReceiptVersion)
}
}
}

Expand Down
27 changes: 12 additions & 15 deletions cmd/rpcdaemon/commands/eth_txs.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,11 @@ func (api *APIImpl) GetTransactionByHash(ctx context.Context, txnHash common.Has
}

if chainConfig.IsOptimism() {
depositNonces := rawdb.ReadDepositNonces(tx, block.NumberU64())
if txnIndex >= uint64(len(depositNonces)) {
return nil, fmt.Errorf("depositNonce for tx %x not found", txnHash)
} else {
return newRPCTransaction(txn, blockHash, blockNum, txnIndex, baseFee, depositNonces[txnIndex]), nil
receipts := rawdb.ReadRawReceipts(tx, block.NumberU64())
if len(receipts) <= int(txnIndex) {
return nil, fmt.Errorf("block has less receipts than expected: %d <= %d, block: %d", len(receipts), int(txnIndex), blockNum)
}
return newRPCTransaction(txn, blockHash, blockNum, txnIndex, baseFee, receipts[txnIndex]), nil
}
return newRPCTransaction(txn, blockHash, blockNum, txnIndex, baseFee, nil), nil
}
Expand Down Expand Up @@ -209,12 +208,11 @@ func (api *APIImpl) GetTransactionByBlockHashAndIndex(ctx context.Context, block
}

if chainConfig.IsOptimism() {
depositNonces := rawdb.ReadDepositNonces(tx, block.NumberU64())
if uint64(txIndex) >= uint64(len(depositNonces)) {
return nil, fmt.Errorf("depositNonce for tx %x not found", txs[txIndex].Hash())
} else {
return newRPCTransaction(txs[txIndex], block.Hash(), block.NumberU64(), uint64(txIndex), block.BaseFee(), depositNonces[txIndex]), nil
receipts := rawdb.ReadRawReceipts(tx, block.NumberU64())
if len(receipts) <= int(txIndex) {
return nil, fmt.Errorf("block has less receipts than expected: %d <= %d, block: %d", len(receipts), int(txIndex), block.NumberU64())
}
return newRPCTransaction(txs[txIndex], block.Hash(), block.NumberU64(), uint64(txIndex), block.BaseFee(), receipts[txIndex]), nil
}
return newRPCTransaction(txs[txIndex], block.Hash(), block.NumberU64(), uint64(txIndex), block.BaseFee(), nil), nil
}
Expand Down Expand Up @@ -280,12 +278,11 @@ func (api *APIImpl) GetTransactionByBlockNumberAndIndex(ctx context.Context, blo
return newRPCBorTransaction(borTx, derivedBorTxHash, block.Hash(), block.NumberU64(), uint64(txIndex), block.BaseFee(), chainConfig.ChainID), nil
}
if chainConfig.IsOptimism() {
depositNonces := rawdb.ReadDepositNonces(tx, blockNum)
if uint64(txIndex) >= uint64(len(depositNonces)) {
return nil, fmt.Errorf("depositNonce for tx %x not found", txs[txIndex].Hash())
} else {
return newRPCTransaction(txs[txIndex], block.Hash(), blockNum, uint64(txIndex), block.BaseFee(), depositNonces[txIndex]), nil
receipts := rawdb.ReadRawReceipts(tx, block.NumberU64())
if len(receipts) <= int(txIndex) {
return nil, fmt.Errorf("block has less receipts than expected: %d <= %d, block: %d", len(receipts), int(txIndex), block.NumberU64())
}
return newRPCTransaction(txs[txIndex], block.Hash(), block.NumberU64(), uint64(txIndex), block.BaseFee(), receipts[txIndex]), nil
}
return newRPCTransaction(txs[txIndex], block.Hash(), block.NumberU64(), uint64(txIndex), block.BaseFee(), nil), nil
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/rpcdaemon/commands/eth_uncles.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ func (api *APIImpl) GetUncleByBlockNumberAndIndex(ctx context.Context, number rp
return nil, nil
}
uncle := types.NewBlockWithHeader(uncles[index])
depositNonces := rawdb.ReadDepositNonces(tx, blockNum)
return ethapi.RPCMarshalBlock(uncle, false, false, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(tx, blockNum)
return ethapi.RPCMarshalBlock(uncle, false, false, additionalFields, receipts)
}

// GetUncleByBlockHashAndIndex implements eth_getUncleByBlockHashAndIndex. Returns information about an uncle given a block's hash and the index of the uncle.
Expand Down Expand Up @@ -79,8 +79,8 @@ func (api *APIImpl) GetUncleByBlockHashAndIndex(ctx context.Context, hash common
return nil, nil
}
uncle := types.NewBlockWithHeader(uncles[index])
depositNonces := rawdb.ReadDepositNonces(tx, number)
return ethapi.RPCMarshalBlock(uncle, false, false, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(tx, number)
return ethapi.RPCMarshalBlock(uncle, false, false, additionalFields, receipts)
}

// GetUncleCountByBlockNumber implements eth_getUncleCountByBlockNumber. Returns the number of uncles in the block, if any.
Expand Down
4 changes: 2 additions & 2 deletions cmd/rpcdaemon/commands/graphql_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ func (api *GraphQLAPIImpl) delegateGetBlockByNumber(tx kv.Tx, b *types.Block, nu
return nil, err
}
additionalFields := make(map[string]interface{})
depositNonces := rawdb.ReadDepositNonces(tx, uint64(number.Int64()))
response, err := ethapi.RPCMarshalBlock(b, inclTx, inclTx, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(tx, uint64(number.Int64()))
response, err := ethapi.RPCMarshalBlock(b, inclTx, inclTx, additionalFields, receipts)
if !inclTx {
delete(response, "transactions") // workaround for https://github.com/ledgerwatch/erigon/issues/4989#issuecomment-1218415666
}
Expand Down
19 changes: 9 additions & 10 deletions cmd/rpcdaemon/commands/otterscan_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,18 +520,17 @@ func (api *OtterscanAPIImpl) searchTransactionsBeforeV3(tx kv.TemporalTx, ctx co
return nil, err
}
var rpcTx *RPCTransaction
var receipt *types.Receipt
if chainConfig.IsOptimism() {
depositNonces := rawdb.ReadDepositNonces(tx, blockNum)
if txIndex >= len(depositNonces) {
return nil, fmt.Errorf("depositNonce for tx %x not found", txn.Hash())
} else {
rpcTx = newRPCTransaction(txn, blockHash, blockNum, uint64(txIndex), header.BaseFee, depositNonces[txIndex])
receipts := rawdb.ReadRawReceipts(tx, blockNum)
if len(receipts) <= txIndex {
return nil, fmt.Errorf("block has less receipts than expected: %d <= %d, block: %d", len(receipts), txIndex, blockNum)
}
} else {
rpcTx = newRPCTransaction(txn, blockHash, blockNum, uint64(txIndex), header.BaseFee, nil)
receipt = receipts[txIndex]
}
rpcTx = newRPCTransaction(txn, blockHash, blockNum, uint64(txIndex), header.BaseFee, receipt)
txs = append(txs, rpcTx)
receipt := &types.Receipt{
receipt = &types.Receipt{
Type: txn.Type(), CumulativeGasUsed: res.UsedGas,
TransactionIndex: uint(txIndex),
BlockNumber: header.Number, BlockHash: blockHash, Logs: rawLogs,
Expand Down Expand Up @@ -677,8 +676,8 @@ func (api *OtterscanAPIImpl) delegateGetBlockByNumber(tx kv.Tx, b *types.Block,
return nil, err
}
additionalFields := make(map[string]interface{})
depositNonces := rawdb.ReadDepositNonces(tx, uint64(number.Int64()))
response, err := ethapi.RPCMarshalBlock(b, inclTx, inclTx, additionalFields, depositNonces)
receipts := rawdb.ReadRawReceipts(tx, uint64(number.Int64()))
response, err := ethapi.RPCMarshalBlock(b, inclTx, inclTx, additionalFields, receipts)
if !inclTx {
delete(response, "transactions") // workaround for https://github.com/ledgerwatch/erigon/issues/4989#issuecomment-1218415666
}
Expand Down
13 changes: 4 additions & 9 deletions cmd/rpcdaemon/commands/otterscan_search_trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,6 @@ func (api *OtterscanAPIImpl) traceBlock(dbtx kv.Tx, ctx context.Context, blockNu
header := block.Header()
rules := chainConfig.Rules(block.NumberU64(), header.Time)
found := false

var depositNonces []*uint64
if chainConfig.IsOptimism() {
depositNonces = rawdb.ReadDepositNonces(dbtx, blockNum)
}
for idx, tx := range block.Transactions() {
ibs.SetTxContext(tx.Hash(), block.Hash(), idx)

Expand All @@ -116,11 +111,11 @@ func (api *OtterscanAPIImpl) traceBlock(dbtx kv.Tx, ctx context.Context, blockNu
_ = ibs.FinalizeTx(rules, cachedWriter)

if tracer.Found {
var depositNonce *uint64
if chainConfig.IsOptimism() && idx < len(depositNonces) {
depositNonce = depositNonces[idx]
var receipt *types.Receipt
if chainConfig.IsOptimism() && idx < len(block.Transactions()) {
receipt = blockReceipts[idx]
}
rpcTx := newRPCTransaction(tx, block.Hash(), blockNum, uint64(idx), block.BaseFee(), depositNonce)
rpcTx := newRPCTransaction(tx, block.Hash(), blockNum, uint64(idx), block.BaseFee(), receipt)
mReceipt := marshalReceipt(blockReceipts[idx], tx, chainConfig, block.HeaderNoCopy(), tx.Hash(), true)
mReceipt["timestamp"] = block.Time()
rpcTxs = append(rpcTxs, rpcTx)
Expand Down
15 changes: 2 additions & 13 deletions core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
"github.com/ledgerwatch/erigon-lib/chain"
"math"
"math/big"
"time"

"github.com/ledgerwatch/erigon-lib/chain"

"github.com/gballet/go-verkle"
common2 "github.com/ledgerwatch/erigon-lib/common"
libcommon "github.com/ledgerwatch/erigon-lib/common"
Expand Down Expand Up @@ -851,18 +852,6 @@ func ReadReceipts(config *chain.Config, db kv.Tx, block *types.Block, senders []
return receipts
}

func ReadDepositNonces(db kv.Tx, blockNumber uint64) []*uint64 {
receipts := ReadRawReceipts(db, blockNumber)
if receipts == nil {
return nil
}
depositNonces := make([]*uint64, len(receipts))
for i, r := range receipts {
depositNonces[i] = r.DepositNonce
}
return depositNonces
}

// WriteReceipts stores all the transaction receipts belonging to a block.
func WriteReceipts(tx kv.Putter, number uint64, receipts types.Receipts) error {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
Expand Down
9 changes: 7 additions & 2 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,14 @@ func applyTransaction(config *chain.Config, engine consensus.EngineReader, gp *G
receipt.GasUsed = result.UsedGas

if msg.IsDepositTx() && config.IsOptimismRegolith(evm.Context().Time) {
// The actual nonce for deposit transactions is only recorded from Regolith onwards.
// Before the Regolith fork the DepositNonce must remain nil
// The actual nonce for deposit transactions is only recorded from Regolith onwards and
// otherwise must be nil.
receipt.DepositNonce = &nonce

if config.IsOptimismCanyon(evm.Context().Time) {
receipt.DepositReceiptVersion = new(uint64)
*receipt.DepositReceiptVersion = types.CanyonDepositReceiptVersion
}
}

// if the transaction created a contract, store the creation address in the receipt.
Expand Down
Loading

0 comments on commit a1b6e0b

Please sign in to comment.