Skip to content

Commit

Permalink
Merge pull request #85 from hyperledger/err-flexibility
Browse files Browse the repository at this point in the history
Allow formatting of string errors separately from matching
  • Loading branch information
awrichar authored Nov 1, 2024
2 parents 1608ddc + 656dd98 commit b366550
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 25 deletions.
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

0 comments on commit b366550

Please sign in to comment.