Skip to content

Commit

Permalink
Add GetBlockReceipts method
Browse files Browse the repository at this point in the history
  • Loading branch information
MDobak committed Feb 12, 2024
1 parent 84bdff5 commit b2d5d8f
Show file tree
Hide file tree
Showing 5 changed files with 330 additions and 0 deletions.
9 changes: 9 additions & 0 deletions rpc/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@ func (c *baseClient) GetTransactionReceipt(ctx context.Context, hash types.Hash)
return &res, nil
}

// GetBlockReceipts implements the RPC interface.
func (c *baseClient) GetBlockReceipts(ctx context.Context, block types.BlockNumber) ([]*types.TransactionReceipt, error) {
var res []*types.TransactionReceipt
if err := c.transport.Call(ctx, &res, "eth_getBlockReceipts", block); err != nil {
return nil, err
}
return res, nil
}

// GetUncleByBlockHashAndIndex implements the RPC interface.
func (c *baseClient) GetUncleByBlockHashAndIndex(ctx context.Context, hash types.Hash, index uint64) (*types.Block, error) {
var res types.Block
Expand Down
70 changes: 70 additions & 0 deletions rpc/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,76 @@ func TestBaseClient_GetTransactionReceipt(t *testing.T) {
assert.Equal(t, false, receipt.Logs[0].Removed)
}

const mockGetBlockReceiptsRequest = `
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_getBlockReceipts",
"params": [
"0x1"
]
}
`

const mockGetBlockReceiptsResponse = `
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"blockHash": "0x1111111111111111111111111111111111111111111111111111111111111111",
"blockNumber": "0x2222",
"contractAddress": null,
"cumulativeGasUsed": "0x33333",
"effectiveGasPrice": "0x4444444444",
"from": "0x5555555555555555555555555555555555555555",
"gasUsed": "0x66666",
"logs": [
{
"address": "0x7777777777777777777777777777777777777777",
"blockHash": "0x1111111111111111111111111111111111111111111111111111111111111111",
"blockNumber": "0x2222",
"data": "0x000000000000000000000000398137383b3d25c92898c656696e41950e47316b00000000000000000000000000000000000000000000000000000000000cee6100000000000000000000000000000000000000000000000000000000000ac3e100000000000000000000000000000000000000000000000000000000005baf35",
"logIndex": "0x8",
"removed": false,
"topics": [
"0x9999999999999999999999999999999999999999999999999999999999999999"
],
"transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"transactionIndex": "0x11"
}
],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000200000000000000000000000000000",
"status": "0x1",
"to": "0x7777777777777777777777777777777777777777",
"transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"transactionIndex": "0x11",
"type": "0x0"
}
]
}
`

func TestBaseClient_GetBlockReceipts(t *testing.T) {
httpMock := newHTTPMock()
client := &baseClient{transport: httpMock}

httpMock.ResponseMock = &http.Response{
StatusCode: 200,
Body: io.NopCloser(bytes.NewBufferString(mockGetBlockReceiptsResponse)),
}

receipts, err := client.GetBlockReceipts(
context.Background(),
types.MustBlockNumberFromHex("0x1"),
)

require.NoError(t, err)
assert.JSONEq(t, mockGetBlockReceiptsRequest, readBody(httpMock.Request))
require.Len(t, receipts, 1)
assert.Equal(t, types.MustHashFromHex("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", types.PadNone), receipts[0].TransactionHash)
}

const mockGetUncleByBlockHashAndIndexRequest = `
{
"jsonrpc": "2.0",
Expand Down
5 changes: 5 additions & 0 deletions rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ type RPC interface {
// It returns the receipt of a transaction by transaction hash.
GetTransactionReceipt(ctx context.Context, hash types.Hash) (*types.TransactionReceipt, error)

// GetBlockReceipts performs eth_getBlockReceipts RPC call.
//
// It returns all transaction receipts for a given block hash or number.
GetBlockReceipts(ctx context.Context, block types.BlockNumber) ([]*types.TransactionReceipt, error)

// GetUncleByBlockHashAndIndex performs eth_getUncleByBlockNumberAndIndex RPC call.
//
// It returns information about an uncle of a block by number and uncle index position.
Expand Down
27 changes: 27 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,33 @@ func (s Signature) IsZero() bool {
return true
}

// Equal returns true if the signature is equal to the given signature.
//
// Nil values are considered as zero.
func (s Signature) Equal(c Signature) bool {
sv, sr, ss := s.V, s.R, s.S
cv, cr, cs := c.V, c.R, c.S
if sv == nil {
sv = new(big.Int)
}
if sr == nil {
sr = new(big.Int)
}
if ss == nil {
ss = new(big.Int)
}
if cv == nil {
cv = new(big.Int)
}
if cr == nil {
cr = new(big.Int)
}
if cs == nil {
cs = new(big.Int)
}
return sv.Cmp(cv) == 0 && sr.Cmp(cr) == 0 && ss.Cmp(cs) == 0
}

func (s Signature) Copy() *Signature {
cpy := &Signature{}
if s.V != nil {
Expand Down
219 changes: 219 additions & 0 deletions types/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,225 @@ func Test_BlockNumberType_Marshal(t *testing.T) {
}
}

func Test_BlockIdentifierType_Unmarshal(t *testing.T) {
tests := []struct {
arg string
want BlockIdentifier
wantErr bool
}{
{
arg: `"0x0"`,
want: BlockIdentifier{
Number: BlockNumberFromUint64Ptr(0),
Hash: nil,
},
},
{
arg: `"0xF"`,
want: BlockIdentifier{
Number: BlockNumberFromUint64Ptr(15),
Hash: nil,
},
},
{
arg: `"0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"`,
want: BlockIdentifier{
Number: nil,
Hash: MustHashFromHexPtr("0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff", PadNone),
},
},
{
arg: `"latest"`,
want: BlockIdentifier{
Number: &LatestBlockNumber,
Hash: nil,
},
},
{
arg: `"invalid"`,
wantErr: true,
},
}
for n, tt := range tests {
t.Run(fmt.Sprintf("case-%d", n+1), func(t *testing.T) {
v := &BlockIdentifier{}
err := v.UnmarshalJSON([]byte(tt.arg))
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, *v)
}
})
}
}

func Test_BlockIdentifierType_Marshal(t *testing.T) {
tests := []struct {
arg BlockIdentifier
want string
}{
{arg: MustBlockIdentifierFromHex("0x0"), want: `"0x0"`},
{arg: MustBlockIdentifierFromHex("0xf"), want: `"0xf"`},
{arg: MustBlockIdentifierFromHex("0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"), want: `"0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"`},
{arg: MustBlockIdentifierFromHex("latest"), want: `"latest"`},
}
for n, tt := range tests {
t.Run(fmt.Sprintf("case-%d", n+1), func(t *testing.T) {
j, err := tt.arg.MarshalJSON()
assert.NoError(t, err)
assert.Equal(t, tt.want, string(j))
})
}
}

func Test_SignatureType_Unmarshal(t *testing.T) {
tests := []struct {
arg string
want Signature
wantErr bool
}{
{
arg: `"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"`,
want: Signature{
V: big.NewInt(0),
R: big.NewInt(0),
S: big.NewInt(0),
},
},
{
arg: `"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"`,
want: Signature{
V: big.NewInt(0),
R: big.NewInt(0),
S: big.NewInt(0),
},
},
{
arg: `"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021b"`,
want: Signature{
V: big.NewInt(27),
R: big.NewInt(1),
S: big.NewInt(2),
},
},
}
for n, tt := range tests {
t.Run(fmt.Sprintf("case-%d", n+1), func(t *testing.T) {
v := &Signature{}
err := v.UnmarshalJSON([]byte(tt.arg))
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.True(t, tt.want.Equal(*v))
}
})
}
}

func Test_SignatureType_Marshal(t *testing.T) {
tests := []struct {
signature Signature
want string
wantErr bool
}{
{
signature: Signature{},
want: `"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"`,
},
{
signature: Signature{
V: big.NewInt(0),
R: big.NewInt(0),
S: big.NewInt(0),
},
want: `"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"`,
},
{
signature: Signature{
V: big.NewInt(27),
R: big.NewInt(1),
S: big.NewInt(2),
},
want: `"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021b"`,
},
}
for n, tt := range tests {
t.Run(fmt.Sprintf("case-%d", n+1), func(t *testing.T) {
j, err := tt.signature.MarshalJSON()
assert.NoError(t, err)
assert.Equal(t, tt.want, string(j))
})
}
}

func Test_SignatureType_Equal(t *testing.T) {
tests := []struct {
a, b Signature
want bool
}{
{
a: Signature{},
b: Signature{},
want: true,
},
{
a: Signature{},
b: Signature{
V: big.NewInt(0),
R: big.NewInt(0),
S: big.NewInt(0),
},
want: true,
},
{
a: Signature{
V: big.NewInt(0),
R: nil,
S: big.NewInt(0),
},
b: Signature{
V: nil,
R: big.NewInt(0),
S: big.NewInt(0),
},
want: true,
},
{
a: Signature{
V: big.NewInt(27),
R: big.NewInt(1),
S: big.NewInt(2),
},
b: Signature{
V: big.NewInt(27),
R: big.NewInt(1),
S: big.NewInt(2),
},
want: true,
},
{
a: Signature{
V: big.NewInt(27),
R: nil,
S: big.NewInt(2),
},
b: Signature{
V: nil,
R: big.NewInt(2),
S: big.NewInt(2),
},
want: false,
},
}
for n, tt := range tests {
t.Run(fmt.Sprintf("case-%d", n+1), func(t *testing.T) {
assert.Equal(t, tt.want, tt.a.Equal(tt.b))
})
}
}

func Test_BytesType_Unmarshal(t *testing.T) {
tests := []struct {
arg string
Expand Down

0 comments on commit b2d5d8f

Please sign in to comment.