Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow formatting of string errors separately from matching #85

Merged
merged 4 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 28 additions & 17 deletions pkg/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,29 +340,40 @@ func (a ABI) ErrorString(revertData []byte) (string, bool) {
return a.ErrorStringCtx(context.Background(), revertData)
}

func (a ABI) ErrorStringCtx(ctx context.Context, revertData []byte) (string, bool) {
var parsed []interface{}
func (a ABI) ErrorStringCtx(ctx context.Context, revertData []byte) (strError string, ok bool) {
e, cv, ok := a.ParseErrorCtx(ctx, revertData)
if ok {
if res, err := NewSerializer().SetFormattingMode(FormatAsFlatArrays).SerializeInterfaceCtx(ctx, cv); err == nil {
parsed, ok = res.([]interface{})
}
strError = FormatErrorStringCtx(ctx, e, cv)
ok = strError != ""
}
if !ok || parsed == nil {
return "", false
return strError, ok
}

func FormatErrorStringCtx(ctx context.Context, e *Entry, cv *ComponentValue) string {
var ok bool
var parsed []interface{}
if res, err := NewSerializer().
SetFormattingMode(FormatAsFlatArrays).
SetIntSerializer(Base10StringIntSerializer).
SetByteSerializer(HexByteSerializer0xPrefix).
SetAddressSerializer(HexAddrSerializer0xPrefix).
SerializeInterfaceCtx(ctx, cv); err == nil {
parsed, ok = res.([]interface{})
}
buff := new(bytes.Buffer)
buff.WriteString(e.Name)
buff.WriteRune('(')
for i, c := range parsed {
if i > 0 {
buff.WriteRune(',')
buff := new(strings.Builder)
if ok && parsed != nil {
buff.WriteString(e.Name)
buff.WriteRune('(')
for i, c := range parsed {
if i > 0 {
buff.WriteRune(',')
}
b, _ := json.Marshal(c)
buff.Write(b)
}
b, _ := json.Marshal(c)
buff.Write(b)
buff.WriteRune(')')
}
buff.WriteRune(')')
return buff.String(), true
return buff.String()
}

// Validate processes all the components of all the parameters in this ABI entry
Expand Down
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
Loading