Skip to content

Commit

Permalink
Merge pull request #101 from INFURA/TXL-22-include-byte-signature-in-…
Browse files Browse the repository at this point in the history
…data-payload

Add input type to allow function selector decoding
  • Loading branch information
antonydenyer authored Jan 17, 2024
2 parents 8b8f17d + 348b328 commit 8a2a672
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 16 deletions.
2 changes: 1 addition & 1 deletion eth/block_from_raw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func TestBlock_FromRaw_EIP2930(t *testing.T) {
Gas: *eth.MustQuantity("0x7a120"),
GasPrice: eth.MustQuantity("0x1"),
Hash: *eth.MustHash("0x0503e1a4ead116b0d1c942c47d54d54d10ed5eaf3a57d2e974bc5cb2e8ee0c47"),
Input: *eth.MustData("0x1a8451e600000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000001000"),
Input: *eth.MustInput("0x1a8451e600000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000001000"),
Nonce: *eth.MustQuantity("0xd"),
To: eth.MustAddress("0xcccccccccccccccccccccccccccccccccccccccc"),
Index: eth.MustQuantity("0xd"),
Expand Down
4 changes: 2 additions & 2 deletions eth/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func TestMainnetGethBlocks(t *testing.T) {
require.Equal(t, eth.Data("0xd783010302844765746887676f312e352e31856c696e7578"), block.ExtraData)
require.Equal(t, true, block.Transactions[0].Populated)
require.Equal(t, int64(0), block.Transactions[0].Index.Int64())
require.Equal(t, eth.Data("0x"), block.Transactions[0].Input)
require.Equal(t, eth.Input("0x"), block.Transactions[0].Input)

j, err := json.Marshal(&block)
require.NoError(t, err)
Expand Down Expand Up @@ -179,7 +179,7 @@ func TestMainnetParityBlocks(t *testing.T) {
require.Equal(t, eth.Data("0xd783010302844765746887676f312e352e31856c696e7578"), block.ExtraData)
require.Equal(t, true, block.Transactions[0].Populated)
require.Equal(t, int64(0), block.Transactions[0].Index.Int64())
require.Equal(t, eth.Data("0x"), block.Transactions[0].Input)
require.Equal(t, eth.Input("0x"), block.Transactions[0].Input)

j, err := json.Marshal(&block)
require.NoError(t, err)
Expand Down
20 changes: 20 additions & 0 deletions eth/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
)

type Data string
type Data4 Data
type Data8 Data
type Data20 Data
type Data32 Data
Expand All @@ -31,6 +32,16 @@ func NewData(value string) (*Data, error) {
return &d, nil
}

func NewData4(value string) (*Data4, error) {
parsed, err := validateHex(value, 4, "data")
if err != nil {
return nil, err
}

d := Data4(parsed)
return &d, nil
}

func NewData8(value string) (*Data8, error) {
parsed, err := validateHex(value, 8, "data")
if err != nil {
Expand Down Expand Up @@ -88,6 +99,15 @@ func MustData(value string) *Data {
return d
}

func MustData4(value string) *Data4 {
d, err := NewData4(value)
if err != nil {
panic(err)
}

return d
}

func MustData8(value string) *Data8 {
d, err := NewData8(value)
if err != nil {
Expand Down
51 changes: 51 additions & 0 deletions eth/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package eth

import (
"github.com/INFURA/go-ethlibs/rlp"
"github.com/pkg/errors"
"strings"
)

type Input Data

func NewInput(value string) (*Input, error) {
if !strings.HasPrefix(value, "0x") {
return nil, errors.Errorf("invalid input: %s", value)
}

a := Input(value)
return &a, nil
}

func MustInput(value string) *Input {
a, err := NewInput(value)
if err != nil {
panic(err)
}

return a
}

func (i Input) String() string {
return string(i)
}

func (i Input) Bytes() []byte {
return Data(i).Bytes()
}

// RLP returns the Input as an RLP-encoded string, note Input can never be null
func (i Input) RLP() rlp.Value {
return rlp.Value{
String: strings.ToLower(i.String()),
}
}

func (i Input) FunctionSelector() *Data4 {
if len(i) >= 10 {
b := Data4(i[:10])
return &b
}

return nil
}
33 changes: 33 additions & 0 deletions eth/input_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package eth

import (
"github.com/stretchr/testify/require"
"testing"
)

func TestInput_FunctionSelector(t *testing.T) {
t.Run("empty input is nil", func(t *testing.T) {
input, err := NewInput("0x")
require.NoError(t, err)
require.Nil(t, input.FunctionSelector())
})

t.Run("short input is nil", func(t *testing.T) {
input, err := NewInput("0x1234")
require.NoError(t, err)
require.Nil(t, input.FunctionSelector())
})

t.Run("exact input returns selector", func(t *testing.T) {
input, err := NewInput("0x2fbbe334")
require.NoError(t, err)
require.Equal(t, input.FunctionSelector(), MustData4("0x2fbbe334"))
})

t.Run("input with arg returns selector", func(t *testing.T) {
input, err := NewInput("0xa41368620000000000000000000000000000000000000000000000000000000000000020")
require.NoError(t, err)
require.Equal(t, input.FunctionSelector(), MustData4("0xa4136862"))
})

}
4 changes: 2 additions & 2 deletions eth/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Transaction struct {
From Address `json:"from"`
Gas Quantity `json:"gas"`
Hash Hash `json:"hash"`
Input Data `json:"input"`
Input Input `json:"input"`
Nonce Quantity `json:"nonce"`
To *Address `json:"to"`
Index *Quantity `json:"transactionIndex"`
Expand Down Expand Up @@ -366,7 +366,7 @@ func (t Transaction) MarshalJSON() ([]byte, error) {
Gas Quantity `json:"gas"`
GasPrice *Quantity `json:"gasPrice"`
Hash Hash `json:"hash"`
Input Data `json:"input"`
Input Input `json:"input"`
Nonce Quantity `json:"nonce"`
To *Address `json:"to"`
Index *Quantity `json:"transactionIndex"`
Expand Down
18 changes: 12 additions & 6 deletions eth/transaction_from_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (t *Transaction) FromRaw(input string) error {
maxFeePerGas Quantity
to *Address
value Quantity
data Data
data Input
v Quantity
r Quantity
s Quantity
Expand Down Expand Up @@ -332,11 +332,11 @@ func (t *Transaction) FromRaw(input string) error {
// Note that when calling this function, the receivers MUST be pointers never values, and for "optional" receivers
// such as Address a pointer to a pointer must be passed. For example:
//
// var (
// addr *eth.Address
// nonce eth.Quantity
// )
// err := rlpDecodeList(payload, &addr, &nonce)
// var (
// addr *eth.Address
// nonce eth.Quantity
// )
// err := rlpDecodeList(payload, &addr, &nonce)
//
// TODO: Consider making this function public once all receiver types in the eth package are supported.
func rlpDecodeList(input interface{}, receivers ...interface{}) error {
Expand Down Expand Up @@ -375,6 +375,12 @@ func rlpDecodeList(input interface{}, receivers ...interface{}) error {
}
*receiver = a
}
case *Input:
d, err := NewInput(value.String)
if err != nil {
return errors.Wrapf(err, "could not decode list item %d to Input", i)
}
*receiver = *d
case *Data:
d, err := NewData(value.String)
if err != nil {
Expand Down
10 changes: 5 additions & 5 deletions eth/transaction_signing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestTransaction_Sign(t *testing.T) {
Gas: eth.QuantityFromUInt64(90000),
To: eth.MustAddress("0xc149Be1bcDFa69a94384b46A1F91350E5f81c1AB"),
Value: eth.QuantityFromUInt64(950000000000000000),
Input: *eth.MustData("0x"),
Input: *eth.MustInput("0x"),
}

// This purposefully uses the already highly compromised keypair from the go-ethereum book:
Expand Down Expand Up @@ -65,7 +65,7 @@ func TestTransaction_Sign_2(t *testing.T) {
Gas: eth.QuantityFromUInt64(22000),
To: eth.MustAddress("0x43700db832E9Ac990D36d6279A846608643c904E"),
Value: eth.QuantityFromUInt64(1000000000),
Input: *eth.MustData("0x"),
Input: *eth.MustInput("0x"),
}

signed, err := tx.Sign("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19", chainId)
Expand Down Expand Up @@ -113,7 +113,7 @@ func TestTransaction_Sign_3(t *testing.T) {
Gas: eth.QuantityFromUInt64(22000),
To: eth.MustAddress("0x43700db832E9Ac990D36d6279A846608643c904E"),
Value: eth.QuantityFromUInt64(1000000000),
Input: *eth.MustData("0x"),
Input: *eth.MustInput("0x"),
}

signed, err := tx.Sign("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19", chainId)
Expand Down Expand Up @@ -201,7 +201,7 @@ func TestTransaction_Sign_EIP2930(t *testing.T) {
ChainId: &chainId,
Gas: eth.QuantityFromInt64(0x62d4),
GasPrice: eth.OptionalQuantityFromInt(0x3b9aca00),
Input: eth.Data("0x"),
Input: eth.Input("0x"),
Nonce: eth.QuantityFromInt64(0),
To: eth.MustAddress("0xdf0a88b2b68c673713a8ec826003676f272e3573"),
Value: eth.QuantityFromInt64(0x1),
Expand Down Expand Up @@ -276,7 +276,7 @@ func TestTransaction_Sign_EIP1559(t *testing.T) {
ChainId: &chainId,
MaxFeePerGas: eth.OptionalQuantityFromInt(15488430592 * 2),
MaxPriorityFeePerGas: eth.OptionalQuantityFromInt(15488430592),
Input: eth.Data("0x"),
Input: eth.Input("0x"),
Nonce: eth.QuantityFromInt64(0),
To: eth.MustAddress("0xdf0a88b2b68c673713a8ec826003676f272e3573"),
Value: eth.QuantityFromInt64(0x1),
Expand Down

0 comments on commit 8a2a672

Please sign in to comment.