Skip to content

Commit

Permalink
Implemented GetTransactionByBlockNumber/HashAndIndex, GetBlockTransac…
Browse files Browse the repository at this point in the history
…tionCountByHash (#144)

* Implemented eth method GetBlockTransactionCountByHas

* Implemented eth method GetTransactionByBlockNumberAndIndex

* Implemented eth metod GetTransactionByBlockHashAndIndex

* Published methods: GetTransactionByBlockNumberAndIndex,  GetTransactionByBlockHashAndIndex,
GetBlockTransactionCountByHash

* Fix linter issues

* Remove empty line

* Address comments

* Implemented method GetTransactionByBlockAndIndex

* Fix build UT

---------

Co-authored-by: Stefan Negovanović <[email protected]>
  • Loading branch information
novosandara and Stefan-Ethernal authored Mar 6, 2024
1 parent e5d5a9b commit 6d89cb1
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 4 deletions.
71 changes: 71 additions & 0 deletions jsonrpc/eth_blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ func TestEth_Block_BlockNumber(t *testing.T) {
assert.Equal(t, argUintPtr(10), num)
}

func TestEth_Block_GetBlockTransactionCountByHash(t *testing.T) {
store := &mockBlockStore{}
block := newTestBlock(1, hash1)

for i := 0; i < 10; i++ {
block.Transactions = append(block.Transactions, []*types.Transaction{
types.NewTx(&types.LegacyTx{BaseTx: &types.BaseTx{Nonce: 0, From: addr0}})}...)
}
store.add(block)

eth := newTestEthEndpoint(store)

res, err := eth.GetBlockTransactionCountByHash(block.Header.Hash)

assert.NoError(t, err)
assert.NotNil(t, res, "expected to return block, but got nil")
assert.Equal(t, "0xa", res)
}

func TestEth_Block_GetBlockTransactionCountByNumber(t *testing.T) {
store := &mockBlockStore{}
block := newTestBlock(1, hash1)
Expand All @@ -102,6 +121,58 @@ func TestEth_Block_GetBlockTransactionCountByNumber(t *testing.T) {
assert.Equal(t, "0xa", res)
}

func TestEth_Block_GetTransactionByBlockNumberAndIndex(t *testing.T) {
store := &mockBlockStore{}
eth := newTestEthEndpoint(store)
block := newTestBlock(1, hash1)

for i := 0; i < 10; i++ {
txn := newTestTransaction(uint64(i), addr0)
block.Transactions = append(block.Transactions, txn)
}
store.add(block)

testIndex := 5
res, err := eth.GetTransactionByBlockNumberAndIndex(BlockNumber(block.Header.Number), argUint64(testIndex))

transaction := toTransaction(
block.Transactions[testIndex],
argUintPtr(block.Number()),
argHashPtr(block.Hash()),
&testIndex,
)

assert.NoError(t, err)
assert.NotNil(t, res, "expected to return transaction, but got nil")
assert.Equal(t, transaction, res)
}

func TestEth_Block_GetTransactionByBlockHashAndIndex(t *testing.T) {
store := &mockBlockStore{}
block := newTestBlock(1, hash1)

for i := 0; i < 10; i++ {
txn := newTestTransaction(uint64(i), addr0)
block.Transactions = append(block.Transactions, txn)
}
store.add(block)

eth := newTestEthEndpoint(store)
testIndex := 5
res, err := eth.GetTransactionByBlockHashAndIndex(block.Header.Hash, argUint64(testIndex))

transaction := toTransaction(
block.Transactions[testIndex],
argUintPtr(block.Number()),
argHashPtr(block.Hash()),
&testIndex,
)

assert.NoError(t, err)
assert.NotNil(t, res, "expected to return transaction, but got nil")
assert.Equal(t, transaction, res)
}

func TestEth_GetTransactionByHash(t *testing.T) {
t.Parallel()

Expand Down
39 changes: 35 additions & 4 deletions jsonrpc/eth_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ type Eth struct {
priceLimit uint64
}

var (
ErrInsufficientFunds = errors.New("insufficient funds for execution")
)

// ChainId returns the chain id of the client
//
//nolint:stylecheck
Expand Down Expand Up @@ -176,6 +172,16 @@ func (e *Eth) filterExtra(block *types.Block) error {
return 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)
if !ok {
return nil, nil
}

return *common.EncodeUint64(uint64(len(block.Transactions))), nil
}

func (e *Eth) GetBlockTransactionCountByNumber(number BlockNumber) (interface{}, error) {
num, err := GetNumericBlockNumber(number, e.store)
if err != nil {
Expand All @@ -191,6 +197,31 @@ func (e *Eth) GetBlockTransactionCountByNumber(number BlockNumber) (interface{},
return *common.EncodeUint64(uint64(len(block.Transactions))), nil
}

// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (e *Eth) GetTransactionByBlockNumberAndIndex(number BlockNumber, index argUint64) (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
}

return GetTransactionByBlockAndIndex(block, index)
}

// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
func (e *Eth) GetTransactionByBlockHashAndIndex(blockHash types.Hash, index argUint64) (interface{}, error) {
block, ok := e.store.GetBlockByHash(blockHash, true)
if !ok {
return nil, nil
}

return GetTransactionByBlockAndIndex(block, index)
}

// BlockNumber returns current block number
func (e *Eth) BlockNumber() (interface{}, error) {
h := e.store.Header()
Expand Down
19 changes: 19 additions & 0 deletions jsonrpc/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ var (
ErrNegativeBlockNumber = errors.New("invalid argument 0: block number must not be negative")
ErrFailedFetchGenesis = errors.New("error fetching genesis block header")
ErrNoDataInContractCreation = errors.New("contract creation without data provided")
ErrIndexOutOfRange = errors.New("the index is invalid, it is out of range of expected values")
ErrInsufficientFunds = errors.New("insufficient funds for execution")
)

type latestHeaderGetter interface {
Expand Down Expand Up @@ -43,6 +45,23 @@ func GetNumericBlockNumber(number BlockNumber, store latestHeaderGetter) (uint64
}
}

// GetTransactionByBlockAndIndex returns the transaction for the given block and index.
func GetTransactionByBlockAndIndex(block *types.Block, index argUint64) (interface{}, error) {
idx := int(index)
size := len(block.Transactions)

if size == 0 || size < idx {
return nil, ErrIndexOutOfRange
}

return toTransaction(
block.Transactions[index],
argUintPtr(block.Number()),
argHashPtr(block.Hash()),
&idx,
), nil
}

type headerGetter interface {
Header() *types.Header
GetHeaderByNumber(uint64) (*types.Header, bool)
Expand Down

0 comments on commit 6d89cb1

Please sign in to comment.