Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Canyon Hard Fork] Receipt Root Deposit Nonce Hashing Bug Fix #99

Merged
merged 10 commits into from
Nov 7, 2023
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)
ImTei marked this conversation as resolved.
Show resolved Hide resolved
}
}
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
ImTei marked this conversation as resolved.
Show resolved Hide resolved
}
}

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