diff --git a/action/rlp_tx.go b/action/rlp_tx.go index 2d7c34613c..9d23b2617f 100644 --- a/action/rlp_tx.go +++ b/action/rlp_tx.go @@ -9,17 +9,18 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" "golang.org/x/crypto/sha3" ) -func rlpRawHash(rawTx *types.Transaction, chainID uint32) (hash.Hash256, error) { - h := types.NewEIP155Signer(big.NewInt(int64(chainID))).Hash(rawTx) +func rlpRawHash(rawTx *types.Transaction, signer types.Signer) (hash.Hash256, error) { + h := signer.Hash(rawTx) return hash.BytesToHash256(h[:]), nil } -func rlpSignedHash(tx *types.Transaction, chainID uint32, sig []byte) (hash.Hash256, error) { - signedTx, err := RawTxToSignedTx(tx, chainID, sig) +func rlpSignedHash(tx *types.Transaction, signer types.Signer, sig []byte) (hash.Hash256, error) { + signedTx, err := RawTxToSignedTx(tx, signer, sig) if err != nil { return hash.ZeroHash256, err } @@ -31,7 +32,7 @@ func rlpSignedHash(tx *types.Transaction, chainID uint32, sig []byte) (hash.Hash } // RawTxToSignedTx converts the raw tx to corresponding signed tx -func RawTxToSignedTx(rawTx *types.Transaction, chainID uint32, sig []byte) (*types.Transaction, error) { +func RawTxToSignedTx(rawTx *types.Transaction, signer types.Signer, sig []byte) (*types.Transaction, error) { if len(sig) != 65 { return nil, errors.Errorf("invalid signature length = %d, expecting 65", len(sig)) } @@ -43,7 +44,7 @@ func RawTxToSignedTx(rawTx *types.Transaction, chainID uint32, sig []byte) (*typ // TODO: currently all our web3 tx are EIP-155 protected tx // in the future release, use proper signer for other supported tx types (EIP-1559, EIP-2930) - signedTx, err := rawTx.WithSignature(types.NewEIP155Signer(big.NewInt(int64(chainID))), sc) + signedTx, err := rawTx.WithSignature(signer, sc) if err != nil { return nil, err } @@ -83,3 +84,17 @@ func DecodeRawTx(rawData string, chainID uint32) (tx *types.Transaction, sig []b pubkey, err = crypto.RecoverPubkey(rawHash[:], sig) return } + +// NewEthSigner returns the proper signer for Eth-compatible tx +func NewEthSigner(txType iotextypes.Encoding, chainID uint32) (types.Signer, error) { + // TODO: use proper signer according to tx type + switch txType { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // native tx use same signature format as that of Homestead + return types.HomesteadSigner{}, nil + case iotextypes.Encoding_ETHEREUM_RLP: + return types.NewEIP155Signer(big.NewInt(int64(chainID))), nil + default: + return nil, ErrInvalidAct + } +} diff --git a/action/rlp_tx_test.go b/action/rlp_tx_test.go index 7098a92839..62304643d5 100644 --- a/action/rlp_tx_test.go +++ b/action/rlp_tx_test.go @@ -78,7 +78,9 @@ func TestGenerateRlp(t *testing.T) { require.Contains(err.Error(), v.err) continue } - h, err := rlpSignedHash(tx, _evmNetworkID, v.sig) + signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, _evmNetworkID) + require.NoError(err) + h, err := rlpSignedHash(tx, signer, v.sig) if err != nil { require.Contains(err.Error(), v.err) } @@ -333,7 +335,9 @@ func TestRlpDecodeVerify(t *testing.T) { require.True(bytes.Equal(sig, selp.signature)) raw, err := selp.envelopeHash() require.NoError(err) - rawHash := types.NewEIP155Signer(big.NewInt(int64(_evmNetworkID))).Hash(tx) + signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, _evmNetworkID) + require.NoError(err) + rawHash := signer.Hash(tx) require.True(bytes.Equal(rawHash[:], raw[:])) require.NotEqual(raw, h) require.NoError(selp.VerifySignature()) @@ -395,7 +399,9 @@ func TestIssue3944(t *testing.T) { r.Equal("1b", v.Text(16)) r.NotEqual(hash, tx.Hash().Hex()) // hash does not match with wrong V value in signature - tx1, err := RawTxToSignedTx(tx, 4690, sig) + signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, 4690) + r.NoError(err) + tx1, err := RawTxToSignedTx(tx, signer, sig) r.NoError(err) v, q, s = tx1.RawSignatureValues() r.Equal(sig[:32], q.Bytes()) diff --git a/action/sealedenvelope.go b/action/sealedenvelope.go index d2107e2ede..396a0eff76 100644 --- a/action/sealedenvelope.go +++ b/action/sealedenvelope.go @@ -39,7 +39,11 @@ func (sealed *SealedEnvelope) envelopeHash() (hash.Hash256, error) { if err != nil { return hash.ZeroHash256, err } - return rlpRawHash(tx, sealed.evmNetworkID) + signer, err := NewEthSigner(sealed.encoding, sealed.evmNetworkID) + if err != nil { + return hash.ZeroHash256, err + } + return rlpRawHash(tx, signer) case iotextypes.Encoding_IOTEX_PROTOBUF: return hash.Hash256b(byteutil.Must(proto.Marshal(sealed.Envelope.Proto()))), nil default: @@ -71,7 +75,11 @@ func (sealed *SealedEnvelope) calcHash() (hash.Hash256, error) { if err != nil { return hash.ZeroHash256, err } - return rlpSignedHash(tx, sealed.evmNetworkID, sealed.Signature()) + signer, err := NewEthSigner(sealed.encoding, sealed.evmNetworkID) + if err != nil { + return hash.ZeroHash256, err + } + return rlpSignedHash(tx, signer, sealed.Signature()) case iotextypes.Encoding_IOTEX_PROTOBUF: return hash.Hash256b(byteutil.Must(proto.Marshal(sealed.Proto()))), nil default: @@ -146,7 +154,11 @@ func (sealed *SealedEnvelope) loadProto(pbAct *iotextypes.Action, evmID uint32) if err != nil { return err } - if _, err = rlpSignedHash(tx, evmID, pbAct.GetSignature()); err != nil { + signer, err := NewEthSigner(encoding, evmID) + if err != nil { + return err + } + if _, err = rlpSignedHash(tx, signer, pbAct.GetSignature()); err != nil { return err } sealed.evmNetworkID = evmID diff --git a/api/web3server_integrity_test.go b/api/web3server_integrity_test.go index ab146924ed..ba93323640 100644 --- a/api/web3server_integrity_test.go +++ b/api/web3server_integrity_test.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/iotexproject/go-pkgs/util" "github.com/iotexproject/iotex-address/address" + "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/stretchr/testify/require" "github.com/iotexproject/iotex-core/action" @@ -693,7 +694,9 @@ func web3Staking(t *testing.T, handler *hTTPHandler) { big.NewInt(0), test.data, ) - tx, err := types.SignTx(rawTx, types.NewEIP155Signer(big.NewInt(int64(_evmNetworkID))), ecdsaPvk) + signer, err := action.NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, _evmNetworkID) + require.NoError(err) + tx, err := types.SignTx(rawTx, signer, ecdsaPvk) require.NoError(err) BinaryData, err := tx.MarshalBinary() require.NoError(err) diff --git a/api/web3server_marshal_test.go b/api/web3server_marshal_test.go index 91e4e7c3f5..618058c61d 100644 --- a/api/web3server_marshal_test.go +++ b/api/web3server_marshal_test.go @@ -11,6 +11,7 @@ import ( "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-address/address" + "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/stretchr/testify/require" "github.com/iotexproject/iotex-core/action" @@ -155,7 +156,9 @@ func TestBlockObjectMarshal(t *testing.T) { t.Run("BlockWithDetail", func(t *testing.T) { raw := types.NewContractCreation(2, unit.ConvertIotxToRau(1000), 21000, unit.ConvertIotxToRau(1), []byte{}) - ethTx, err := action.RawTxToSignedTx(raw, 0, sevlp.Signature()) + signer, err := action.NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, 0) + require.NoError(err) + ethTx, err := action.RawTxToSignedTx(raw, signer, sevlp.Signature()) require.NoError(err) tx := &getTransactionResult{ blockHash: _testBlkHash, @@ -230,7 +233,9 @@ func TestTransactionObjectMarshal(t *testing.T) { t.Run("ContractCreation", func(t *testing.T) { raw := types.NewContractCreation(1, big.NewInt(10), 21000, big.NewInt(0), []byte{}) sig, _ := hex.DecodeString("363964383961306166323764636161363766316236326133383335393464393735393961616464326237623136346362343131326161386464666434326638391b") - tx, err := action.RawTxToSignedTx(raw, 4690, sig) + signer, err := action.NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, 4690) + require.NoError(err) + tx, err := action.RawTxToSignedTx(raw, signer, sig) res, err := json.Marshal(&getTransactionResult{ blockHash: _testBlkHash, to: nil, @@ -266,7 +271,9 @@ func TestTransactionObjectMarshal(t *testing.T) { pubkey, _ := crypto.HexStringToPublicKey("04806b217cb0b6a675974689fd99549e525d967287eee9a62dc4e598eea981b8158acfe026da7bf58397108abd0607672832c28ef3bc7b5855077f6e67ab5fc096") actHash, _ := hash.HexStringToHash256("cbc2560d986d79a46bfd96a08d18c6045b29f97352c1360289e371d9cffd6b6a") raw := types.NewContractCreation(305, big.NewInt(0), 297131, big.NewInt(1000000000000), data) - tx, err := action.RawTxToSignedTx(raw, 0, sig) + signer, err := action.NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, 0) + require.NoError(err) + tx, err := action.RawTxToSignedTx(raw, signer, sig) require.NoError(err) res, err := json.Marshal(&getTransactionResult{ blockHash: blkHash, diff --git a/api/web3server_utils.go b/api/web3server_utils.go index 8faa4b456b..a3efdd3cad 100644 --- a/api/web3server_utils.go +++ b/api/web3server_utils.go @@ -19,6 +19,7 @@ import ( "github.com/iotexproject/go-pkgs/util" "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" "github.com/tidwall/gjson" "go.uber.org/zap" @@ -117,7 +118,11 @@ func (svr *web3Handler) getTransactionFromActionInfo(blkHash hash.Hash256, selp if err != nil { return nil, err } - tx, err := action.RawTxToSignedTx(ethTx, svr.coreService.EVMNetworkID(), selp.Signature()) + signer, err := action.NewEthSigner(iotextypes.Encoding(selp.Encoding()), svr.coreService.EVMNetworkID()) + if err != nil { + return nil, err + } + tx, err := action.RawTxToSignedTx(ethTx, signer, selp.Signature()) if err != nil { return nil, err }