From 07ada947a9a9033cd24baa14d99c08b59327b000 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Fri, 8 Mar 2024 09:12:19 +0100 Subject: [PATCH 01/20] implemented methods: eth_getHeaderByNumber eth_getHeaderByHash. --- jsonrpc/eth_blockchain_test.go | 53 ++++++++++++++++++++++++++++++++++ jsonrpc/eth_endpoint.go | 35 ++++++++++++++++++++++ jsonrpc/types.go | 46 +++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index ad1f1c2e0a..73bb5ef46c 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -68,6 +68,59 @@ func TestEth_Block_GetBlockByHash(t *testing.T) { assert.Nil(t, res) } +func TestEth_Block_GetHeaderByNumber(t *testing.T) { + store := &mockBlockStore{} + for i := 0; i < 10; i++ { + store.add(newTestBlock(uint64(i), hash1)) + } + + eth := newTestEthEndpoint(store) + + cases := []struct { + description string + blockNum BlockNumber + isNotNil bool + err bool + }{ + {"should be able to get the latest block number", LatestBlockNumber, true, false}, + {"should be able to get the earliest block number", EarliestBlockNumber, true, false}, + {"should not be able to get block with negative number", BlockNumber(-50), false, true}, + {"should be able to get block with number 0", BlockNumber(0), true, false}, + {"should be able to get block with number 2", BlockNumber(2), true, false}, + {"should be able to get block with number greater than latest block", BlockNumber(50), false, false}, + } + for _, c := range cases { + res, err := eth.GetHeadarByNumber(c.blockNum) + + if c.isNotNil { + assert.NotNil(t, res, "expected to return block, but got nil") + } else { + assert.Nil(t, res, "expected to return nil, but got data") + } + + if c.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + } +} + +func TestEth_Block_GetHeaderByHash(t *testing.T) { + store := &mockBlockStore{} + store.add(newTestBlock(1, hash1)) + + eth := newTestEthEndpoint(store) + + res, err := eth.GetHeadarByHash(hash1) + assert.NoError(t, err) + assert.NotNil(t, res) + + res, err = eth.GetHeadarByHash(hash2) + assert.NoError(t, err) + assert.Nil(t, res) +} + func TestEth_Block_BlockNumber(t *testing.T) { store := &mockBlockStore{} store.add(&types.Block{ diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index 4527fe32a0..c63fa3e6f6 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -155,6 +155,41 @@ func (e *Eth) GetBlockByHash(hash types.Hash, fullTx bool) (interface{}, error) return toBlock(block, fullTx), nil } +// GetHeaderByNumber returns the requested canonical block header. +// * When blockNr is -1 the chain head is returned. +// * When blockNr is -2 the pending chain head is returned. +func (e *Eth) GetHeadarByNumber(number BlockNumber) (interface{}, error) { + num, err := GetNumericBlockNumber(number, e.store) + if err != nil { + return nil, err + } + + block, ok := e.store.GetBlockByNumber(num, true) + if !ok { + return nil, nil + } + + if err := e.filterExtra(block); err != nil { + return nil, err + } + + return toHeader(block.Header), nil +} + +// GetHeaderByHash returns the requested header by hash. +func (e *Eth) GetHeadarByHash(hash types.Hash) (interface{}, error) { + block, ok := e.store.GetBlockByHash(hash, true) + if !ok { + return nil, nil + } + + if err := e.filterExtra(block); err != nil { + return nil, err + } + + return toHeader(block.Header), nil +} + func (e *Eth) filterExtra(block *types.Block) error { // we need to copy it because the store returns header from storage directly // and not a copy, so changing it, actually changes it in storage as well diff --git a/jsonrpc/types.go b/jsonrpc/types.go index fdb34b7323..e135c590b9 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -108,6 +108,27 @@ func toTransaction( return res } +type header struct { + ParentHash types.Hash `json:"parentHash"` + Sha3Uncles types.Hash `json:"sha3Uncles"` + Miner argBytes `json:"miner"` + StateRoot types.Hash `json:"stateRoot"` + TxRoot types.Hash `json:"transactionsRoot"` + ReceiptsRoot types.Hash `json:"receiptsRoot"` + LogsBloom types.Bloom `json:"logsBloom"` + Difficulty argUint64 `json:"difficulty"` + TotalDifficulty argUint64 `json:"totalDifficulty"` + Number argUint64 `json:"number"` + GasLimit argUint64 `json:"gasLimit"` + GasUsed argUint64 `json:"gasUsed"` + Timestamp argUint64 `json:"timestamp"` + ExtraData argBytes `json:"extraData"` + MixHash types.Hash `json:"mixHash"` + Nonce types.Nonce `json:"nonce"` + Hash types.Hash `json:"hash"` + BaseFee argUint64 `json:"baseFeePerGas,omitempty"` +} + type block struct { ParentHash types.Hash `json:"parentHash"` Sha3Uncles types.Hash `json:"sha3Uncles"` @@ -198,6 +219,31 @@ func toBlock(b *types.Block, fullTx bool) *block { return res } +func toHeader(h *types.Header) *header { + res := &header{ + ParentHash: h.ParentHash, + Sha3Uncles: h.Sha3Uncles, + Miner: argBytes(h.Miner), + StateRoot: h.StateRoot, + TxRoot: h.TxRoot, + ReceiptsRoot: h.ReceiptsRoot, + LogsBloom: h.LogsBloom, + Difficulty: argUint64(h.Difficulty), + TotalDifficulty: argUint64(h.Difficulty), // not needed for POS + Number: argUint64(h.Number), + GasLimit: argUint64(h.GasLimit), + GasUsed: argUint64(h.GasUsed), + Timestamp: argUint64(h.Timestamp), + ExtraData: argBytes(h.ExtraData), + MixHash: h.MixHash, + Nonce: h.Nonce, + Hash: h.Hash, + BaseFee: argUint64(h.BaseFee), + } + + return res +} + type receipt struct { Root types.Hash `json:"root"` CumulativeGasUsed argUint64 `json:"cumulativeGasUsed"` From 22a5ece51abecd5cc124ee1506257cdb4719aa1a Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Sun, 10 Mar 2024 14:06:23 +0100 Subject: [PATCH 02/20] The following methods were created: eth_createAccessList, eth_coinbase, eth_getBlockReceipts, txpool_ContentFrom --- jsonrpc/eth_endpoint.go | 90 ++++++++++++++++++++++++++++++++++++++ jsonrpc/txpool_endpoint.go | 36 +++++++++++++++ jsonrpc/types.go | 5 +++ 3 files changed, 131 insertions(+) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index c63fa3e6f6..e196db2774 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -207,6 +207,37 @@ func (e *Eth) filterExtra(block *types.Block) error { return nil } +// CreateAccessList creates a EIP-2930 type AccessList for the given transaction. +// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state. +func (e *Eth) CreateAccessList(arg *txnArgs, filter BlockNumberOrHash) (interface{}, error) { + header, err := GetHeaderFromBlockNumberOrHash(filter, e.store) + if err != nil { + return nil, err + } + + transaction, err := DecodeTxn(arg, header.Number, e.store, true) + if err != nil { + return nil, err + } + + res := &accessListResult{ + Accesslist: transaction.AccessList(), + GasUsed: argUint64(header.GasUsed), + } + + return res, nil +} + +// Returns the client coinbase address. +func (e *Eth) Coinbase() (interface{}, error) { + h := e.store.Header() + if h == nil { + return nil, fmt.Errorf("header has a nil value") + } + + return types.BytesToAddress(h.Miner), nil +} + // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. func (e *Eth) GetBlockTransactionCountByHash(blockHash types.Hash) (interface{}, error) { block, ok := e.store.GetBlockByHash(blockHash, true) @@ -410,6 +441,65 @@ func (e *Eth) GetTransactionReceipt(hash types.Hash) (interface{}, error) { return toReceipt(raw, txn, uint64(txIndex), block.Header, logs), nil } +// GetBlockReceipts returns all transaction receipts for a given block. +func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { + num, err := GetNumericBlockNumber(number, e.store) + if err != nil { + return nil, err + } + + block, ok := e.store.GetBlockByNumber(num, true) + if !ok { + return nil, nil + } + + blockHash := block.Hash() + receipts, err := e.store.GetReceiptsByHash(blockHash) + if err != nil { + // block receipts not found + e.logger.Warn( + fmt.Sprintf("Receipts for block with hash [%s] not found", blockHash.String()), + ) + + return nil, nil + } + + numberOfReceipts := len(receipts) + if numberOfReceipts == 0 { + // Receipts not written yet on the db + e.logger.Warn( + fmt.Sprintf("No receipts found for block with hash [%s]", blockHash.String()), + ) + + return nil, nil + } + + if len(block.Transactions) == 0 { + e.logger.Warn( + fmt.Sprintf("No transations found for block with hash [%s]", blockHash.String()), + ) + + return nil, nil + } + + if numberOfReceipts > len(block.Transactions) { + numberOfReceipts = len(block.Transactions) + } + + var resReceipts []*receipt = make([]*receipt, numberOfReceipts) + logIndex := 0 + for txIndex, txn := range block.Transactions { + raw := receipts[txIndex] + // accumulate receipt logs indexes from block transactions + // that are before the desired transaction + logIndex += len(receipts[txIndex].Logs) + logs := toLogs(raw.Logs, uint64(logIndex), uint64(txIndex), block.Header, raw.TxHash) + resReceipts[txIndex] = toReceipt(raw, txn, uint64(txIndex), block.Header, logs) + } + + return resReceipts, nil +} + // GetStorageAt returns the contract storage at the index position func (e *Eth) GetStorageAt( address types.Address, diff --git a/jsonrpc/txpool_endpoint.go b/jsonrpc/txpool_endpoint.go index 5c2bb5e69f..f3d6f04847 100644 --- a/jsonrpc/txpool_endpoint.go +++ b/jsonrpc/txpool_endpoint.go @@ -29,6 +29,11 @@ type ContentResponse struct { Queued map[types.Address]map[uint64]*transaction `json:"queued"` } +type ContentAddressResponse struct { + Pending map[uint64]*transaction `json:"pending"` + Queued map[uint64]*transaction `json:"queued"` +} + type InspectResponse struct { Pending map[string]map[string]string `json:"pending"` Queued map[string]map[string]string `json:"queued"` @@ -41,6 +46,37 @@ type StatusResponse struct { Queued uint64 `json:"queued"` } +// ContentFrom returns the transactions contained within the transaction pool. +func (t *TxPool) ContentFrom(addr types.Address) (interface{}, error) { + convertTxMap := func(txMap []*types.Transaction) map[uint64]*transaction { + result := make(map[uint64]*transaction, len(txMap)) + for key, tx := range txMap { + result[uint64(key)] = toTransaction(tx, nil, &types.ZeroHash, nil) + } + + return result + } + + pendingTxs, queuedTxs := t.store.GetTxs(true) + + pTxs, ok := pendingTxs[addr] + if !ok { + return nil, nil + } + + qTxs, ok := queuedTxs[addr] + if !ok { + return nil, nil + } + + resp := ContentAddressResponse{ + Pending: convertTxMap(pTxs), + Queued: convertTxMap(qTxs), + } + + return resp, nil +} + // Create response for txpool_content request. // See https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content. func (t *TxPool) Content() (interface{}, error) { diff --git a/jsonrpc/types.go b/jsonrpc/types.go index e135c590b9..78611824e8 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -129,6 +129,11 @@ type header struct { BaseFee argUint64 `json:"baseFeePerGas,omitempty"` } +type accessListResult struct { + Accesslist types.TxAccessList `json:"accessList"` + GasUsed argUint64 `json:"gasUsed"` +} + type block struct { ParentHash types.Hash `json:"parentHash"` Sha3Uncles types.Hash `json:"sha3Uncles"` From 202ae4afc9ceb9cd719ca7779e4b1d60e5b6b6b3 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Sun, 10 Mar 2024 14:29:54 +0100 Subject: [PATCH 03/20] fix lint --- jsonrpc/eth_endpoint.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index e196db2774..c33f6a7afa 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -454,14 +454,14 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { } blockHash := block.Hash() - receipts, err := e.store.GetReceiptsByHash(blockHash) - if err != nil { + receipts, errR := e.store.GetReceiptsByHash(blockHash) + if errR != nil { // block receipts not found e.logger.Warn( fmt.Sprintf("Receipts for block with hash [%s] not found", blockHash.String()), ) - return nil, nil + return nil, errR } numberOfReceipts := len(receipts) @@ -476,7 +476,7 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { if len(block.Transactions) == 0 { e.logger.Warn( - fmt.Sprintf("No transations found for block with hash [%s]", blockHash.String()), + fmt.Sprintf("No transactions found for block with hash [%s]", blockHash.String()), ) return nil, nil @@ -486,15 +486,15 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { numberOfReceipts = len(block.Transactions) } - var resReceipts []*receipt = make([]*receipt, numberOfReceipts) + resReceipts := make([]*receipt, numberOfReceipts) logIndex := 0 - for txIndex, txn := range block.Transactions { - raw := receipts[txIndex] + for i, transaction := range block.Transactions { + raw := receipts[i] // accumulate receipt logs indexes from block transactions // that are before the desired transaction - logIndex += len(receipts[txIndex].Logs) - logs := toLogs(raw.Logs, uint64(logIndex), uint64(txIndex), block.Header, raw.TxHash) - resReceipts[txIndex] = toReceipt(raw, txn, uint64(txIndex), block.Header, logs) + logIndex += len(receipts[i].Logs) + logs := toLogs(raw.Logs, uint64(logIndex), uint64(i), block.Header, raw.TxHash) + resReceipts[i] = toReceipt(raw, transaction, uint64(i), block.Header, logs) } return resReceipts, nil From c3cbd86d1a8f76bd31c6226f487769ec1af1385a Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Tue, 12 Mar 2024 00:31:38 +0100 Subject: [PATCH 04/20] CR fix, part 1 --- jsonrpc/eth_endpoint.go | 25 +++++++++---------- jsonrpc/filter_manager.go | 8 +++--- jsonrpc/filter_manager_test.go | 24 +++++++++++------- jsonrpc/types.go | 45 ++++++++++++---------------------- jsonrpc/types_test.go | 13 +++++++--- 5 files changed, 55 insertions(+), 60 deletions(-) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index c33f6a7afa..a7b46fedd0 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -232,7 +232,7 @@ func (e *Eth) CreateAccessList(arg *txnArgs, filter BlockNumberOrHash) (interfac func (e *Eth) Coinbase() (interface{}, error) { h := e.store.Header() if h == nil { - return nil, fmt.Errorf("header has a nil value") + return nil, ErrHeaderNotFound } return types.BytesToAddress(h.Miner), nil @@ -292,7 +292,7 @@ func (e *Eth) GetTransactionByBlockHashAndIndex(blockHash types.Hash, index argU func (e *Eth) BlockNumber() (interface{}, error) { h := e.store.Header() if h == nil { - return nil, fmt.Errorf("header has a nil value") + return nil, ErrHeaderNotFound } return argUintPtr(h.Number), nil @@ -454,6 +454,14 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { } blockHash := block.Hash() + if len(block.Transactions) == 0 { + e.logger.Warn( + fmt.Sprintf("No transactions found for block with hash [%s]", blockHash.String()), + ) + + return nil, nil + } + receipts, errR := e.store.GetReceiptsByHash(blockHash) if errR != nil { // block receipts not found @@ -474,20 +482,9 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { return nil, nil } - if len(block.Transactions) == 0 { - e.logger.Warn( - fmt.Sprintf("No transactions found for block with hash [%s]", blockHash.String()), - ) - - return nil, nil - } - - if numberOfReceipts > len(block.Transactions) { - numberOfReceipts = len(block.Transactions) - } - resReceipts := make([]*receipt, numberOfReceipts) logIndex := 0 + for i, transaction := range block.Transactions { raw := receipts[i] // accumulate receipt logs indexes from block transactions diff --git a/jsonrpc/filter_manager.go b/jsonrpc/filter_manager.go index 03bacde8ff..1c5153f4e6 100644 --- a/jsonrpc/filter_manager.go +++ b/jsonrpc/filter_manager.go @@ -152,7 +152,7 @@ func (f *blockFilter) getUpdates() (interface{}, error) { updates := make([]string, len(headers)) for index, header := range headers { - updates[index] = header.Hash.String() + updates[index] = header.BlockHeader.Hash.String() } return updates, nil @@ -772,7 +772,7 @@ func (f *FilterManager) processBlockEvent(evnt *blockchain.Event) { // appendLogsToFilters makes each LogFilters append logs in the header func (f *FilterManager) appendLogsToFilters(header *block) error { - receipts, err := f.store.GetReceiptsByHash(header.Hash) + receipts, err := f.store.GetReceiptsByHash(header.BlockHeader.Hash) if err != nil { return err } @@ -790,9 +790,9 @@ func (f *FilterManager) appendLogsToFilters(header *block) error { return nil } - block, ok := f.store.GetBlockByHash(header.Hash, true) + block, ok := f.store.GetBlockByHash(header.BlockHeader.Hash, true) if !ok { - f.logger.Error("could not find block in store", "hash", header.Hash.String()) + f.logger.Error("could not find block in store", "hash", header.BlockHeader.Hash.String()) return nil } diff --git a/jsonrpc/filter_manager_test.go b/jsonrpc/filter_manager_test.go index 00693147e2..fdd968ea72 100644 --- a/jsonrpc/filter_manager_test.go +++ b/jsonrpc/filter_manager_test.go @@ -661,19 +661,23 @@ func newMockWsConnWithMsgCh() (*mockWsConn, <-chan []byte) { func TestHeadStream_Basic(t *testing.T) { t.Parallel() - b := newBlockStream(&block{Hash: types.StringToHash("1")}) - b.push(&block{Hash: types.StringToHash("2")}) + blockHeader1 := &header{Hash: types.StringToHash("1")} + blockHeader2 := &header{Hash: types.StringToHash("2")} + blockHeader3 := &header{Hash: types.StringToHash("3")} + blockHeader4 := &header{Hash: types.StringToHash("4")} + b := newBlockStream(&block{BlockHeader: blockHeader1}) + b.push(&block{BlockHeader: blockHeader2}) cur := b.getHead() - b.push(&block{Hash: types.StringToHash("3")}) - b.push(&block{Hash: types.StringToHash("4")}) + b.push(&block{BlockHeader: blockHeader3}) + b.push(&block{BlockHeader: blockHeader4}) // get the updates, there are two new entries updates, next := cur.getUpdates() - assert.Equal(t, updates[0].Hash.String(), types.StringToHash("3").String()) - assert.Equal(t, updates[1].Hash.String(), types.StringToHash("4").String()) + assert.Equal(t, updates[0].BlockHeader.Hash.String(), types.StringToHash("3").String()) + assert.Equal(t, updates[1].BlockHeader.Hash.String(), types.StringToHash("4").String()) // there are no new entries updates, _ = next.getUpdates() @@ -686,7 +690,8 @@ func TestHeadStream_Concurrent(t *testing.T) { nReaders := 20 nMessages := 10 - b := newBlockStream(&block{Number: 0}) + blockHeader := &header{Number: 0} + b := newBlockStream(&block{BlockHeader: blockHeader}) // Write co-routine with jitter go func() { @@ -696,7 +701,8 @@ func TestHeadStream_Concurrent(t *testing.T) { z := rand.NewZipf(rand.New(rand.NewSource(seed)), 1.5, 1.5, 50) for i := 0; i < nMessages; i++ { - b.push(&block{Number: argUint64(i)}) + bHeader := &header{Number: argUint64(i)} + b.push(&block{BlockHeader: bHeader}) wait := time.Duration(z.Uint64()) * time.Millisecond time.Sleep(wait) @@ -718,7 +724,7 @@ func TestHeadStream_Concurrent(t *testing.T) { blocks, next := item.getUpdates() for _, block := range blocks { - if num := uint64(block.Number); num != expect { + if num := uint64(block.BlockHeader.Number); num != expect { errCh <- fmt.Errorf("subscriber %05d bad event want=%d, got=%d", i, num, expect) return diff --git a/jsonrpc/types.go b/jsonrpc/types.go index 78611824e8..11254e6c15 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -135,45 +135,28 @@ type accessListResult struct { } type block struct { - ParentHash types.Hash `json:"parentHash"` - Sha3Uncles types.Hash `json:"sha3Uncles"` - Miner argBytes `json:"miner"` - StateRoot types.Hash `json:"stateRoot"` - TxRoot types.Hash `json:"transactionsRoot"` - ReceiptsRoot types.Hash `json:"receiptsRoot"` - LogsBloom types.Bloom `json:"logsBloom"` - Difficulty argUint64 `json:"difficulty"` - TotalDifficulty argUint64 `json:"totalDifficulty"` - Size argUint64 `json:"size"` - Number argUint64 `json:"number"` - GasLimit argUint64 `json:"gasLimit"` - GasUsed argUint64 `json:"gasUsed"` - Timestamp argUint64 `json:"timestamp"` - ExtraData argBytes `json:"extraData"` - MixHash types.Hash `json:"mixHash"` - Nonce types.Nonce `json:"nonce"` - Hash types.Hash `json:"hash"` - Transactions []transactionOrHash `json:"transactions"` - Uncles []types.Hash `json:"uncles"` - BaseFee argUint64 `json:"baseFeePerGas,omitempty"` + BlockHeader *header + Size argUint64 `json:"size"` + Transactions []transactionOrHash `json:"transactions"` + Uncles []types.Hash `json:"uncles"` } func (b *block) Copy() *block { bb := new(block) *bb = *b - bb.Miner = make([]byte, len(b.Miner)) - copy(bb.Miner[:], b.Miner[:]) + bb.BlockHeader.Miner = make([]byte, len(b.BlockHeader.Miner)) + copy(bb.BlockHeader.Miner[:], b.BlockHeader.Miner[:]) - bb.ExtraData = make([]byte, len(b.ExtraData)) - copy(bb.ExtraData[:], b.ExtraData[:]) + bb.BlockHeader.ExtraData = make([]byte, len(b.BlockHeader.ExtraData)) + copy(bb.BlockHeader.ExtraData[:], b.BlockHeader.ExtraData[:]) return bb } func toBlock(b *types.Block, fullTx bool) *block { h := b.Header - res := &block{ + resHeader := &header{ ParentHash: h.ParentHash, Sha3Uncles: h.Sha3Uncles, Miner: argBytes(h.Miner), @@ -183,7 +166,6 @@ func toBlock(b *types.Block, fullTx bool) *block { LogsBloom: h.LogsBloom, Difficulty: argUint64(h.Difficulty), TotalDifficulty: argUint64(h.Difficulty), // not needed for POS - Size: argUint64(b.Size()), Number: argUint64(h.Number), GasLimit: argUint64(h.GasLimit), GasUsed: argUint64(h.GasUsed), @@ -192,11 +174,16 @@ func toBlock(b *types.Block, fullTx bool) *block { MixHash: h.MixHash, Nonce: h.Nonce, Hash: h.Hash, - Transactions: []transactionOrHash{}, - Uncles: []types.Hash{}, BaseFee: argUint64(h.BaseFee), } + res := &block{ + BlockHeader: resHeader, + Size: argUint64(b.Size()), + Transactions: []transactionOrHash{}, + Uncles: []types.Hash{}, + } + for idx, txn := range b.Transactions { if fullTx { txn.SetGasPrice(txn.GetGasPrice(b.Header.BaseFee)) diff --git a/jsonrpc/types_test.go b/jsonrpc/types_test.go index 3b6cd06e57..bfc64af140 100644 --- a/jsonrpc/types_test.go +++ b/jsonrpc/types_test.go @@ -165,10 +165,13 @@ func TestToTransaction_EIP1559(t *testing.T) { } func TestBlock_Copy(t *testing.T) { - b := &block{ + bHeader := &header{ ExtraData: []byte{0x1}, Miner: []byte{0x2}, - Uncles: []types.Hash{{0x0, 0x1}}, + } + b := &block{ + BlockHeader: bHeader, + Uncles: []types.Hash{{0x0, 0x1}}, } bb := b.Copy() @@ -180,7 +183,7 @@ var testsuite embed.FS func TestBlock_Encoding(t *testing.T) { getBlock := func() block { - return block{ + bHeader := &header{ ParentHash: types.Hash{0x1}, Sha3Uncles: types.Hash{0x2}, Miner: types.Address{0x1}.Bytes(), @@ -199,6 +202,8 @@ func TestBlock_Encoding(t *testing.T) { Hash: types.Hash{0x8}, BaseFee: 15, } + + return block{BlockHeader: bHeader} } testBlock := func(name string, b block) { @@ -215,7 +220,7 @@ func TestBlock_Encoding(t *testing.T) { t.Run("block with no base fee", func(t *testing.T) { b := getBlock() - b.BaseFee = 0 + b.BlockHeader.BaseFee = 0 testBlock("testsuite/block-with-no-basefee.json", b) }) From 8df59597f2d8e88dd232885ee1e6a43c1a87ba0a Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Tue, 12 Mar 2024 18:37:16 +0100 Subject: [PATCH 05/20] CR fix, part 2 --- jsonrpc/eth_blockchain_test.go | 6 +++--- jsonrpc/eth_endpoint.go | 16 +++------------- jsonrpc/filter_manager.go | 8 ++++---- jsonrpc/filter_manager_test.go | 25 +++++++++---------------- jsonrpc/types.go | 14 +++++++------- jsonrpc/types_test.go | 20 +++++++++----------- 6 files changed, 35 insertions(+), 54 deletions(-) diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index 73bb5ef46c..b4b05e40a5 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -90,7 +90,7 @@ func TestEth_Block_GetHeaderByNumber(t *testing.T) { {"should be able to get block with number greater than latest block", BlockNumber(50), false, false}, } for _, c := range cases { - res, err := eth.GetHeadarByNumber(c.blockNum) + res, err := eth.GetHeaderByNumber(c.blockNum) if c.isNotNil { assert.NotNil(t, res, "expected to return block, but got nil") @@ -112,11 +112,11 @@ func TestEth_Block_GetHeaderByHash(t *testing.T) { eth := newTestEthEndpoint(store) - res, err := eth.GetHeadarByHash(hash1) + res, err := eth.GetHeaderByHash(hash1) assert.NoError(t, err) assert.NotNil(t, res) - res, err = eth.GetHeadarByHash(hash2) + res, err = eth.GetHeaderByHash(hash2) assert.NoError(t, err) assert.Nil(t, res) } diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index a7b46fedd0..29fd63edb7 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -158,7 +158,7 @@ func (e *Eth) GetBlockByHash(hash types.Hash, fullTx bool) (interface{}, error) // GetHeaderByNumber returns the requested canonical block header. // * When blockNr is -1 the chain head is returned. // * When blockNr is -2 the pending chain head is returned. -func (e *Eth) GetHeadarByNumber(number BlockNumber) (interface{}, error) { +func (e *Eth) GetHeaderByNumber(number BlockNumber) (interface{}, error) { num, err := GetNumericBlockNumber(number, e.store) if err != nil { return nil, err @@ -177,7 +177,7 @@ func (e *Eth) GetHeadarByNumber(number BlockNumber) (interface{}, error) { } // GetHeaderByHash returns the requested header by hash. -func (e *Eth) GetHeadarByHash(hash types.Hash) (interface{}, error) { +func (e *Eth) GetHeaderByHash(hash types.Hash) (interface{}, error) { block, ok := e.store.GetBlockByHash(hash, true) if !ok { return nil, nil @@ -228,16 +228,6 @@ func (e *Eth) CreateAccessList(arg *txnArgs, filter BlockNumberOrHash) (interfac return res, nil } -// Returns the client coinbase address. -func (e *Eth) Coinbase() (interface{}, error) { - h := e.store.Header() - if h == nil { - return nil, ErrHeaderNotFound - } - - return types.BytesToAddress(h.Miner), nil -} - // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. func (e *Eth) GetBlockTransactionCountByHash(blockHash types.Hash) (interface{}, error) { block, ok := e.store.GetBlockByHash(blockHash, true) @@ -657,7 +647,7 @@ func (e *Eth) Call(arg *txnArgs, filter BlockNumberOrHash, apiOverride *stateOve // EstimateGas estimates the gas needed to execute a transaction func (e *Eth) EstimateGas(arg *txnArgs, rawNum *BlockNumber) (interface{}, error) { - number := LatestBlockNumber + number := LatestBlockNumber /* */ if rawNum != nil { number = *rawNum } diff --git a/jsonrpc/filter_manager.go b/jsonrpc/filter_manager.go index 1c5153f4e6..03bacde8ff 100644 --- a/jsonrpc/filter_manager.go +++ b/jsonrpc/filter_manager.go @@ -152,7 +152,7 @@ func (f *blockFilter) getUpdates() (interface{}, error) { updates := make([]string, len(headers)) for index, header := range headers { - updates[index] = header.BlockHeader.Hash.String() + updates[index] = header.Hash.String() } return updates, nil @@ -772,7 +772,7 @@ func (f *FilterManager) processBlockEvent(evnt *blockchain.Event) { // appendLogsToFilters makes each LogFilters append logs in the header func (f *FilterManager) appendLogsToFilters(header *block) error { - receipts, err := f.store.GetReceiptsByHash(header.BlockHeader.Hash) + receipts, err := f.store.GetReceiptsByHash(header.Hash) if err != nil { return err } @@ -790,9 +790,9 @@ func (f *FilterManager) appendLogsToFilters(header *block) error { return nil } - block, ok := f.store.GetBlockByHash(header.BlockHeader.Hash, true) + block, ok := f.store.GetBlockByHash(header.Hash, true) if !ok { - f.logger.Error("could not find block in store", "hash", header.BlockHeader.Hash.String()) + f.logger.Error("could not find block in store", "hash", header.Hash.String()) return nil } diff --git a/jsonrpc/filter_manager_test.go b/jsonrpc/filter_manager_test.go index fdd968ea72..2f9f05306d 100644 --- a/jsonrpc/filter_manager_test.go +++ b/jsonrpc/filter_manager_test.go @@ -660,24 +660,19 @@ func newMockWsConnWithMsgCh() (*mockWsConn, <-chan []byte) { func TestHeadStream_Basic(t *testing.T) { t.Parallel() + b := newBlockStream(&block{header: header{Hash: types.StringToHash("1")}}) - blockHeader1 := &header{Hash: types.StringToHash("1")} - blockHeader2 := &header{Hash: types.StringToHash("2")} - blockHeader3 := &header{Hash: types.StringToHash("3")} - blockHeader4 := &header{Hash: types.StringToHash("4")} - b := newBlockStream(&block{BlockHeader: blockHeader1}) - - b.push(&block{BlockHeader: blockHeader2}) + b.push(&block{header: header{Hash: types.StringToHash("2")}}) cur := b.getHead() - b.push(&block{BlockHeader: blockHeader3}) - b.push(&block{BlockHeader: blockHeader4}) + b.push(&block{header: header{Hash: types.StringToHash("3")}}) + b.push(&block{header: header{Hash: types.StringToHash("4")}}) // get the updates, there are two new entries updates, next := cur.getUpdates() - assert.Equal(t, updates[0].BlockHeader.Hash.String(), types.StringToHash("3").String()) - assert.Equal(t, updates[1].BlockHeader.Hash.String(), types.StringToHash("4").String()) + assert.Equal(t, updates[0].Hash.String(), types.StringToHash("3").String()) + assert.Equal(t, updates[1].Hash.String(), types.StringToHash("4").String()) // there are no new entries updates, _ = next.getUpdates() @@ -690,8 +685,7 @@ func TestHeadStream_Concurrent(t *testing.T) { nReaders := 20 nMessages := 10 - blockHeader := &header{Number: 0} - b := newBlockStream(&block{BlockHeader: blockHeader}) + b := newBlockStream(&block{header: header{Number: 0}}) // Write co-routine with jitter go func() { @@ -701,8 +695,7 @@ func TestHeadStream_Concurrent(t *testing.T) { z := rand.NewZipf(rand.New(rand.NewSource(seed)), 1.5, 1.5, 50) for i := 0; i < nMessages; i++ { - bHeader := &header{Number: argUint64(i)} - b.push(&block{BlockHeader: bHeader}) + b.push(&block{header: header{Number: argUint64(i)}}) wait := time.Duration(z.Uint64()) * time.Millisecond time.Sleep(wait) @@ -724,7 +717,7 @@ func TestHeadStream_Concurrent(t *testing.T) { blocks, next := item.getUpdates() for _, block := range blocks { - if num := uint64(block.BlockHeader.Number); num != expect { + if num := uint64(block.Number); num != expect { errCh <- fmt.Errorf("subscriber %05d bad event want=%d, got=%d", i, num, expect) return diff --git a/jsonrpc/types.go b/jsonrpc/types.go index 11254e6c15..ff3002d081 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -135,7 +135,7 @@ type accessListResult struct { } type block struct { - BlockHeader *header + header Size argUint64 `json:"size"` Transactions []transactionOrHash `json:"transactions"` Uncles []types.Hash `json:"uncles"` @@ -145,18 +145,18 @@ func (b *block) Copy() *block { bb := new(block) *bb = *b - bb.BlockHeader.Miner = make([]byte, len(b.BlockHeader.Miner)) - copy(bb.BlockHeader.Miner[:], b.BlockHeader.Miner[:]) + bb.Miner = make([]byte, len(b.Miner)) + copy(bb.Miner[:], b.Miner[:]) - bb.BlockHeader.ExtraData = make([]byte, len(b.BlockHeader.ExtraData)) - copy(bb.BlockHeader.ExtraData[:], b.BlockHeader.ExtraData[:]) + bb.ExtraData = make([]byte, len(b.ExtraData)) + copy(bb.ExtraData[:], b.ExtraData[:]) return bb } func toBlock(b *types.Block, fullTx bool) *block { h := b.Header - resHeader := &header{ + resHeader := header{ ParentHash: h.ParentHash, Sha3Uncles: h.Sha3Uncles, Miner: argBytes(h.Miner), @@ -178,7 +178,7 @@ func toBlock(b *types.Block, fullTx bool) *block { } res := &block{ - BlockHeader: resHeader, + header: resHeader, Size: argUint64(b.Size()), Transactions: []transactionOrHash{}, Uncles: []types.Hash{}, diff --git a/jsonrpc/types_test.go b/jsonrpc/types_test.go index bfc64af140..5e570451d1 100644 --- a/jsonrpc/types_test.go +++ b/jsonrpc/types_test.go @@ -165,13 +165,13 @@ func TestToTransaction_EIP1559(t *testing.T) { } func TestBlock_Copy(t *testing.T) { - bHeader := &header{ - ExtraData: []byte{0x1}, - Miner: []byte{0x2}, - } b := &block{ - BlockHeader: bHeader, - Uncles: []types.Hash{{0x0, 0x1}}, + header: header{ + ExtraData: []byte{0x1}, + Miner: []byte{0x2}, + }, + + Uncles: []types.Hash{{0x0, 0x1}}, } bb := b.Copy() @@ -183,7 +183,7 @@ var testsuite embed.FS func TestBlock_Encoding(t *testing.T) { getBlock := func() block { - bHeader := &header{ + return block{header: header{ ParentHash: types.Hash{0x1}, Sha3Uncles: types.Hash{0x2}, Miner: types.Address{0x1}.Bytes(), @@ -201,9 +201,7 @@ func TestBlock_Encoding(t *testing.T) { Nonce: types.Nonce{10}, Hash: types.Hash{0x8}, BaseFee: 15, - } - - return block{BlockHeader: bHeader} + }} } testBlock := func(name string, b block) { @@ -220,7 +218,7 @@ func TestBlock_Encoding(t *testing.T) { t.Run("block with no base fee", func(t *testing.T) { b := getBlock() - b.BlockHeader.BaseFee = 0 + b.BaseFee = 0 testBlock("testsuite/block-with-no-basefee.json", b) }) From d07f2e49315773fa9a6a315e0e0eea8831dcbc2a Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Tue, 12 Mar 2024 23:46:11 +0100 Subject: [PATCH 06/20] lint fix --- e2e-polybft/e2e/bridge_test.go | 4 ++- e2e-polybft/e2e/consensus_test.go | 5 +-- e2e-polybft/e2e/jsonrpc_test.go | 2 ++ e2e-polybft/e2e/txpool_test.go | 3 ++ e2e-polybft/property/property_test.go | 3 ++ jsonrpc/codec_test.go | 2 ++ jsonrpc/dispatcher.go | 1 + jsonrpc/dispatcher_test.go | 4 +++ jsonrpc/eth_blockchain_test.go | 3 ++ jsonrpc/eth_state_test.go | 3 ++ jsonrpc/filter_manager.go | 1 + jsonrpc/filter_manager_fuzz_test.go | 3 ++ jsonrpc/filter_manager_test.go | 2 ++ jsonrpc/helper.go | 1 + jsonrpc/jsonrpc.go | 1 + network/identity_e2e_test.go | 1 + network/server_test.go | 4 +++ state/immutable-trie/copy_trie_test.go | 6 ++++ state/immutable-trie/hasher.go | 1 + state/runtime/evm/bitmap.go | 1 + state/runtime/evm/bitmap_test.go | 1 + state/runtime/evm/dispatch_table.go | 1 + state/runtime/evm/dispatch_table_test.go | 1 + state/runtime/evm/evm_test.go | 3 ++ state/runtime/evm/instructions.go | 5 +++ state/runtime/evm/instructions_test.go | 5 +++ state/runtime/evm/state.go | 1 + state/transition_test.go | 1 + state/txn.go | 8 +++-- txpool/event_subscription_test.go | 5 +++ txpool/txpool_test.go | 45 ++++++++++++++++++++++++ types/rlp_marshal_storage.go | 2 ++ 32 files changed, 124 insertions(+), 5 deletions(-) diff --git a/e2e-polybft/e2e/bridge_test.go b/e2e-polybft/e2e/bridge_test.go index 921e26605c..e67f2a9c29 100644 --- a/e2e-polybft/e2e/bridge_test.go +++ b/e2e-polybft/e2e/bridge_test.go @@ -74,12 +74,13 @@ func TestE2E_Bridge_RootchainTokensTransfers(t *testing.T) { framework.WithBridge(), framework.WithSecretsCallback(func(addrs []types.Address, tcc *framework.TestClusterConfig) { for i := 0; i < len(addrs); i++ { - tcc.StakeAmounts = append(tcc.StakeAmounts, ethgo.Ether(10)) // premine receivers, so that they are able to do withdrawals + tcc.StakeAmounts = append(tcc.StakeAmounts, ethgo.Ether(10)) } tcc.Premine = append(tcc.Premine, receivers...) })) + defer cluster.Stop() cluster.WaitForReady(t) @@ -1337,6 +1338,7 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { checkBalancesFn(types.Address(rewardWalletKey.Address()), bigZero, command.DefaultPremineBalance, true) validatorsExpectedBalance := new(big.Int).Sub(command.DefaultPremineBalance, command.DefaultStake) + for _, server := range cluster.Servers { validatorAccount, err := validatorHelper.GetAccountFromDir(server.DataDir()) require.NoError(t, err) diff --git a/e2e-polybft/e2e/consensus_test.go b/e2e-polybft/e2e/consensus_test.go index 0115d6bcb1..49d39b7b2a 100644 --- a/e2e-polybft/e2e/consensus_test.go +++ b/e2e-polybft/e2e/consensus_test.go @@ -398,6 +398,7 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", addr, initValidatorsBalance)) config.StakeAmounts = append(config.StakeAmounts, new(big.Int).Set(initValidatorsBalance)) validatorsAddrs[i] = addr + initialTotalSupply.Add(initialTotalSupply, initValidatorsBalance) } })) @@ -536,7 +537,7 @@ func TestE2E_Consensus_EIP1559Check(t *testing.T) { client := cluster.Servers[0].JSONRPC().Eth() - waitUntilBalancesChanged := func(acct ethgo.Address, initialBalance *big.Int) error { + waitUntilBalancesChanged := func(initialBalance *big.Int) error { err := cluster.WaitUntil(30*time.Second, 1*time.Second, func() bool { balance, err := client.GetBalance(recipient, ethgo.Latest) if err != nil { @@ -587,7 +588,7 @@ func TestE2E_Consensus_EIP1559Check(t *testing.T) { require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) // wait for recipient's balance to increase - err = waitUntilBalancesChanged(recipient, receiverInitialBalance) + err = waitUntilBalancesChanged(receiverInitialBalance) require.NoError(t, err) block, _ := client.GetBlockByHash(receipt.BlockHash, true) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 9198f4d697..530f02efb4 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -190,11 +190,13 @@ func TestE2E_JsonRPC(t *testing.T) { Value: newBalance, }) require.NoError(t, err) + txPrice := gasPrice * estimatedGas // subtract gasPrice * estimatedGas from the balance and transfer the rest to the other account // in order to leave no funds on the account amountToSend := new(big.Int).Sub(newBalance, big.NewInt(int64(txPrice))) targetAddr := acct.Address() + txn = cluster.SendTxn(t, key1, ðgo.Transaction{ To: &targetAddr, Value: amountToSend, diff --git a/e2e-polybft/e2e/txpool_test.go b/e2e-polybft/e2e/txpool_test.go index e842259605..f6c28db1e6 100644 --- a/e2e-polybft/e2e/txpool_test.go +++ b/e2e-polybft/e2e/txpool_test.go @@ -83,7 +83,9 @@ func TestE2E_TxPool_Transfer(t *testing.T) { if err != nil { return true } + t.Logf("Balance %s %s", receiver, balance) + if balance.Uint64() != uint64(sendAmount) { return false } @@ -274,6 +276,7 @@ func TestE2E_TxPool_BroadcastTransactions(t *testing.T) { for _, srv := range cluster.Servers { balance, err := srv.WaitForNonZeroBalance(recipient, time.Second*10) assert.NoError(t, err) + if balance != nil && balance.BitLen() > 0 { assert.Equal(t, sentAmount, balance) } else { diff --git a/e2e-polybft/property/property_test.go b/e2e-polybft/property/property_test.go index 28c518c7e1..55d7bcdc71 100644 --- a/e2e-polybft/property/property_test.go +++ b/e2e-polybft/property/property_test.go @@ -109,8 +109,11 @@ func TestProperty_DropValidators(t *testing.T) { // check that block production is stoped currentBlock, err = activeValidator.JSONRPC().Eth().BlockNumber() require.NoError(t, err) + oldBlockNumber := currentBlock + time.Sleep(2 * blockTime) + currentBlock, err = activeValidator.JSONRPC().Eth().BlockNumber() require.NoError(t, err) require.Equal(t, oldBlockNumber, currentBlock) diff --git a/jsonrpc/codec_test.go b/jsonrpc/codec_test.go index 38f41e7219..631145e237 100644 --- a/jsonrpc/codec_test.go +++ b/jsonrpc/codec_test.go @@ -105,9 +105,11 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) { assert.Error(t, err) } else { assert.NoError(t, err) + if tt.expectedBnh.BlockNumber != nil { assert.Equal(t, *bnh.BlockNumber, *tt.expectedBnh.BlockNumber) } + if tt.expectedBnh.BlockHash != nil { assert.Equal(t, bnh.BlockHash.String(), tt.expectedBnh.BlockHash.String()) } diff --git a/jsonrpc/dispatcher.go b/jsonrpc/dispatcher.go index 7f66ef6559..b027060491 100644 --- a/jsonrpc/dispatcher.go +++ b/jsonrpc/dispatcher.go @@ -212,6 +212,7 @@ func (d *Dispatcher) handleSubscribe(req Request, conn wsConn) (string, Error) { if err != nil { return "", NewInternalError(err.Error()) } + filterID = d.filterManager.NewLogFilter(logQuery, conn) } else if subscribeMethod == "newPendingTransactions" { filterID = d.filterManager.NewPendingTxFilter(conn) diff --git a/jsonrpc/dispatcher_test.go b/jsonrpc/dispatcher_test.go index 63cfc7e90d..193e4a069e 100644 --- a/jsonrpc/dispatcher_test.go +++ b/jsonrpc/dispatcher_test.go @@ -467,20 +467,24 @@ func TestDispatcherBatchRequest(t *testing.T) { assert.Equal(t, c.err, resp.Error) } else { var batchResp []SuccessResponse + assert.NoError(t, expectBatchJSONResult(res, &batchResp)) if c.name == "leading-whitespace" { assert.Len(t, batchResp, 4) + for index, resp := range batchResp { assert.Equal(t, c.batchResponse[index].Error, resp.Error) } } else if c.name == "valid-batch-req" { assert.Len(t, batchResp, 6) + for index, resp := range batchResp { assert.Equal(t, c.batchResponse[index].Error, resp.Error) } } else if c.name == "no-limits" { assert.Len(t, batchResp, 12) + for index, resp := range batchResp { assert.Equal(t, c.batchResponse[index].Error, resp.Error) } diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index b4b05e40a5..1ab4f48408 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -314,8 +314,10 @@ func TestEth_GetTransactionReceipt(t *testing.T) { eth := newTestEthEndpoint(store) block := newTestBlock(1, hash4) store.add(block) + txn0 := newTestTransaction(uint64(0), addr0) txn1 := newTestTransaction(uint64(1), addr1) + block.Transactions = []*types.Transaction{txn0, txn1} receipt1 := &types.Receipt{ Logs: []*types.Log{ @@ -340,6 +342,7 @@ func TestEth_GetTransactionReceipt(t *testing.T) { }, } receipt1.SetStatus(types.ReceiptSuccess) + receipt2 := &types.Receipt{ Logs: []*types.Log{ { diff --git a/jsonrpc/eth_state_test.go b/jsonrpc/eth_state_test.go index f931294145..858681a562 100644 --- a/jsonrpc/eth_state_test.go +++ b/jsonrpc/eth_state_test.go @@ -131,6 +131,7 @@ func TestEth_State_GetBalance(t *testing.T) { assert.Equal(t, nil, balance) } else { assert.NoError(t, err) + if tt.expectedBalance == 0 { uintBalance, ok := balance.(*argUint64) if !ok { @@ -383,6 +384,7 @@ func TestEth_State_GetCode(t *testing.T) { assert.Error(t, err) } else { assert.NoError(t, err) + if tt.target.String() == uninitializedAddress.String() { assert.Equal(t, "0x", code) } else { @@ -553,6 +555,7 @@ func TestEth_State_GetStorageAt(t *testing.T) { storage: make(map[types.Hash][]byte), } account := store.account + for index, data := range storage { account.Storage(index, data.Bytes()) } diff --git a/jsonrpc/filter_manager.go b/jsonrpc/filter_manager.go index 03bacde8ff..b33c293177 100644 --- a/jsonrpc/filter_manager.go +++ b/jsonrpc/filter_manager.go @@ -973,6 +973,7 @@ func (h *headElem) getUpdates() ([]*block, *headElem) { if nextElem.header != nil { res = append(res, nextElem.header) } + cur = nextElem } } diff --git a/jsonrpc/filter_manager_fuzz_test.go b/jsonrpc/filter_manager_fuzz_test.go index 49b46d27dc..2cf0fbb3ee 100644 --- a/jsonrpc/filter_manager_fuzz_test.go +++ b/jsonrpc/filter_manager_fuzz_test.go @@ -102,6 +102,7 @@ func FuzzGetLogsForQuery(f *testing.F) { if len(hash) != types.HashLength { t.Skip() } + blockHash := types.BytesToHash(hash) logQuery := LogQuery{ @@ -157,6 +158,7 @@ func FuzzGetLogFilterFromID(f *testing.F) { if len(address) != types.AddressLength { t.Skip() } + logFilter := &LogQuery{ Addresses: []types.Address{types.BytesToAddress(address)}, toBlock: BlockNumber(toBlock), @@ -165,6 +167,7 @@ func FuzzGetLogFilterFromID(f *testing.F) { retrivedLogFilter, err := m.GetLogFilterFromID( m.NewLogFilter(logFilter, &MockClosedWSConnection{}), ) + if err != nil { assert.Equal(t, logFilter, retrivedLogFilter.query) } diff --git a/jsonrpc/filter_manager_test.go b/jsonrpc/filter_manager_test.go index 2f9f05306d..792a5c6d16 100644 --- a/jsonrpc/filter_manager_test.go +++ b/jsonrpc/filter_manager_test.go @@ -660,6 +660,7 @@ func newMockWsConnWithMsgCh() (*mockWsConn, <-chan []byte) { func TestHeadStream_Basic(t *testing.T) { t.Parallel() + b := newBlockStream(&block{header: header{Hash: types.StringToHash("1")}}) b.push(&block{header: header{Hash: types.StringToHash("2")}}) @@ -722,6 +723,7 @@ func TestHeadStream_Concurrent(t *testing.T) { return } + expect++ if expect == uint64(nMessages) { diff --git a/jsonrpc/helper.go b/jsonrpc/helper.go index becff911b4..abd8e2c783 100644 --- a/jsonrpc/helper.go +++ b/jsonrpc/helper.go @@ -195,6 +195,7 @@ func DecodeTxn(arg *txnArgs, blockNumber uint64, store nonceGetter, forceSetNonc if err != nil { return nil, err } + arg.Nonce = argUintPtr(nonce) } diff --git a/jsonrpc/jsonrpc.go b/jsonrpc/jsonrpc.go index bfae70b15b..4d3cf0fdd1 100644 --- a/jsonrpc/jsonrpc.go +++ b/jsonrpc/jsonrpc.go @@ -158,6 +158,7 @@ func middlewareFactory(config *Config) func(http.Handler) http.Handler { break } } + next.ServeHTTP(w, r) }) } diff --git a/network/identity_e2e_test.go b/network/identity_e2e_test.go index 6d6f7c3ed2..7d493b050a 100644 --- a/network/identity_e2e_test.go +++ b/network/identity_e2e_test.go @@ -45,6 +45,7 @@ func TestIdentityHandshake(t *testing.T) { }, } servers, createErr := createServers(2, params) + if createErr != nil { t.Fatalf("Unable to create servers, %v", createErr) } diff --git a/network/server_test.go b/network/server_test.go index 43f06582a6..c458b5f3b4 100644 --- a/network/server_test.go +++ b/network/server_test.go @@ -654,6 +654,7 @@ func TestRunDial(t *testing.T) { t.Fatalf("Unable to join peer, %v", joinErr) } } + closeServers(servers...) }) @@ -674,6 +675,7 @@ func TestRunDial(t *testing.T) { assert.Error(t, joinErr) } } + closeServers(servers...) }) @@ -766,6 +768,7 @@ func TestSubscribe(t *testing.T) { server := setupServer(t, true) ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(func() { cancel() }) @@ -801,6 +804,7 @@ func TestSubscribe(t *testing.T) { server := setupServer(t, false) ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(func() { cancel() }) diff --git a/state/immutable-trie/copy_trie_test.go b/state/immutable-trie/copy_trie_test.go index 4d678f5eed..7faa764d8f 100644 --- a/state/immutable-trie/copy_trie_test.go +++ b/state/immutable-trie/copy_trie_test.go @@ -14,9 +14,11 @@ func TestCompareModelOfTrieCopy(t *testing.T) { ldbStorageOld := ldbstorage.NewMemStorage() ldbStorageNew := ldbstorage.NewMemStorage() ldb, err := leveldb.Open(ldbStorageOld, nil) + if err != nil { t.Fatal(err) } + defer ldb.Close() ldbNew, err := leveldb.Open(ldbStorageNew, nil) @@ -39,11 +41,14 @@ func TestCompareModelOfTrieCopy(t *testing.T) { } tx.Commit() + stateRoot := trie.Hash() result, err := HashChecker(stateRoot.Bytes(), kv) + if err != nil { t.Fatal(err) } + if stateRoot != result { t.Fatal("Hashes are not equal", stateRoot, result) } @@ -57,6 +62,7 @@ func TestCompareModelOfTrieCopy(t *testing.T) { if err != nil { t.Error(err) } + if stateRoot != result { t.Error("Hashes are not equal", stateRoot, result) } diff --git a/state/immutable-trie/hasher.go b/state/immutable-trie/hasher.go index 38ea53350c..aa5b80a8e3 100644 --- a/state/immutable-trie/hasher.go +++ b/state/immutable-trie/hasher.go @@ -117,6 +117,7 @@ func (t *Txn) Hash() ([]byte, error) { } } else { tmp := val.MarshalTo(nil) + h.hash.Reset() h.hash.Write(tmp) diff --git a/state/runtime/evm/bitmap.go b/state/runtime/evm/bitmap.go index ae6929ea57..7a830bc806 100644 --- a/state/runtime/evm/bitmap.go +++ b/state/runtime/evm/bitmap.go @@ -39,6 +39,7 @@ func (b *bitmap) setCode(code []byte) { // jumpdest b.set(uint64(i)) } + i++ } } diff --git a/state/runtime/evm/bitmap_test.go b/state/runtime/evm/bitmap_test.go index 932fc69a39..b4f6809fb6 100644 --- a/state/runtime/evm/bitmap_test.go +++ b/state/runtime/evm/bitmap_test.go @@ -13,6 +13,7 @@ func TestIsPush(t *testing.T) { if !strings.HasPrefix(OpCode(i).String(), "PUSH") { t.Fatal("err") } + num++ } } diff --git a/state/runtime/evm/dispatch_table.go b/state/runtime/evm/dispatch_table.go index ec7b44b4c5..e7b45264b1 100644 --- a/state/runtime/evm/dispatch_table.go +++ b/state/runtime/evm/dispatch_table.go @@ -22,6 +22,7 @@ func registerRange(from, to OpCode, factory func(n int) instruction, gas uint64) c := 1 for i := from; i <= to; i++ { register(i, handler{factory(c), 0, gas}) + c++ } } diff --git a/state/runtime/evm/dispatch_table_test.go b/state/runtime/evm/dispatch_table_test.go index a3dfe906a6..9c296660aa 100644 --- a/state/runtime/evm/dispatch_table_test.go +++ b/state/runtime/evm/dispatch_table_test.go @@ -29,6 +29,7 @@ func TestPushOpcodes(t *testing.T) { assert.Len(t, res, c) assert.True(t, bytes.HasPrefix(code[1:], res)) + c++ } } diff --git a/state/runtime/evm/evm_test.go b/state/runtime/evm/evm_test.go index 6b20b48e29..f690305fcb 100644 --- a/state/runtime/evm/evm_test.go +++ b/state/runtime/evm/evm_test.go @@ -237,9 +237,11 @@ func TestRun(t *testing.T) { contract := newMockContract(tt.value, tt.gas, tt.code) host := &mockHost{} config := tt.config + if config == nil { config = &chain.ForksInTime{} } + res := evm.Run(contract, host, config) assert.Equal(t, tt.expected, res) }) @@ -408,6 +410,7 @@ func TestRunWithTracer(t *testing.T) { host := &mockHost{ tracer: tracer, } + config := tt.config if config == nil { config = &chain.ForksInTime{} diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 8fc6d3bb19..b7d369b648 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -88,9 +88,11 @@ func opSDiv(c *state) { } else { neg := a.Sign() != b.Sign() b.Div(a.Abs(a), b.Abs(b)) + if neg { b.Neg(b) } + toU256(b) } } @@ -118,9 +120,11 @@ func opSMod(c *state) { } else { neg := a.Sign() < 0 b.Mod(a.Abs(a), b.Abs(b)) + if neg { b.Neg(b) } + toU256(b) } } @@ -1347,6 +1351,7 @@ func (c *state) buildCallContract(op OpCode) (*runtime.Contract, uint64, uint64, return nil, 0, 0, nil } + gas = initialGas.Uint64() } diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index 143921b989..74fa195204 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -639,6 +639,7 @@ func TestSStore(t *testing.T) { mockHost := &mockHost{} mockHost.On("SetStorage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(runtime.StorageUnchanged).Once() + s.host = mockHost s.push(one) @@ -659,6 +660,7 @@ func TestSStore(t *testing.T) { mockHost := &mockHost{} mockHost.On("SetStorage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(runtime.StorageModified).Once() + s.host = mockHost s.push(one) @@ -676,6 +678,7 @@ func TestSStore(t *testing.T) { mockHost := &mockHost{} mockHost.On("SetStorage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(runtime.StorageAdded).Once() + s.host = mockHost s.push(one) @@ -696,6 +699,7 @@ func TestSStore(t *testing.T) { mockHost := &mockHost{} mockHost.On("SetStorage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(runtime.StorageDeleted).Once() + s.host = mockHost s.push(one) @@ -1093,6 +1097,7 @@ func TestExtCodeCopy(t *testing.T) { t.Run("NonEIP150Fork", func(t *testing.T) { leftGas := uint64(974) + s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() diff --git a/state/runtime/evm/state.go b/state/runtime/evm/state.go index 8f6fa2ebd0..52aba2b9f9 100644 --- a/state/runtime/evm/state.go +++ b/state/runtime/evm/state.go @@ -104,6 +104,7 @@ func (c *state) reset() { return x.SetInt64(0) }, c.stack[i]) } + c.stack = c.stack[:0] c.tmp = c.tmp[:0] c.ret = c.ret[:0] diff --git a/state/transition_test.go b/state/transition_test.go index 47a33ea978..9fabbc5a8e 100644 --- a/state/transition_test.go +++ b/state/transition_test.go @@ -153,6 +153,7 @@ func TestTransfer(t *testing.T) { err := transition.Transfer(tt.from, tt.to, amount) assert.Equal(t, tt.expectedErr, err) + if err == nil { // should move balance oldBalanceOfFrom := big.NewInt(int64(tt.preState[tt.from].Balance)) diff --git a/state/txn.go b/state/txn.go index 0eeb618ff7..168481d22c 100644 --- a/state/txn.go +++ b/state/txn.go @@ -150,7 +150,7 @@ func (txn *Txn) upsertAccount(addr types.Address, create bool, f func(object *St func (txn *Txn) AddSealingReward(addr types.Address, balance *big.Int) { txn.upsertAccount(addr, true, func(object *StateObject) { if object.Suicide { - *object = *newStateObject(txn) + *object = *newStateObject() object.Account.Balance.SetBytes(balance.Bytes()) } else { object.Account.Balance.Add(object.Account.Balance, balance) @@ -366,6 +366,7 @@ func (txn *Txn) IncrNonce(addr types.Address) error { return } + object.Account.Nonce++ }) @@ -447,6 +448,7 @@ func (txn *Txn) Suicide(addr types.Address) bool { suicided = true object.Suicide = true } + if object != nil { object.Account.Balance = new(big.Int) } @@ -536,7 +538,7 @@ func (txn *Txn) Empty(addr types.Address) bool { return obj.Empty() } -func newStateObject(txn *Txn) *StateObject { +func newStateObject() *StateObject { return &StateObject{ Account: &Account{ Balance: big.NewInt(0), @@ -571,6 +573,7 @@ func (txn *Txn) CleanDeleteObjects(deleteEmptyObjects bool) error { if !ok { return false } + if a.Suicide || a.Empty() && deleteEmptyObjects { remove = append(remove, k) } @@ -637,6 +640,7 @@ func (txn *Txn) Commit(deleteEmptyObjects bool) ([]*Object, error) { } else { store.Val = v.([]byte) //nolint:forcetypeassert } + obj.Storage = append(obj.Storage, store) return false diff --git a/txpool/event_subscription_test.go b/txpool/event_subscription_test.go index e7c6412927..d003a71141 100644 --- a/txpool/event_subscription_test.go +++ b/txpool/event_subscription_test.go @@ -123,6 +123,7 @@ func TestEventSubscription_ProcessedEvents(t *testing.T) { // Set the event listener processed := int64(0) + go func() { for range subscription.outputCh { atomic.AddInt64(&processed, 1) @@ -133,6 +134,7 @@ func TestEventSubscription_ProcessedEvents(t *testing.T) { var wg sync.WaitGroup for _, event := range testCase.events { wg.Add(1) + go func(event *proto.TxPoolEvent) { defer wg.Done() @@ -141,8 +143,11 @@ func TestEventSubscription_ProcessedEvents(t *testing.T) { } wg.Wait() + eventWaitCtx, eventWaitFn := context.WithTimeout(context.Background(), 30*time.Second) + defer eventWaitFn() + if _, err := tests.RetryUntilTimeout(eventWaitCtx, func() (interface{}, bool) { return nil, atomic.LoadInt64(&processed) != int64(testCase.expectedProcessed) }); err != nil { diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 13cde912ee..74f915815a 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -152,6 +152,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrInvalidTxType", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.StateTxType) @@ -170,7 +171,9 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrTxTypeNotSupported London hardfork not enabled", func(t *testing.T) { t.Parallel() + pool := setupPool() + pool.forks.RemoveFork(chain.London) tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) @@ -188,6 +191,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrNegativeValue", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -201,6 +205,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrBlockLimitExceeded", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -217,6 +222,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrExtractSignature", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -231,6 +237,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrInvalidSender", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(addr1, 0, 1, types.LegacyTxType) @@ -247,7 +254,9 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrUnderpriced", func(t *testing.T) { t.Parallel() + pool := setupPool() + pool.priceLimit = 1000000 tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) // gasPrice == 1 @@ -261,7 +270,9 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrInvalidAccountState", func(t *testing.T) { t.Parallel() + pool := setupPool() + pool.store = faultyMockStore{} // nonce is 1000000 so ErrNonceTooLow @@ -277,6 +288,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrTxPoolOverflow", func(t *testing.T) { t.Parallel() + pool := setupPool() // fill the pool @@ -293,6 +305,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("FillTxPoolToTheLimit", func(t *testing.T) { t.Parallel() + pool := setupPool() // fill the pool leaving only 1 slot @@ -309,6 +322,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrIntrinsicGas", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -323,6 +337,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrAlreadyKnown", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -340,6 +355,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrAlreadyKnown", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -362,6 +378,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrOversizedData", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -382,6 +399,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrNonceTooLow", func(t *testing.T) { t.Parallel() + pool := setupPool() // faultyMockStore.GetNonce() == 99999 @@ -397,6 +415,7 @@ func TestAddTxErrors(t *testing.T) { t.Run("ErrInsufficientFunds", func(t *testing.T) { t.Parallel() + pool := setupPool() tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) @@ -543,6 +562,7 @@ func TestAddTxHighPressure(t *testing.T) { pool.SetSigner(&mockSigner{}) pool.getOrCreateAccount(addr1) + pool.accounts.get(addr1).nextNonce = 5 // mock high pressure @@ -570,6 +590,7 @@ func TestAddTxHighPressure(t *testing.T) { pool.SetSigner(&mockSigner{}) pool.getOrCreateAccount(addr1) + pool.accounts.get(addr1).nextNonce = 5 // mock high pressure @@ -602,6 +623,7 @@ func TestAddGossipTx(t *testing.T) { pool, err := newTestPool() pool.localPeerID = peer.ID("test") + assert.NoError(t, err) pool.SetSigner(signer) @@ -2191,7 +2213,9 @@ func Test_TxPool_validateTx(t *testing.T) { t.Run("tx input larger than the TxPoolMaxInitCodeSize", func(t *testing.T) { t.Parallel() + pool := setupPool() + pool.forks = chain.AllForksEnabled.Copy() input := make([]byte, state.TxPoolMaxInitCodeSize+1) @@ -2210,7 +2234,9 @@ func Test_TxPool_validateTx(t *testing.T) { t.Run("tx input the same as TxPoolMaxInitCodeSize", func(t *testing.T) { t.Parallel() + pool := setupPool() + pool.forks = chain.AllForksEnabled.Copy() input := make([]byte, state.TxPoolMaxInitCodeSize) @@ -2330,7 +2356,9 @@ func Test_TxPool_validateTx(t *testing.T) { t.Run("eip-1559 tx placed without eip-1559 fork enabled", func(t *testing.T) { t.Parallel() + pool := setupPool() + pool.forks = chain.AllForksEnabled.Copy() pool.forks.RemoveFork(chain.London) @@ -2619,10 +2647,13 @@ func TestResetAccounts_Enqueued(t *testing.T) { // setup prestate totalTx := 0 expectedPromoted := uint64(0) + for addr, txs := range allTxs { expectedPromoted += expected.accounts[addr].promoted + for _, tx := range txs { totalTx++ + assert.NoError(t, pool.addTx(local, tx)) } } @@ -2714,10 +2745,13 @@ func TestResetAccounts_Enqueued(t *testing.T) { // setup prestate expectedEnqueuedTx := 0 expectedPromotedTx := uint64(0) + for addr, txs := range allTxs { expectedPromotedTx += expected.accounts[addr].promoted + for _, tx := range txs { expectedEnqueuedTx++ + assert.NoError(t, pool.addTx(local, tx)) } } @@ -2903,6 +2937,7 @@ func TestExecutablesOrder(t *testing.T) { ) expectedPromotedTx := 0 + for _, txs := range test.allTxs { for _, tx := range txs { expectedPromotedTx++ @@ -2921,8 +2956,10 @@ func TestExecutablesOrder(t *testing.T) { pool.Prepare() var successful []*types.Transaction + for { tx := pool.Peek() + if tx == nil { break } @@ -3102,6 +3139,7 @@ func TestRecovery(t *testing.T) { // setup prestate totalTx := 0 expectedEnqueued := uint64(0) + for addr, txs := range test.allTxs { // preset nonce so promotions can happen acc := pool.getOrCreateAccount(addr) @@ -3112,6 +3150,7 @@ func TestRecovery(t *testing.T) { // send txs for _, sTx := range txs { totalTx++ + assert.NoError(t, pool.addTx(local, sTx.tx)) } } @@ -3124,8 +3163,10 @@ func TestRecovery(t *testing.T) { func() { pool.Prepare() + for { tx := pool.Peek() + if tx == nil { break } @@ -3322,9 +3363,11 @@ func TestGetTxs(t *testing.T) { // send txs expectedPromotedTx := 0 + for _, txs := range test.allTxs { nonce := uint64(0) promotable := uint64(0) + for _, tx := range txs { // send all txs if tx.Nonce() == nonce+promotable { @@ -3419,6 +3462,7 @@ func TestSetSealing(t *testing.T) { // Set initial value pool.sealing.Store(false) + if test.initialValue { pool.sealing.Store(true) } @@ -3700,6 +3744,7 @@ func TestAddTx_TxReplacement(t *testing.T) { pool, err := newTestPool() pool.chainID = big.NewInt(100) + require.NoError(t, err) pool.baseFee = 100 diff --git a/types/rlp_marshal_storage.go b/types/rlp_marshal_storage.go index 6d11d009ab..1c8f5055a0 100644 --- a/types/rlp_marshal_storage.go +++ b/types/rlp_marshal_storage.go @@ -21,6 +21,7 @@ func (b *Body) marshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { for _, tx := range b.Transactions { v0.Set(tx.marshalStoreRLPWith(ar)) } + vv.Set(v0) } @@ -31,6 +32,7 @@ func (b *Body) marshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { for _, uncle := range b.Uncles { v1.Set(uncle.MarshalRLPWith(ar)) } + vv.Set(v1) } From 1fc6f10e3f4ba2cc102f67b51d2b6ac2917ae933 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Thu, 14 Mar 2024 22:48:04 +0100 Subject: [PATCH 07/20] created UTs for methods: eth_createAccessList, eth_getBlockReceipts, txpool_ContentFrom --- jsonrpc/eth_blockchain_test.go | 154 ++++++++++++++++++++++++++++++++ jsonrpc/jsonrpc.go | 1 + jsonrpc/txpool_endpoint.go | 12 +-- jsonrpc/txpool_endpoint_test.go | 121 +++++++++++++++++++++++++ 4 files changed, 282 insertions(+), 6 deletions(-) diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index 1ab4f48408..426f595a99 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -3,6 +3,7 @@ package jsonrpc import ( "errors" "math/big" + "strconv" "testing" "github.com/0xPolygon/polygon-edge/blockchain" @@ -371,6 +372,68 @@ func TestEth_GetTransactionReceipt(t *testing.T) { }) } +func TestEth_GetBlockReceipts(t *testing.T) { + store := newMockBlockStore() + eth := newTestEthEndpoint(store) + block := newTestBlock(1, hash4) + store.add(block) + + txn0 := newTestTransaction(uint64(0), addr0) + txn1 := newTestTransaction(uint64(1), addr1) + + block.Transactions = []*types.Transaction{txn0, txn1} + receipt1 := &types.Receipt{ + Logs: []*types.Log{ + { + // log 0 + Topics: []types.Hash{ + hash1, + }, + }, + { + // log 1 + Topics: []types.Hash{ + hash2, + }, + }, + { + // log 2 + Topics: []types.Hash{ + hash3, + }, + }, + }, + } + receipt1.SetStatus(types.ReceiptSuccess) + + receipt2 := &types.Receipt{ + Logs: []*types.Log{ + { + // log 3 + Topics: []types.Hash{ + hash4, + }, + }, + }, + } + receipt2.SetStatus(types.ReceiptSuccess) + store.receipts[hash4] = []*types.Receipt{receipt1, receipt2} + + res, err := eth.GetBlockReceipts(1) + + assert.NoError(t, err) + assert.NotNil(t, res) + + response := res.([]*receipt) + assert.Equal(t, txn1.Hash(), response[1].TxHash) + assert.Equal(t, 2, len(response)) + assert.Equal(t, block.Hash(), response[1].BlockHash) + assert.NotNil(t, response[1].Logs) + assert.Len(t, response[1].Logs, 1) + assert.Equal(t, uint64(4), uint64(response[1].Logs[0].LogIndex)) + assert.Equal(t, uint64(1), uint64(response[1].Logs[0].TxIndex)) +} + func TestEth_Syncing(t *testing.T) { store := newMockBlockStore() eth := newTestEthEndpoint(store) @@ -564,6 +627,88 @@ func TestEth_Call(t *testing.T) { }) } +func TestEth_CreateAccessList(t *testing.T) { + store := newMockBlockStore() + hashs := make([]types.Hash, 10) + latest := LatestBlockNumber + blockNum1 := BlockNumber(1) + blockNum2 := BlockNumber(2) + + for i := 0; i < 10; i++ { + hashs[i] = types.StringToHash(strconv.Itoa(i)) + block := newTestBlock(uint64(i), hashs[i]) + block.Header.GasUsed = uint64(i * 10) + store.add(block) + } + + eth := newTestEthEndpoint(store) + + txn := &txnArgs{ + From: &addr0, + To: &addr1, + Gas: argUintPtr(100000), + GasPrice: argBytesPtr([]byte{0x64}), + Value: argBytesPtr([]byte{0x64}), + Data: nil, + Nonce: argUintPtr(0), + } + + cases := []struct { + filter BlockNumberOrHash + gas uint64 + err bool + }{ + { + // both fields are empty + BlockNumberOrHash{}, + 90, + true, + }, + { + // return the latest block number + BlockNumberOrHash{BlockNumber: &latest}, + 90, + true, + }, + { + // specific real block number + BlockNumberOrHash{BlockNumber: &blockNum1}, + 10, + true, + }, + { + // specific block number (not found) + BlockNumberOrHash{BlockNumber: &blockNum2}, + 20, + true, + }, + { + // specific block by hash (found). By default all blocks in the mock have hash zero + BlockNumberOrHash{BlockHash: &types.ZeroHash}, + 0, + false, + }, + { + // specific block by hash (not found) + BlockNumberOrHash{BlockHash: &hashs[8]}, + 80, + true, + }, + } + + for _, c := range cases { + res, err := eth.CreateAccessList(txn, c.filter) + if c.err { + assert.NoError(t, err) + assert.NotNil(t, res) + bres := res.(*accessListResult) + assert.Equal(t, argUint64(c.gas), bres.GasUsed) + } else { + assert.Nil(t, err) + } + } +} + type testStore interface { ethStore } @@ -614,6 +759,15 @@ func (m *mockBlockStore) appendBlocksToStore(blocks []*types.Block) { } } +func (m *mockBlockStore) GetHeaderByNumber(num uint64) (*types.Header, bool) { + block, ok := m.GetBlockByNumber(num, true) + if !ok { + return nil, false + } + + return block.Header, block.Header != nil +} + func (m *mockBlockStore) setupLogs() { m.receipts = make(map[types.Hash][]*types.Receipt) diff --git a/jsonrpc/jsonrpc.go b/jsonrpc/jsonrpc.go index bba25b5bd6..e5283e92f2 100644 --- a/jsonrpc/jsonrpc.go +++ b/jsonrpc/jsonrpc.go @@ -150,6 +150,7 @@ func (j *JSONRPC) setupHTTP() error { } j.logger.Info("http server started", "addr", j.config.Addr.String()) + return nil } diff --git a/jsonrpc/txpool_endpoint.go b/jsonrpc/txpool_endpoint.go index f3d6f04847..c6836c7591 100644 --- a/jsonrpc/txpool_endpoint.go +++ b/jsonrpc/txpool_endpoint.go @@ -48,10 +48,10 @@ type StatusResponse struct { // ContentFrom returns the transactions contained within the transaction pool. func (t *TxPool) ContentFrom(addr types.Address) (interface{}, error) { - convertTxMap := func(txMap []*types.Transaction) map[uint64]*transaction { - result := make(map[uint64]*transaction, len(txMap)) - for key, tx := range txMap { - result[uint64(key)] = toTransaction(tx, nil, &types.ZeroHash, nil) + convertTxMap := func(txs []*types.Transaction) map[uint64]*transaction { + result := make(map[uint64]*transaction, len(txs)) + for _, tx := range txs { + result[tx.Nonce()] = toTransaction(tx, nil, &types.ZeroHash, nil) } return result @@ -61,12 +61,12 @@ func (t *TxPool) ContentFrom(addr types.Address) (interface{}, error) { pTxs, ok := pendingTxs[addr] if !ok { - return nil, nil + pTxs = make([]*types.Transaction, 0) } qTxs, ok := queuedTxs[addr] if !ok { - return nil, nil + qTxs = make([]*types.Transaction, 0) } resp := ContentAddressResponse{ diff --git a/jsonrpc/txpool_endpoint_test.go b/jsonrpc/txpool_endpoint_test.go index 3b935f0aef..525ba2bbae 100644 --- a/jsonrpc/txpool_endpoint_test.go +++ b/jsonrpc/txpool_endpoint_test.go @@ -152,6 +152,127 @@ func TestContentEndpoint(t *testing.T) { }) } +func TestContentFrom(t *testing.T) { + t.Parallel() + + t.Run("returns empty ContentAddressResponse if tx pool has no transactions", func(t *testing.T) { + t.Parallel() + + mockStore := newMockTxPoolStore() + txPoolEndpoint := &TxPool{mockStore} + address := types.Address{0x0} + result, _ := txPoolEndpoint.ContentFrom(address) + + response := result.(ContentAddressResponse) + + assert.True(t, mockStore.includeQueued) + assert.Equal(t, 0, len(response.Pending)) + assert.Equal(t, 0, len(response.Queued)) + }) + + t.Run("returns the correct data for the correct address", func(t *testing.T) { + t.Parallel() + + mockStore := newMockTxPoolStore() + address1 := types.Address{0x1} + testTx1 := newTestTransaction(2, address1) + testTx2 := newTestDynamicFeeTransaction(3, address1) + mockStore.pending[address1] = []*types.Transaction{testTx1, testTx2} + txPoolEndpoint := &TxPool{mockStore} + + result, _ := txPoolEndpoint.ContentFrom(address1) + response := result.(ContentAddressResponse) + + assert.Equal(t, 0, len(response.Queued)) + assert.Equal(t, 2, len(response.Pending)) + + txData := response.Pending[testTx1.Nonce()] + assert.NotNil(t, txData) + assert.Equal(t, testTx1.Gas(), uint64(txData.Gas)) + assert.Equal(t, *(testTx1.GasPrice()), big.Int(*txData.GasPrice)) + assert.Equal(t, *(testTx1.GasFeeCap()), big.Int(*txData.GasPrice)) + assert.Equal(t, *(testTx1.GasTipCap()), big.Int(*txData.GasPrice)) + assert.Equal(t, testTx1.To(), txData.To) + assert.Equal(t, testTx1.From(), txData.From) + assert.Equal(t, *(testTx1.Value()), big.Int(txData.Value)) + assert.Equal(t, testTx1.Input(), []byte(txData.Input)) + assert.Equal(t, (*argUint64)(nil), txData.BlockNumber) + assert.Equal(t, (*argUint64)(nil), txData.TxIndex) + + txData = response.Pending[testTx2.Nonce()] + assert.NotNil(t, txData) + assert.Equal(t, (argUint64)(types.DynamicFeeTxType), txData.Type) + assert.Equal(t, testTx2.Gas(), uint64(txData.Gas)) + assert.Nil(t, testTx2.GasPrice()) + assert.Equal(t, *(testTx2.GasFeeCap()), big.Int(*txData.GasFeeCap)) + assert.Equal(t, *(testTx2.GasTipCap()), big.Int(*txData.GasTipCap)) + assert.Equal(t, testTx2.To(), txData.To) + assert.Equal(t, testTx2.From(), txData.From) + assert.Equal(t, *(testTx2.ChainID()), big.Int(*txData.ChainID)) + assert.Equal(t, *(testTx2.Value()), big.Int(txData.Value)) + assert.Equal(t, testTx2.Input(), []byte(txData.Input)) + assert.Equal(t, (*argUint64)(nil), txData.BlockNumber) + assert.Equal(t, (*argUint64)(nil), txData.TxIndex) + }) + + t.Run("returns correct data for queued transaction", func(t *testing.T) { + t.Parallel() + + mockStore := newMockTxPoolStore() + address1, address2 := types.Address{0x1}, types.Address{0x2} + testTx1 := newTestTransaction(2, address1) + testTx2 := newTestDynamicFeeTransaction(1, address2) + mockStore.queued[address1] = []*types.Transaction{testTx1} + mockStore.queued[address2] = []*types.Transaction{testTx2} + txPoolEndpoint := &TxPool{mockStore} + + result, _ := txPoolEndpoint.ContentFrom(address2) + + response := result.(ContentAddressResponse) + assert.Equal(t, 1, len(response.Queued)) + + txData := response.Queued[testTx2.Nonce()] + assert.NotNil(t, txData) + assert.Equal(t, (argUint64)(types.DynamicFeeTxType), txData.Type) + assert.Equal(t, testTx2.Gas(), uint64(txData.Gas)) + assert.Nil(t, testTx2.GasPrice()) + assert.Equal(t, *(testTx2.GasFeeCap()), big.Int(*txData.GasFeeCap)) + assert.Equal(t, *(testTx2.GasTipCap()), big.Int(*txData.GasTipCap)) + assert.Equal(t, testTx2.To(), txData.To) + assert.Equal(t, testTx2.From(), txData.From) + assert.Equal(t, *(testTx2.ChainID()), big.Int(*txData.ChainID)) + assert.Equal(t, *(testTx2.Value()), big.Int(txData.Value)) + assert.Equal(t, testTx2.Input(), []byte(txData.Input)) + assert.Equal(t, (*argUint64)(nil), txData.BlockNumber) + assert.Equal(t, (*argUint64)(nil), txData.TxIndex) + }) + + t.Run("returns correct ContentAddressResponse data for multiple transactions", func(t *testing.T) { + t.Parallel() + + mockStore := newMockTxPoolStore() + address1 := types.Address{0x1} + testTx1 := newTestTransaction(2, address1) + testTx2 := newTestTransaction(4, address1) + testTx3 := newTestTransaction(11, address1) + address2 := types.Address{0x2} + testTx4 := newTestTransaction(7, address2) + testTx5 := newTestTransaction(8, address2) + mockStore.pending[address1] = []*types.Transaction{testTx1, testTx2} + mockStore.pending[address2] = []*types.Transaction{testTx4} + mockStore.queued[address1] = []*types.Transaction{testTx3} + mockStore.queued[address2] = []*types.Transaction{testTx5} + txPoolEndpoint := &TxPool{mockStore} + + result, _ := txPoolEndpoint.ContentFrom(address2) + + response := result.(ContentAddressResponse) + + assert.True(t, mockStore.includeQueued) + assert.Equal(t, 1, len(response.Pending)) + }) +} + func TestInspectEndpoint(t *testing.T) { t.Parallel() From 681665bbcd818df39e421d6237b92f907083eba8 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Thu, 14 Mar 2024 23:57:04 +0100 Subject: [PATCH 08/20] e2e test for eth_getBlockReceipts --- e2e-polybft/e2e/jsonrpc_test.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 8caf872b4a..0f331deaf9 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -389,6 +389,36 @@ func TestE2E_JsonRPC(t *testing.T) { require.NotEqual(t, txn.Receipt().ContractAddress, ethgo.ZeroAddress) }) + t.Run("eth_getBlockReceipts", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + txReceipt := txn.Receipt() + + // Test. The populated fields match with the block + block, err := client.GetBlockByHash(txReceipt.BlockHash, false) + require.NoError(t, err) + + // Test. We can retrieve the receipts by the BlockNumber + receipts, err := client.GetBlockReceipts(ethgo.BlockNumber(txReceipt.BlockNumber)) + require.NoError(t, err) + + for _, receipt := range receipts { + require.Equal(t, receipt.TransactionHash, txn.Receipt().TransactionHash) + require.Equal(t, receipt.BlockNumber, block.Number) + require.Equal(t, receipt.BlockHash, block.Hash) + } + + // Test. The receipt of a deployed contract has the 'ContractAddress' field. + txn = cluster.Deploy(t, acct, contractsapi.TestSimple.Bytecode) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + require.NotEqual(t, txn.Receipt().ContractAddress, ethgo.ZeroAddress) + }) + t.Run("eth_getTransactionByHash", func(t *testing.T) { key1, err := wallet.GenerateKey() require.NoError(t, err) From c7960fe3db0e5697f95fbba34aa518666e8226bb Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Fri, 15 Mar 2024 09:49:13 +0100 Subject: [PATCH 09/20] e2e remove --- e2e-polybft/e2e/jsonrpc_test.go | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 0f331deaf9..8caf872b4a 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -389,36 +389,6 @@ func TestE2E_JsonRPC(t *testing.T) { require.NotEqual(t, txn.Receipt().ContractAddress, ethgo.ZeroAddress) }) - t.Run("eth_getBlockReceipts", func(t *testing.T) { - key1, err := wallet.GenerateKey() - require.NoError(t, err) - txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) - require.NoError(t, txn.Wait()) - require.True(t, txn.Succeed()) - txReceipt := txn.Receipt() - - // Test. The populated fields match with the block - block, err := client.GetBlockByHash(txReceipt.BlockHash, false) - require.NoError(t, err) - - // Test. We can retrieve the receipts by the BlockNumber - receipts, err := client.GetBlockReceipts(ethgo.BlockNumber(txReceipt.BlockNumber)) - require.NoError(t, err) - - for _, receipt := range receipts { - require.Equal(t, receipt.TransactionHash, txn.Receipt().TransactionHash) - require.Equal(t, receipt.BlockNumber, block.Number) - require.Equal(t, receipt.BlockHash, block.Hash) - } - - // Test. The receipt of a deployed contract has the 'ContractAddress' field. - txn = cluster.Deploy(t, acct, contractsapi.TestSimple.Bytecode) - require.NoError(t, txn.Wait()) - require.True(t, txn.Succeed()) - - require.NotEqual(t, txn.Receipt().ContractAddress, ethgo.ZeroAddress) - }) - t.Run("eth_getTransactionByHash", func(t *testing.T) { key1, err := wallet.GenerateKey() require.NoError(t, err) From ace4b5829e36d554f399fceb826b4a40ad814592 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Wed, 20 Mar 2024 00:30:24 +0100 Subject: [PATCH 10/20] CR fix --- jsonrpc/eth_blockchain_test.go | 11 +-------- jsonrpc/eth_endpoint.go | 43 ++++++++++++++++++---------------- jsonrpc/types.go | 33 ++++++++++++++++++++++++++ state/executor.go | 2 ++ state/runtime/runtime.go | 1 + 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index 406f9f7028..175d750601 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -430,7 +430,7 @@ func TestEth_GetBlockReceipts(t *testing.T) { assert.Equal(t, block.Hash(), response[1].BlockHash) assert.NotNil(t, response[1].Logs) assert.Len(t, response[1].Logs, 1) - assert.Equal(t, uint64(4), uint64(response[1].Logs[0].LogIndex)) + assert.Equal(t, uint64(3), uint64(response[1].Logs[0].LogIndex)) assert.Equal(t, uint64(1), uint64(response[1].Logs[0].TxIndex)) } @@ -655,43 +655,36 @@ func TestEth_CreateAccessList(t *testing.T) { cases := []struct { filter BlockNumberOrHash - gas uint64 err bool }{ { // both fields are empty BlockNumberOrHash{}, - 90, true, }, { // return the latest block number BlockNumberOrHash{BlockNumber: &latest}, - 90, true, }, { // specific real block number BlockNumberOrHash{BlockNumber: &blockNum1}, - 10, true, }, { // specific block number (not found) BlockNumberOrHash{BlockNumber: &blockNum2}, - 20, true, }, { // specific block by hash (found). By default all blocks in the mock have hash zero BlockNumberOrHash{BlockHash: &types.ZeroHash}, - 0, false, }, { // specific block by hash (not found) BlockNumberOrHash{BlockHash: &hashs[8]}, - 80, true, }, } @@ -701,8 +694,6 @@ func TestEth_CreateAccessList(t *testing.T) { if c.err { assert.NoError(t, err) assert.NotNil(t, res) - bres := res.(*accessListResult) - assert.Equal(t, argUint64(c.gas), bres.GasUsed) } else { assert.Nil(t, err) } diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index d0d083e77d..0123932580 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -220,12 +220,28 @@ func (e *Eth) CreateAccessList(arg *txnArgs, filter BlockNumberOrHash) (interfac return nil, err } + // If the caller didn't supply the gas limit in the message, then we set it to maximum possible => block gas limit + if transaction.Gas() == 0 { + transaction.SetGas(header.GasLimit) + } + + // Force transaction gas price if empty + if err = e.fillTransactionGasPrice(transaction); err != nil { + return nil, err + } + + // The return value of the execution is saved in the transition (returnValue field) + result, err := e.store.ApplyTxn(header, transaction, nil, true) + if err != nil { + return nil, err + } + res := &accessListResult{ - Accesslist: transaction.AccessList(), - GasUsed: argUint64(header.GasUsed), + Accesslist: toAccessList(result.AccessList), + GasUsed: argUint64(result.GasUsed), } - return res, nil + return res, result.Err } // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. @@ -443,32 +459,19 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { return nil, nil } - blockHash := block.Hash() if len(block.Transactions) == 0 { - e.logger.Warn( - fmt.Sprintf("No transactions found for block with hash [%s]", blockHash.String()), - ) - return nil, nil } + blockHash := block.Hash() receipts, errR := e.store.GetReceiptsByHash(blockHash) - if errR != nil { - // block receipts not found - e.logger.Warn( - fmt.Sprintf("Receipts for block with hash [%s] not found", blockHash.String()), - ) + if errR != nil { return nil, errR } numberOfReceipts := len(receipts) if numberOfReceipts == 0 { - // Receipts not written yet on the db - e.logger.Warn( - fmt.Sprintf("No receipts found for block with hash [%s]", blockHash.String()), - ) - return nil, nil } @@ -479,9 +482,9 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { raw := receipts[i] // accumulate receipt logs indexes from block transactions // that are before the desired transaction - logIndex += len(receipts[i].Logs) logs := toLogs(raw.Logs, uint64(logIndex), uint64(i), block.Header, raw.TxHash) resReceipts[i] = toReceipt(raw, transaction, uint64(i), block.Header, logs) + logIndex += len(receipts[i].Logs) } return resReceipts, nil @@ -647,7 +650,7 @@ func (e *Eth) Call(arg *txnArgs, filter BlockNumberOrHash, apiOverride *stateOve // EstimateGas estimates the gas needed to execute a transaction func (e *Eth) EstimateGas(arg *txnArgs, rawNum *BlockNumber) (interface{}, error) { - number := LatestBlockNumber /* */ + number := LatestBlockNumber if rawNum != nil { number = *rawNum } diff --git a/jsonrpc/types.go b/jsonrpc/types.go index ff3002d081..59d94992de 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -7,6 +7,7 @@ import ( "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" ) @@ -141,6 +142,38 @@ type block struct { Uncles []types.Hash `json:"uncles"` } +func toAccessList(aList *runtime.AccessList) types.TxAccessList { + convertMapToStorageKeys := func(m map[types.Hash]struct{}) []types.Hash { + r := make([]types.Hash, len(m)) + index := 0 + + for key := range m { + r[index] = key + index++ + } + + return r + } + + if aList == nil { + return make(types.TxAccessList, 0) + } + + result := make(types.TxAccessList, len(*aList)) + idx := 0 + + for address, item := range *aList { + result[idx] = types.AccessTuple{ + Address: address, + StorageKeys: convertMapToStorageKeys(item), + } + + idx++ + } + + return result +} + func (b *block) Copy() *block { bb := new(block) *bb = *b diff --git a/state/executor.go b/state/executor.go index 4f094c0c86..14c9c340d7 100644 --- a/state/executor.go +++ b/state/executor.go @@ -667,6 +667,8 @@ func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, er result = t.Call2(msg.From(), *(msg.To()), msg.Input(), value, gasLeft) } + result.AccessList = initialAccessList + refundQuotient := LegacyRefundQuotient if t.config.London { refundQuotient = LondonRefundQuotient diff --git a/state/runtime/runtime.go b/state/runtime/runtime.go index c180c7c777..809b9564d9 100644 --- a/state/runtime/runtime.go +++ b/state/runtime/runtime.go @@ -119,6 +119,7 @@ type ExecutionResult struct { GasUsed uint64 // Total gas used as result of execution Err error // Any error encountered during the execution, listed below Address types.Address // Contract address + AccessList *AccessList // Access list } func (r *ExecutionResult) Succeeded() bool { return r.Err == nil } From 4ece04ec7caec899c03ad97ea019eeef11d080f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Wed, 20 Mar 2024 08:47:24 +0100 Subject: [PATCH 11/20] Remove dummy comment --- state/executor.go | 1 - 1 file changed, 1 deletion(-) diff --git a/state/executor.go b/state/executor.go index 14c9c340d7..50adf1fb39 100644 --- a/state/executor.go +++ b/state/executor.go @@ -884,7 +884,6 @@ func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtim } } - //Berlin: check // we add this to the access-list before taking a snapshot. Even if the creation fails, // the access-list change should not be rolled back according to EIP2929 specs if t.config.Berlin { From a2ce3d5a53d31ed4fa6c0aaefbdeab056d3315e1 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Wed, 20 Mar 2024 19:57:28 +0100 Subject: [PATCH 12/20] CR fix --- jsonrpc/eth_blockchain_test.go | 10 +++++++++ jsonrpc/eth_endpoint.go | 40 +++++++++++++++++++++++----------- jsonrpc/txpool_endpoint.go | 12 ++-------- jsonrpc/types.go | 27 ++++++++++------------- state/executor.go | 2 +- 5 files changed, 51 insertions(+), 40 deletions(-) diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index 175d750601..d0f51632f4 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -759,6 +759,15 @@ func (m *mockBlockStore) GetHeaderByNumber(num uint64) (*types.Header, bool) { return block.Header, block.Header != nil } +func (m *mockBlockStore) GetHeaderByHash(hash types.Hash) (*types.Header, bool) { + block, ok := m.GetBlockByHash(hash, true) + if !ok { + return nil, false + } + + return block.Header, block.Header != nil +} + func (m *mockBlockStore) setupLogs() { m.receipts = make(map[types.Hash][]*types.Receipt) @@ -901,6 +910,7 @@ func (m *mockBlockStore) ApplyTxn(_ *types.Header, _ *types.Transaction, _ types return &runtime.ExecutionResult{ Err: m.ethCallError, ReturnValue: m.returnValue, + AccessList: runtime.NewAccessList(), }, nil } diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index 47a4424e00..f8f6366ee3 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -53,6 +53,9 @@ type ethBlockchainStore interface { // GetBlockByHash gets a block using the provided hash GetBlockByHash(hash types.Hash, full bool) (*types.Block, bool) + // GetHeaderByHash returns the header by his hash + GetHeaderByHash(hash types.Hash) (*types.Header, bool) + // GetBlockByNumber returns a block using the provided number GetBlockByNumber(num uint64, full bool) (*types.Block, bool) @@ -156,51 +159,61 @@ func (e *Eth) GetBlockByHash(hash types.Hash, fullTx bool) (interface{}, error) } // GetHeaderByNumber returns the requested canonical block header. -// * When blockNr is -1 the chain head is returned. -// * When blockNr is -2 the pending chain head is returned. func (e *Eth) GetHeaderByNumber(number BlockNumber) (interface{}, error) { num, err := GetNumericBlockNumber(number, e.store) if err != nil { return nil, err } - block, ok := e.store.GetBlockByNumber(num, true) + header, ok := e.store.GetHeaderByNumber(num) if !ok { return nil, nil } - if err := e.filterExtra(block); err != nil { + headerCopy, err := e.headerFilterExtra(header) + if err != nil { return nil, err } - return toHeader(block.Header), nil + return toHeader(headerCopy), nil } // GetHeaderByHash returns the requested header by hash. func (e *Eth) GetHeaderByHash(hash types.Hash) (interface{}, error) { - block, ok := e.store.GetBlockByHash(hash, true) + header, ok := e.store.GetHeaderByHash(hash) if !ok { return nil, nil } - if err := e.filterExtra(block); err != nil { + headerCopy, err := e.headerFilterExtra(header) + if err != nil { return nil, err } - return toHeader(block.Header), nil + return toHeader(headerCopy), nil } -func (e *Eth) filterExtra(block *types.Block) error { +func (e *Eth) headerFilterExtra(header *types.Header) (*types.Header, error) { // we need to copy it because the store returns header from storage directly // and not a copy, so changing it, actually changes it in storage as well - headerCopy := block.Header.Copy() + headerCopy := header.Copy() filteredExtra, err := e.store.FilterExtra(headerCopy.ExtraData) if err != nil { - return err + return nil, err } headerCopy.ExtraData = filteredExtra + + return headerCopy, err +} + +func (e *Eth) filterExtra(block *types.Block) error { + headerCopy, err := e.headerFilterExtra(block.Header) + if err != nil { + return err + } + // no need to recompute hash (filtered out data is not in the hash in the first place) block.Header = headerCopy @@ -237,11 +250,12 @@ func (e *Eth) CreateAccessList(arg *txnArgs, filter BlockNumberOrHash) (interfac } res := &accessListResult{ - Accesslist: toAccessList(result.AccessList), + Accesslist: toAccessList(*result.AccessList), + Error: result.Err, GasUsed: argUint64(result.GasUsed), } - return res, result.Err + return res, nil } // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. diff --git a/jsonrpc/txpool_endpoint.go b/jsonrpc/txpool_endpoint.go index c6836c7591..9cace9cbe0 100644 --- a/jsonrpc/txpool_endpoint.go +++ b/jsonrpc/txpool_endpoint.go @@ -58,16 +58,8 @@ func (t *TxPool) ContentFrom(addr types.Address) (interface{}, error) { } pendingTxs, queuedTxs := t.store.GetTxs(true) - - pTxs, ok := pendingTxs[addr] - if !ok { - pTxs = make([]*types.Transaction, 0) - } - - qTxs, ok := queuedTxs[addr] - if !ok { - qTxs = make([]*types.Transaction, 0) - } + pTxs, _ := pendingTxs[addr] + qTxs, _ := queuedTxs[addr] resp := ContentAddressResponse{ Pending: convertTxMap(pTxs), diff --git a/jsonrpc/types.go b/jsonrpc/types.go index 712e198175..498b888ed9 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -8,7 +8,6 @@ import ( "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/hex" - "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" "github.com/valyala/fastjson" ) @@ -136,6 +135,7 @@ type header struct { type accessListResult struct { Accesslist types.TxAccessList `json:"accessList"` + Error error `json:"error,omitempty"` GasUsed argUint64 `json:"gasUsed"` } @@ -146,7 +146,7 @@ type block struct { Uncles []types.Hash `json:"uncles"` } -func toAccessList(aList *runtime.AccessList) types.TxAccessList { +func toAccessList(aList map[types.Address]map[types.Hash]struct{}) types.TxAccessList { convertMapToStorageKeys := func(m map[types.Hash]struct{}) []types.Hash { r := make([]types.Hash, len(m)) index := 0 @@ -159,20 +159,15 @@ func toAccessList(aList *runtime.AccessList) types.TxAccessList { return r } - if aList == nil { - return make(types.TxAccessList, 0) - } - - result := make(types.TxAccessList, len(*aList)) - idx := 0 - - for address, item := range *aList { - result[idx] = types.AccessTuple{ - Address: address, - StorageKeys: convertMapToStorageKeys(item), - } - - idx++ + result := make(types.TxAccessList, 0, len(aList)) + for address, item := range aList { + result = append( + result, + types.AccessTuple{ + Address: address, + StorageKeys: convertMapToStorageKeys(item), + }, + ) } return result diff --git a/state/executor.go b/state/executor.go index 50adf1fb39..5274549368 100644 --- a/state/executor.go +++ b/state/executor.go @@ -667,7 +667,7 @@ func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, er result = t.Call2(msg.From(), *(msg.To()), msg.Input(), value, gasLeft) } - result.AccessList = initialAccessList + result.AccessList = t.accessList refundQuotient := LegacyRefundQuotient if t.config.London { From 8df9653e21da780de6de7e45d96893c6167b3066 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Fri, 22 Mar 2024 22:31:13 +0100 Subject: [PATCH 13/20] lint fix --- command/bridge/withdraw/erc1155/withdraw_erc1155.go | 4 ++-- e2e-polybft/e2e/migration_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/command/bridge/withdraw/erc1155/withdraw_erc1155.go b/command/bridge/withdraw/erc1155/withdraw_erc1155.go index 8789ae6d10..27984f4441 100644 --- a/command/bridge/withdraw/erc1155/withdraw_erc1155.go +++ b/command/bridge/withdraw/erc1155/withdraw_erc1155.go @@ -173,12 +173,12 @@ func runCommand(cmd *cobra.Command, _ []string) { } // createWithdrawTxn encodes parameters for withdraw function on child chain predicate contract -func createWithdrawTxn(receivers []types.Address, amounts, TokenIDs []*big.Int) (*ethgo.Transaction, error) { +func createWithdrawTxn(receivers []types.Address, amounts, tokenIDs []*big.Int) (*ethgo.Transaction, error) { withdrawFn := &contractsapi.WithdrawBatchChildERC1155PredicateFn{ ChildToken: types.StringToAddress(wp.TokenAddr), Receivers: receivers, Amounts: amounts, - TokenIDs: TokenIDs, + TokenIDs: tokenIDs, } input, err := withdrawFn.EncodeAbi() diff --git a/e2e-polybft/e2e/migration_test.go b/e2e-polybft/e2e/migration_test.go index 8093ed1e7d..47654a5877 100644 --- a/e2e-polybft/e2e/migration_test.go +++ b/e2e-polybft/e2e/migration_test.go @@ -61,7 +61,7 @@ func TestE2E_Migration(t *testing.T) { relayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(rpcClient)) require.NoError(t, err) - //send transaction to user2 + // send transaction to user2 sendAmount := ethgo.Gwei(10000) receipt, err := relayer.SendTransaction( ðgo.Transaction{ From 6f9b1d3ab37ff4121017121b30812af40b3848b2 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Mon, 25 Mar 2024 22:49:52 +0100 Subject: [PATCH 14/20] CR fix and new tests e2e have been added --- e2e-polybft/e2e/jsonrpc_test.go | 53 +++++++++++++++++++++++++++++++++ jsonrpc/eth_blockchain_test.go | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index b69a365880..01cfd889d1 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -414,6 +414,59 @@ func TestE2E_JsonRPC(t *testing.T) { require.NotEqual(t, ethTxn.From, ethgo.ZeroAddress) }) + t.Run("eth_getHeaderByNumber", func(t *testing.T) { + key1, err := crypto.GenerateECDSAKey() + require.NoError(t, err) + + // Test. We should be able to query the transaction by its hash + txn := cluster.Transfer(t, senderKey, key1.Address(), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + txReceipt := txn.Receipt() + + var header types.Header + err = jsonRPC.Call("eth_getHeaderByNumber", &header, ethgo.BlockNumber(txReceipt.BlockNumber)) + require.NoError(t, err) + + require.Equal(t, txReceipt.BlockNumber, header.Number) + require.Equal(t, txReceipt.BlockHash, header.Hash) + }) + + t.Run("eth_getHeaderByHash", func(t *testing.T) { + key1, err := crypto.GenerateECDSAKey() + require.NoError(t, err) + + // Test. We should be able to query the transaction by its hash + txn := cluster.Transfer(t, senderKey, key1.Address(), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + txReceipt := txn.Receipt() + + var header types.Header + err = jsonRPC.Call("eth_getHeaderByHash", &header, txReceipt.BlockHash) + require.NoError(t, err) + + require.Equal(t, txReceipt.BlockNumber, header.Number) + require.Equal(t, txReceipt.BlockHash, header.Hash) + }) + + t.Run("txpool_contentFrom", func(t *testing.T) { + key1, err := crypto.GenerateECDSAKey() + require.NoError(t, err) + + // Test. We should be able to query the transaction by its hash + txn := cluster.Transfer(t, senderKey, key1.Address(), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + txReceipt := txn.Receipt() + + var contentFrom map[uint64]*ethgo.Transaction + err = jsonRPC.Call("txpool_contentFrom", &contentFrom, key1.Address()) + require.NoError(t, err) + + require.Equal(t, txReceipt.TransactionHash, contentFrom[txn.Txn().Nonce()].Hash) + }) + t.Run("debug_traceTransaction", func(t *testing.T) { key1, err := crypto.GenerateECDSAKey() require.NoError(t, err) diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index d0f51632f4..5c03057200 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -695,7 +695,7 @@ func TestEth_CreateAccessList(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, res) } else { - assert.Nil(t, err) + assert.NoError(t, err) } } } From 685e4e0ad7817f48214e1cc4d4b7f5981ded38c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Tue, 26 Mar 2024 10:12:25 +0100 Subject: [PATCH 15/20] Address comments --- e2e-polybft/e2e/jsonrpc_test.go | 4 ---- jsonrpc/eth_endpoint.go | 2 +- jsonrpc/types.go | 27 --------------------------- state/runtime/access_list.go | 25 +++++++++++++++++++++++++ 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 01cfd889d1..89459e8cc7 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -418,7 +418,6 @@ func TestE2E_JsonRPC(t *testing.T) { key1, err := crypto.GenerateECDSAKey() require.NoError(t, err) - // Test. We should be able to query the transaction by its hash txn := cluster.Transfer(t, senderKey, key1.Address(), one) require.NoError(t, txn.Wait()) require.True(t, txn.Succeed()) @@ -436,7 +435,6 @@ func TestE2E_JsonRPC(t *testing.T) { key1, err := crypto.GenerateECDSAKey() require.NoError(t, err) - // Test. We should be able to query the transaction by its hash txn := cluster.Transfer(t, senderKey, key1.Address(), one) require.NoError(t, txn.Wait()) require.True(t, txn.Succeed()) @@ -454,7 +452,6 @@ func TestE2E_JsonRPC(t *testing.T) { key1, err := crypto.GenerateECDSAKey() require.NoError(t, err) - // Test. We should be able to query the transaction by its hash txn := cluster.Transfer(t, senderKey, key1.Address(), one) require.NoError(t, txn.Wait()) require.True(t, txn.Succeed()) @@ -471,7 +468,6 @@ func TestE2E_JsonRPC(t *testing.T) { key1, err := crypto.GenerateECDSAKey() require.NoError(t, err) - // Test. We should be able to query the transaction by its hash txn := cluster.Transfer(t, senderKey, key1.Address(), one) require.NoError(t, txn.Wait()) require.True(t, txn.Succeed()) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index f8f6366ee3..8105f96340 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -250,7 +250,7 @@ func (e *Eth) CreateAccessList(arg *txnArgs, filter BlockNumberOrHash) (interfac } res := &accessListResult{ - Accesslist: toAccessList(*result.AccessList), + Accesslist: result.AccessList.ToTxAccessList(), Error: result.Err, GasUsed: argUint64(result.GasUsed), } diff --git a/jsonrpc/types.go b/jsonrpc/types.go index 498b888ed9..a8055ae791 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -146,33 +146,6 @@ type block struct { Uncles []types.Hash `json:"uncles"` } -func toAccessList(aList map[types.Address]map[types.Hash]struct{}) types.TxAccessList { - convertMapToStorageKeys := func(m map[types.Hash]struct{}) []types.Hash { - r := make([]types.Hash, len(m)) - index := 0 - - for key := range m { - r[index] = key - index++ - } - - return r - } - - result := make(types.TxAccessList, 0, len(aList)) - for address, item := range aList { - result = append( - result, - types.AccessTuple{ - Address: address, - StorageKeys: convertMapToStorageKeys(item), - }, - ) - } - - return result -} - func (b *block) Copy() *block { bb := new(block) *bb = *b diff --git a/state/runtime/access_list.go b/state/runtime/access_list.go index 8b806931a5..7471829932 100644 --- a/state/runtime/access_list.go +++ b/state/runtime/access_list.go @@ -113,3 +113,28 @@ func (al *AccessList) DeleteSlot(address types.Address, slot types.Hash) { delete(slotMap, slot) } } + +// ToTxAccessList converts access list from internal representation to the types.TxAccessList +func (al *AccessList) ToTxAccessList() types.TxAccessList { + convertToKeysSlice := func(m map[types.Hash]struct{}) []types.Hash { + storageKeys := make([]types.Hash, 0, len(m)) + for key := range m { + storageKeys = append(storageKeys, key) + } + + return storageKeys + } + + result := make(types.TxAccessList, 0, len(*al)) + for address, storageKeys := range *al { + result = append( + result, + types.AccessTuple{ + Address: address, + StorageKeys: convertToKeysSlice(storageKeys), + }, + ) + } + + return result +} From b95b8f4d23d3df86490fce5650aae27078c4e561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Tue, 26 Mar 2024 10:28:12 +0100 Subject: [PATCH 16/20] Minor simplification --- jsonrpc/txpool_endpoint.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/jsonrpc/txpool_endpoint.go b/jsonrpc/txpool_endpoint.go index 9cace9cbe0..c2ecc6aac1 100644 --- a/jsonrpc/txpool_endpoint.go +++ b/jsonrpc/txpool_endpoint.go @@ -58,12 +58,9 @@ func (t *TxPool) ContentFrom(addr types.Address) (interface{}, error) { } pendingTxs, queuedTxs := t.store.GetTxs(true) - pTxs, _ := pendingTxs[addr] - qTxs, _ := queuedTxs[addr] - resp := ContentAddressResponse{ - Pending: convertTxMap(pTxs), - Queued: convertTxMap(qTxs), + Pending: convertTxMap(pendingTxs[addr]), + Queued: convertTxMap(queuedTxs[addr]), } return resp, nil From 845579b1b96362b60ccebbe21dd93eedeca2ae81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Tue, 26 Mar 2024 10:40:38 +0100 Subject: [PATCH 17/20] Minor changes in eth_getBlockReceipts --- jsonrpc/eth_endpoint.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index 8105f96340..e79c54381e 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -470,35 +470,33 @@ func (e *Eth) GetBlockReceipts(number BlockNumber) (interface{}, error) { block, ok := e.store.GetBlockByNumber(num, true) if !ok { - return nil, nil + return nil, ErrBlockNotFound } if len(block.Transactions) == 0 { return nil, nil } - blockHash := block.Hash() - receipts, errR := e.store.GetReceiptsByHash(blockHash) - - if errR != nil { - return nil, errR + receipts, err := e.store.GetReceiptsByHash(block.Hash()) + if err != nil { + return nil, err } - numberOfReceipts := len(receipts) - if numberOfReceipts == 0 { + receiptsNum := len(receipts) + if receiptsNum == 0 { return nil, nil } - resReceipts := make([]*receipt, numberOfReceipts) + resReceipts := make([]*receipt, receiptsNum) logIndex := 0 for i, transaction := range block.Transactions { raw := receipts[i] - // accumulate receipt logs indexes from block transactions + // accumulate receipt logs indices from block transactions // that are before the desired transaction logs := toLogs(raw.Logs, uint64(logIndex), uint64(i), block.Header, raw.TxHash) resReceipts[i] = toReceipt(raw, transaction, uint64(i), block.Header, logs) - logIndex += len(receipts[i].Logs) + logIndex += len(raw.Logs) } return resReceipts, nil From fb0ee2905ef888b3dc83c040c90ed9600d10d1e2 Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Tue, 26 Mar 2024 15:31:45 +0100 Subject: [PATCH 18/20] e2e test fix and cr fix --- e2e-polybft/e2e/jsonrpc_test.go | 13 +++++++++---- jsonrpc/txpool_endpoint_test.go | 10 ++++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 89459e8cc7..58a4600ffd 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -428,7 +428,7 @@ func TestE2E_JsonRPC(t *testing.T) { require.NoError(t, err) require.Equal(t, txReceipt.BlockNumber, header.Number) - require.Equal(t, txReceipt.BlockHash, header.Hash) + require.Equal(t, txReceipt.BlockHash, ethgo.Hash(header.Hash)) }) t.Run("eth_getHeaderByHash", func(t *testing.T) { @@ -445,7 +445,7 @@ func TestE2E_JsonRPC(t *testing.T) { require.NoError(t, err) require.Equal(t, txReceipt.BlockNumber, header.Number) - require.Equal(t, txReceipt.BlockHash, header.Hash) + require.Equal(t, txReceipt.BlockHash, ethgo.Hash(header.Hash)) }) t.Run("txpool_contentFrom", func(t *testing.T) { @@ -457,11 +457,16 @@ func TestE2E_JsonRPC(t *testing.T) { require.True(t, txn.Succeed()) txReceipt := txn.Receipt() - var contentFrom map[uint64]*ethgo.Transaction + type ContentAddressResponse struct { + Pending map[uint64]*ethgo.Transaction `json:"pending"` + Queued map[uint64]*ethgo.Transaction `json:"queued"` + } + + var contentFrom ContentAddressResponse err = jsonRPC.Call("txpool_contentFrom", &contentFrom, key1.Address()) require.NoError(t, err) - require.Equal(t, txReceipt.TransactionHash, contentFrom[txn.Txn().Nonce()].Hash) + require.Equal(t, txReceipt.TransactionHash, contentFrom.Pending[txn.Txn().Nonce()].Hash) }) t.Run("debug_traceTransaction", func(t *testing.T) { diff --git a/jsonrpc/txpool_endpoint_test.go b/jsonrpc/txpool_endpoint_test.go index e956bf143d..d776349415 100644 --- a/jsonrpc/txpool_endpoint_test.go +++ b/jsonrpc/txpool_endpoint_test.go @@ -226,7 +226,8 @@ func TestContentFrom(t *testing.T) { mockStore.queued[address2] = []*types.Transaction{testTx2} txPoolEndpoint := &TxPool{mockStore} - result, _ := txPoolEndpoint.ContentFrom(address2) + result, err := txPoolEndpoint.ContentFrom(address2) + assert.NoError(t, err) response := result.(ContentAddressResponse) assert.Equal(t, 1, len(response.Queued)) @@ -264,12 +265,17 @@ func TestContentFrom(t *testing.T) { mockStore.queued[address2] = []*types.Transaction{testTx5} txPoolEndpoint := &TxPool{mockStore} - result, _ := txPoolEndpoint.ContentFrom(address2) + result, err := txPoolEndpoint.ContentFrom(address2) + assert.NoError(t, err) response := result.(ContentAddressResponse) assert.True(t, mockStore.includeQueued) assert.Equal(t, 1, len(response.Pending)) + assert.Equal(t, testTx4.Hash(), response.Pending[testTx4.Nonce()].Hash) + assert.Equal(t, 1, len(response.Queued)) + assert.Equal(t, testTx5.Hash(), response.Queued[testTx5.Nonce()].Hash) + }) } From 469ca4f7d64c7e894764eab240ffc11a6f489d1e Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Tue, 26 Mar 2024 15:43:27 +0100 Subject: [PATCH 19/20] lint fix --- jsonrpc/txpool_endpoint_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/jsonrpc/txpool_endpoint_test.go b/jsonrpc/txpool_endpoint_test.go index d776349415..430f38f93e 100644 --- a/jsonrpc/txpool_endpoint_test.go +++ b/jsonrpc/txpool_endpoint_test.go @@ -275,7 +275,6 @@ func TestContentFrom(t *testing.T) { assert.Equal(t, testTx4.Hash(), response.Pending[testTx4.Nonce()].Hash) assert.Equal(t, 1, len(response.Queued)) assert.Equal(t, testTx5.Hash(), response.Queued[testTx5.Nonce()].Hash) - }) } From 329f1b93e837f5d236556db86a926802e750dd3c Mon Sep 17 00:00:00 2001 From: Novo Sandara Date: Tue, 26 Mar 2024 18:16:24 +0100 Subject: [PATCH 20/20] e2e --- e2e-polybft/e2e/jsonrpc_test.go | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 58a4600ffd..8741c7715d 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -448,27 +448,6 @@ func TestE2E_JsonRPC(t *testing.T) { require.Equal(t, txReceipt.BlockHash, ethgo.Hash(header.Hash)) }) - t.Run("txpool_contentFrom", func(t *testing.T) { - key1, err := crypto.GenerateECDSAKey() - require.NoError(t, err) - - txn := cluster.Transfer(t, senderKey, key1.Address(), one) - require.NoError(t, txn.Wait()) - require.True(t, txn.Succeed()) - txReceipt := txn.Receipt() - - type ContentAddressResponse struct { - Pending map[uint64]*ethgo.Transaction `json:"pending"` - Queued map[uint64]*ethgo.Transaction `json:"queued"` - } - - var contentFrom ContentAddressResponse - err = jsonRPC.Call("txpool_contentFrom", &contentFrom, key1.Address()) - require.NoError(t, err) - - require.Equal(t, txReceipt.TransactionHash, contentFrom.Pending[txn.Txn().Nonce()].Hash) - }) - t.Run("debug_traceTransaction", func(t *testing.T) { key1, err := crypto.GenerateECDSAKey() require.NoError(t, err)