Skip to content

Commit

Permalink
fix #18254, Need to throw error when methods are called at future blocks
Browse files Browse the repository at this point in the history
-[x] add unit test for StorageAt rpc call
-[x] Return error message on future block
-[x] add TransactionCount rpc call unit testing

Signed-off-by: Deshi Xiao <xiaods@gmail.com>
  • Loading branch information
xiaods committed Feb 1, 2019
1 parent 05d2143 commit 3508efc
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 2 deletions.
6 changes: 5 additions & 1 deletion eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package eth

import (
"context"
"errors"
"math/big"

"github.com/ethereum/go-ethereum/accounts"
Expand Down Expand Up @@ -94,9 +95,12 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.
}
// Otherwise resolve the block number and return its state
header, err := b.HeaderByNumber(ctx, blockNr)
if header == nil || err != nil {
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header not found at future block")
}
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
return stateDb, header, err
}
Expand Down
178 changes: 177 additions & 1 deletion ethclient/ethclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
package ethclient

import (
"context"
"fmt"
"math/big"
"reflect"
"testing"
"time"

"github.com/ethereum/go-ethereum"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
)

// Verify that Client implements the ethereum interfaces.
Expand Down Expand Up @@ -150,3 +153,176 @@ func TestToFilterArg(t *testing.T) {
})
}
}

func TestNewClient(t *testing.T) {
type args struct {
c *rpc.Client
}
tests := []struct {
name string
args args
want *Client
}{
{
"new Client",
args{},
&Client{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewClient(tt.args.c); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewClient() = %v, want %v", got, tt.want)
}
})
}
}

func TestClient_StorageAt(t *testing.T) {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer cancel()

type fields struct {
c *rpc.Client
}
type args struct {
ctx context.Context
account common.Address
key common.Hash
blockNumber *big.Int
}
tests := []struct {
name string
fields fields
args args
want []byte
wantErr bool
}{
{
"call StorageAt at future block",
fields{
c: &rpc.Client{},
},
args{
ctx: ctx,
account: common.HexToAddress("0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2"),
key: common.HexToHash("0x0"),
blockNumber: big.NewInt(1000000000),
},
[]byte(nil),
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ec := &Client{
c: tt.fields.c,
}
got, err := ec.StorageAt(tt.args.ctx, tt.args.account, tt.args.key, tt.args.blockNumber)
if (err != nil) != tt.wantErr {
t.Errorf("Client.StorageAt() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Client.StorageAt() = %#v, want %#v", got, tt.want)
}
})
}
}

func TestClient_TransactionCount(t *testing.T) {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer cancel()

type fields struct {
c *rpc.Client
}
type args struct {
ctx context.Context
blockHash common.Hash
}
tests := []struct {
name string
fields fields
args args
want uint
wantErr bool
}{
{
"call TransactionCount at future block",
fields{
c: &rpc.Client{},
},
args{
ctx: ctx,
blockHash: common.HexToHash("0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"),
},
0,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ec := &Client{
c: tt.fields.c,
}
got, err := ec.TransactionCount(tt.args.ctx, tt.args.blockHash)
if (err != nil) != tt.wantErr {
t.Errorf("Client.TransactionCount() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Client.TransactionCount() = %v, want %v", got, tt.want)
}
})
}
}

func TestClient_PendingTransactionCount(t *testing.T) {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer cancel()

type fields struct {
c *rpc.Client
}
type args struct {
ctx context.Context
}
tests := []struct {
name string
fields fields
args args
want uint
wantErr bool
}{
{
"call TransactionCount at pending block",
fields{
c: &rpc.Client{},
},
args{
ctx: ctx,
},
0,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ec := &Client{
c: tt.fields.c,
}
got, err := ec.PendingTransactionCount(tt.args.ctx)
if (err != nil) != tt.wantErr {
t.Errorf("Client.PendingTransactionCount() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Client.PendingTransactionCount() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 3508efc

Please sign in to comment.