diff --git a/jsonrpc/codec.go b/jsonrpc/codec.go index 1129ff1cf7..b0c3128941 100644 --- a/jsonrpc/codec.go +++ b/jsonrpc/codec.go @@ -169,6 +169,21 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error { return nil } +// stringToBlockNumberSafe parses string and returns Block Number +// works similar to stringToBlockNumber +// but treats empty string or pending block number as a latest +func stringToBlockNumberSafe(str string) (BlockNumber, error) { + switch str { + case "", pending: + return LatestBlockNumber, nil + default: + return stringToBlockNumber(str) + } +} + +// stringToBlockNumber parses string and returns Block Number +// empty string is treated as an error +// pending blocks are allowed func stringToBlockNumber(str string) (BlockNumber, error) { if str == "" { return 0, fmt.Errorf("value is empty") @@ -176,7 +191,9 @@ func stringToBlockNumber(str string) (BlockNumber, error) { str = strings.Trim(str, "\"") switch str { - case pending, latest: + case pending: + return PendingBlockNumber, nil + case latest: return LatestBlockNumber, nil case earliest: return EarliestBlockNumber, nil diff --git a/jsonrpc/codec_test.go b/jsonrpc/codec_test.go index 2b1c221929..38f41e7219 100644 --- a/jsonrpc/codec_test.go +++ b/jsonrpc/codec_test.go @@ -16,6 +16,7 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) { blockNumberZero := BlockNumber(0x0) blockNumberLatest := LatestBlockNumber + blockNumberPending := PendingBlockNumber tests := []struct { name string @@ -58,6 +59,14 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) { BlockNumber: &blockNumberLatest, }, }, + { + "should unmarshal pending block number properly", + `"pending"`, + false, + BlockNumberOrHash{ + BlockNumber: &blockNumberPending, + }, + }, { "should unmarshal block number 0 properly #1", `{"blockNumber": "0x0"}`, diff --git a/jsonrpc/dispatcher_test.go b/jsonrpc/dispatcher_test.go index e3d1cb780f..ae0331b228 100644 --- a/jsonrpc/dispatcher_test.go +++ b/jsonrpc/dispatcher_test.go @@ -304,7 +304,7 @@ func TestDispatcherFuncDecode(t *testing.T) { { "filter", `[{"fromBlock": "pending", "toBlock": "earliest"}]`, - LogQuery{fromBlock: LatestBlockNumber, toBlock: EarliestBlockNumber}, // pending = latest + LogQuery{fromBlock: LatestBlockNumber, toBlock: EarliestBlockNumber}, // pending == latest }, } diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index e7d7d4d7ec..e517bbb06f 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -498,7 +498,7 @@ func (e *Eth) EstimateGas(arg *txnArgs, rawNum *BlockNumber) (interface{}, error return nil, err } - forksInTime := e.store.GetForksInTime(uint64(number)) + forksInTime := e.store.GetForksInTime(header.Number) var standardGas uint64 if transaction.IsContractCreation() && forksInTime.Homestead { @@ -717,7 +717,7 @@ func (e *Eth) GetTransactionCount(address types.Address, filter BlockNumberOrHas // The filter is empty, use the latest block by default if filter.BlockNumber == nil && filter.BlockHash == nil { - filter.BlockNumber, _ = createBlockNumberPointer("latest") + filter.BlockNumber, _ = createBlockNumberPointer(latest) } if filter.BlockNumber == nil { diff --git a/jsonrpc/helper.go b/jsonrpc/helper.go index a1ac53a4e1..bd0d72b531 100644 --- a/jsonrpc/helper.go +++ b/jsonrpc/helper.go @@ -138,12 +138,9 @@ type nonceGetter interface { func GetNextNonce(address types.Address, number BlockNumber, store nonceGetter) (uint64, error) { if number == PendingBlockNumber { // Grab the latest pending nonce from the TxPool - // // If the account is not initialized in the local TxPool, // return the latest nonce from the world state - res := store.GetNonce(address) - - return res, nil + return store.GetNonce(address), nil } header, err := GetBlockHeader(number, store) diff --git a/jsonrpc/query.go b/jsonrpc/query.go index 765bc423c2..34521160af 100644 --- a/jsonrpc/query.go +++ b/jsonrpc/query.go @@ -90,20 +90,13 @@ func (q *LogQuery) UnmarshalJSON(data []byte) error { q.BlockHash = obj.BlockHash - if obj.FromBlock == "" { - q.fromBlock = LatestBlockNumber - } else { - if q.fromBlock, err = stringToBlockNumber(obj.FromBlock); err != nil { - return err - } + // pending from/to blocks or "" is treated as a latest block + if q.fromBlock, err = stringToBlockNumberSafe(obj.FromBlock); err != nil { + return err } - if obj.ToBlock == "" { - q.toBlock = LatestBlockNumber - } else { - if q.toBlock, err = stringToBlockNumber(obj.ToBlock); err != nil { - return err - } + if q.toBlock, err = stringToBlockNumberSafe(obj.ToBlock); err != nil { + return err } if obj.Address != nil { diff --git a/jsonrpc/query_test.go b/jsonrpc/query_test.go index 34a168d1af..c0b0cfe278 100644 --- a/jsonrpc/query_test.go +++ b/jsonrpc/query_test.go @@ -1,10 +1,11 @@ package jsonrpc import ( - "reflect" "testing" "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -99,13 +100,23 @@ func TestFilterDecode(t *testing.T) { }, }, }, + { + `{ + "fromBlock": "earliest", + "toBlock": "" + }`, + &LogQuery{ + fromBlock: EarliestBlockNumber, + toBlock: LatestBlockNumber, // empty is converted to the latest + }, + }, { `{ "fromBlock": "pending", "toBlock": "earliest" }`, &LogQuery{ - fromBlock: LatestBlockNumber, // pending = latest + fromBlock: LatestBlockNumber, // pending is converted to the latest toBlock: EarliestBlockNumber, }, }, @@ -121,22 +132,15 @@ func TestFilterDecode(t *testing.T) { }, } - for indx, c := range cases { + for _, c := range cases { res := &LogQuery{} err := res.UnmarshalJSON([]byte(c.str)) - if err != nil && c.res != nil { - t.Fatal(err) - } - - if err == nil && c.res == nil { - t.Fatal("it should fail") - } - if c.res != nil { - if !reflect.DeepEqual(res, c.res) { - t.Fatalf("bad %d", indx) - } + require.NoError(t, err) + require.Equal(t, c.res, res) + } else { + require.Error(t, err) } } } @@ -223,9 +227,7 @@ func TestFilterMatch(t *testing.T) { }, } - for indx, c := range cases { - if c.filter.Match(c.log) != c.match { - t.Fatalf("bad %d", indx) - } + for _, c := range cases { + assert.Equal(t, c.match, c.filter.Match(c.log)) } } diff --git a/txpool/txpool.go b/txpool/txpool.go index aa4707a9a8..7def50a235 100644 --- a/txpool/txpool.go +++ b/txpool/txpool.go @@ -811,6 +811,8 @@ func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { } else if oldTxWithSameNonce.GetGasPrice(p.baseFee).Cmp( tx.GetGasPrice(p.baseFee)) >= 0 { // if tx with same nonce does exist and has same or better gas price -> return error + metrics.IncrCounter([]string{txPoolMetrics, "underpriced_tx"}, 1) + return ErrUnderpriced } @@ -822,6 +824,8 @@ func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { // reject low nonce tx if tx.Nonce < accountNonce { + metrics.IncrCounter([]string{txPoolMetrics, "nonce_too_low_tx"}, 1) + return ErrNonceTooLow } }