From 6790943f948362b83aff363e4bf0d211727598f0 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Tue, 5 Oct 2021 12:09:08 +0300 Subject: [PATCH 1/3] eth,internal: use correct signer when serving old blocks --- eth/api.go | 2 +- internal/ethapi/api.go | 32 +++++++++++++++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/eth/api.go b/eth/api.go index 98d126958782..3ec72c58e43c 100644 --- a/eth/api.go +++ b/eth/api.go @@ -343,7 +343,7 @@ func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, } else { blockRlp = fmt.Sprintf("0x%x", rlpBytes) } - if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true); err != nil { + if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true, api.eth.APIBackend.ChainConfig()); err != nil { blockJSON = map[string]interface{}{"error": err.Error()} } results = append(results, &BadBlockArgs{ diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 1b09420b0d9a..7cc6c0b1706c 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1206,7 +1206,7 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} { // RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain // transaction hashes. -func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { +func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig) (map[string]interface{}, error) { fields := RPCMarshalHeader(block.Header()) fields["size"] = hexutil.Uint64(block.Size()) @@ -1216,7 +1216,7 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]i } if fullTx { formatTx = func(tx *types.Transaction) (interface{}, error) { - return newRPCTransactionFromBlockHash(block, tx.Hash()), nil + return newRPCTransactionFromBlockHash(block, tx.Hash(), config), nil } } txs := block.Transactions() @@ -1250,7 +1250,7 @@ func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *type // rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires // a `PublicBlockchainAPI`. func (s *PublicBlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { - fields, err := RPCMarshalBlock(b, inclTx, fullTx) + fields, err := RPCMarshalBlock(b, inclTx, fullTx, s.b.ChainConfig()) if err != nil { return nil, err } @@ -1285,7 +1285,7 @@ type RPCTransaction struct { // 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) *RPCTransaction { +func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *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 @@ -1294,7 +1294,13 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber if tx.Protected() { signer = types.LatestSignerForChainID(tx.ChainId()) } else { - signer = types.HomesteadSigner{} + // First reply protection (EIP155) was a part of Spurious Dragon. + // Need to distinguish the two HFs because Homestead rejects a subset of S values. + if config.IsHomestead(big.NewInt(0).SetUint64(blockNumber)) { + signer = types.HomesteadSigner{} + } else { + signer = types.FrontierSigner{} + } } from, _ := types.Sender(signer, tx) v, r, s := tx.RawSignatureValues() @@ -1346,16 +1352,16 @@ func newRPCPendingTransaction(tx *types.Transaction, current *types.Header, conf if current != nil { baseFee = misc.CalcBaseFee(config, current) } - return newRPCTransaction(tx, common.Hash{}, 0, 0, baseFee) + return newRPCTransaction(tx, common.Hash{}, 0, 0, baseFee, config) } // newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransaction { +func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *params.ChainConfig) *RPCTransaction { txs := b.Transactions() if index >= uint64(len(txs)) { return nil } - return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee()) + return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee(), config) } // newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index. @@ -1369,10 +1375,10 @@ func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.By } // newRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction { +func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash, config *params.ChainConfig) *RPCTransaction { for idx, tx := range b.Transactions() { if tx.Hash() == hash { - return newRPCTransactionFromBlockIndex(b, uint64(idx)) + return newRPCTransactionFromBlockIndex(b, uint64(idx), config) } } return nil @@ -1513,7 +1519,7 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Co // GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index. func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { - return newRPCTransactionFromBlockIndex(block, uint64(index)) + return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig()) } return nil } @@ -1521,7 +1527,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx conte // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction { if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { - return newRPCTransactionFromBlockIndex(block, uint64(index)) + return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig()) } return nil } @@ -1573,7 +1579,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, has if err != nil { return nil, err } - return newRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee), nil + return newRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee, s.b.ChainConfig()), nil } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { From e1b06d0cd77310febf827b402b75e51837c0c23a Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Tue, 5 Oct 2021 12:42:41 +0300 Subject: [PATCH 2/3] internal: use MakeSigner instead --- internal/ethapi/api.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 7cc6c0b1706c..35d6983f9181 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1296,11 +1296,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber } else { // First reply protection (EIP155) was a part of Spurious Dragon. // Need to distinguish the two HFs because Homestead rejects a subset of S values. - if config.IsHomestead(big.NewInt(0).SetUint64(blockNumber)) { - signer = types.HomesteadSigner{} - } else { - signer = types.FrontierSigner{} - } + signer = types.MakeSigner(config, big.NewInt(0).SetUint64(blockNumber)) } from, _ := types.Sender(signer, tx) v, r, s := tx.RawSignatureValues() From 6c7222206e4674cc35947ba6d1963522d8c69c08 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Tue, 5 Oct 2021 13:03:26 +0300 Subject: [PATCH 3/3] internal: simplify further --- internal/ethapi/api.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 35d6983f9181..4f00370cbbbe 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1286,18 +1286,7 @@ type RPCTransaction struct { // 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, config *params.ChainConfig) *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 - // because the return value of ChainId is zero for those transactions. - var signer types.Signer - if tx.Protected() { - signer = types.LatestSignerForChainID(tx.ChainId()) - } else { - // First reply protection (EIP155) was a part of Spurious Dragon. - // Need to distinguish the two HFs because Homestead rejects a subset of S values. - signer = types.MakeSigner(config, big.NewInt(0).SetUint64(blockNumber)) - } + signer := types.MakeSigner(config, big.NewInt(0).SetUint64(blockNumber)) from, _ := types.Sender(signer, tx) v, r, s := tx.RawSignatureValues() result := &RPCTransaction{