Skip to content

Commit

Permalink
Allow round-tripping of unsigned EIP-1559 signature payloads
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
  • Loading branch information
peterbroadhurst committed Oct 27, 2024
1 parent 6789f16 commit 656dd98
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
25 changes: 18 additions & 7 deletions pkg/ethsigner/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,7 @@ func recoverCommon(tx *Transaction, message []byte, chainID int64, v int64, r, s
}, nil
}

func RecoverEIP1559Transaction(ctx context.Context, rawTx ethtypes.HexBytes0xPrefix, chainID int64) (*ethtypes.Address0xHex, *TransactionWithOriginalPayload, error) {

func decodeEIP1559SignaturePayload(ctx context.Context, rawTx ethtypes.HexBytes0xPrefix, chainID int64, rlpMinLen int) (rlp.List, *Transaction, error) {
if len(rawTx) == 0 || rawTx[0] != TransactionType1559 {
return nil, nil, i18n.NewError(ctx, signermsgs.MsgInvalidEIP1559Transaction, "TransactionType")
}
Expand All @@ -311,18 +310,17 @@ func RecoverEIP1559Transaction(ctx context.Context, rawTx ethtypes.HexBytes0xPre
log.L(ctx).Errorf("Invalid EIP-1559 transaction data '%s': %s", rawTx, err)
return nil, nil, i18n.NewError(ctx, signermsgs.MsgInvalidEIP1559Transaction, err)
}
rlpList := decoded.(rlp.List)

if decoded == nil || len(decoded.(rlp.List)) < 12 {
log.L(ctx).Errorf("Invalid EIP-1559 transaction data '%s': EOF", rawTx)
if len(rlpList) < rlpMinLen {
log.L(ctx).Errorf("Invalid EIP-1559 transaction data (%d RLP elements)", rlpList)
return nil, nil, i18n.NewError(ctx, signermsgs.MsgInvalidEIP1559Transaction, "EOF")
}
rlpList := decoded.(rlp.List)

encodedChainID := rlpList[0].ToData().IntOrZero().Int64()
if encodedChainID != chainID {
return nil, nil, i18n.NewError(ctx, signermsgs.MsgInvalidChainID, chainID, encodedChainID)
}
tx := &Transaction{
return rlpList, &Transaction{
Nonce: (*ethtypes.HexInteger)(rlpList[1].ToData().Int()),
MaxPriorityFeePerGas: (*ethtypes.HexInteger)(rlpList[2].ToData().Int()),
MaxFeePerGas: (*ethtypes.HexInteger)(rlpList[3].ToData().Int()),
Expand All @@ -331,6 +329,19 @@ func RecoverEIP1559Transaction(ctx context.Context, rawTx ethtypes.HexBytes0xPre
Value: (*ethtypes.HexInteger)(rlpList[6].ToData().Int()),
Data: ethtypes.HexBytes0xPrefix(rlpList[7].ToData()),
// No access list support
}, nil
}

func DecodeEIP1559SignaturePayload(ctx context.Context, rawTx ethtypes.HexBytes0xPrefix, chainID int64) (*Transaction, error) {
_, tx, err := decodeEIP1559SignaturePayload(ctx, rawTx, chainID, 9 /* no signature data */)
return tx, err
}

func RecoverEIP1559Transaction(ctx context.Context, rawTx ethtypes.HexBytes0xPrefix, chainID int64) (*ethtypes.Address0xHex, *TransactionWithOriginalPayload, error) {

rlpList, tx, err := decodeEIP1559SignaturePayload(ctx, rawTx, chainID, 12 /* with signature data */)
if err != nil {
return nil, nil, err
}

return recoverCommon(tx,
Expand Down
33 changes: 32 additions & 1 deletion pkg/ethsigner/transaction_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2022 Kaleido, Inc.
// Copyright © 2024 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand Down Expand Up @@ -31,6 +31,7 @@ import (
"github.com/hyperledger/firefly-signer/pkg/secp256k1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

func TestEncodeExistingLegacyEIP155(t *testing.T) {
Expand Down Expand Up @@ -294,6 +295,36 @@ func TestRecoverEIP1559BadStructure(t *testing.T) {
assert.Regexp(t, "FF22084.*EOF", err)
}

func TestDecodeEIP1559SignaturePayloadEmpty(t *testing.T) {
_, err := DecodeEIP1559SignaturePayload(context.Background(), []byte{}, 1001)
assert.Regexp(t, "FF22084.*TransactionType", err)
}

func TestRoundTripEIP1559Payload(t *testing.T) {

txIn := Transaction{
Nonce: ethtypes.NewHexInteger64(3),
GasLimit: ethtypes.NewHexInteger64(40574),
MaxPriorityFeePerGas: ethtypes.NewHexInteger64(505050),
MaxFeePerGas: ethtypes.NewHexInteger64(606060),
To: ethtypes.MustNewAddress("0x497eedc4299dea2f2a364be10025d0ad0f702de3"),
Data: ethtypes.MustNewHexBytes0xPrefix("0xfeedbeef"),
Value: ethtypes.NewHexInteger64(100000000),
}
abiData := txIn.SignaturePayloadEIP1559(1001).Bytes()

txOut, err := DecodeEIP1559SignaturePayload(context.Background(), abiData, 1001)
require.NoError(t, err)

jsonIn, err := json.Marshal(txIn)
require.NoError(t, err)
jsonOut, err := json.Marshal(txOut)
require.NoError(t, err)

require.JSONEq(t, string(jsonIn), string(jsonOut))

}

func TestRecoverEIP1559BadChainID(t *testing.T) {
_, _, err := RecoverEIP1559Transaction(context.Background(), append([]byte{TransactionType1559}, (rlp.List{
rlp.WrapInt(big.NewInt(111)),
Expand Down

0 comments on commit 656dd98

Please sign in to comment.