Eth TX Encoding (#9531)
This commit is contained in:
parent
57a515f7a8
commit
aa0e6c17b9
@ -6,10 +6,12 @@ import (
|
||||
"fmt"
|
||||
mathbig "math/big"
|
||||
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
gocrypto "github.com/filecoin-project/go-crypto"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v8/eam"
|
||||
@ -57,23 +59,38 @@ type EthTxArgs struct {
|
||||
|
||||
func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
var to *EthAddress
|
||||
params := msg.Params
|
||||
var decodedParams []byte
|
||||
var isCreate bool
|
||||
paramsReader := bytes.NewReader(msg.Params)
|
||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||
to = nil
|
||||
|
||||
var create2 eam.Create2Params
|
||||
reader := bytes.NewReader(msg.Params)
|
||||
if err := create2.UnmarshalCBOR(reader); err != nil {
|
||||
switch msg.Method {
|
||||
case builtintypes.MethodsEAM.Create:
|
||||
var create eam.CreateParams
|
||||
if err := create.UnmarshalCBOR(paramsReader); err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
|
||||
params = create2.Initcode
|
||||
} else {
|
||||
decodedParams = create.Initcode
|
||||
isCreate = true
|
||||
case builtintypes.MethodsEAM.Create2:
|
||||
var create2 eam.Create2Params
|
||||
if err := create2.UnmarshalCBOR(paramsReader); err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
decodedParams = create2.Initcode
|
||||
isCreate = true
|
||||
}
|
||||
}
|
||||
if isCreate {
|
||||
addr, err := EthAddressFromFilecoinIDAddress(msg.To)
|
||||
if err != nil {
|
||||
return EthTxArgs{}, nil
|
||||
}
|
||||
to = &addr
|
||||
params, err := cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||
if err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
decodedParams = params
|
||||
}
|
||||
|
||||
return EthTxArgs{
|
||||
@ -81,7 +98,7 @@ func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
Nonce: int(msg.Nonce),
|
||||
To: to,
|
||||
Value: msg.Value,
|
||||
Input: params,
|
||||
Input: decodedParams,
|
||||
MaxFeePerGas: msg.GasFeeCap,
|
||||
MaxPriorityFeePerGas: msg.GasPremium,
|
||||
GasLimit: int(msg.GasLimit),
|
||||
@ -101,6 +118,7 @@ func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
|
||||
return nil, fmt.Errorf("to and input cannot both be empty")
|
||||
}
|
||||
|
||||
var method abi.MethodNum
|
||||
if tx.To == nil {
|
||||
// TODO https://github.com/filecoin-project/ref-fvm/issues/992
|
||||
// TODO unify with applyEvmMsg
|
||||
@ -119,13 +137,19 @@ func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
|
||||
return nil, fmt.Errorf("failed to serialize Create2 params: %w", err)
|
||||
}
|
||||
params = params2
|
||||
method = builtintypes.MethodsEAM.Create2
|
||||
} else {
|
||||
addr, err := tx.To.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
to = addr
|
||||
params = tx.Input
|
||||
var buf bytes.Buffer
|
||||
if err := cbg.WriteByteArray(&buf, tx.Input); err != nil {
|
||||
return nil, fmt.Errorf("failed to encode tx input into a cbor byte-string")
|
||||
}
|
||||
params = buf.Bytes()
|
||||
method = builtintypes.MethodsEVM.InvokeContract
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
@ -133,7 +157,7 @@ func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
|
||||
From: from,
|
||||
To: to,
|
||||
Value: tx.Value,
|
||||
Method: 2,
|
||||
Method: method,
|
||||
Params: params,
|
||||
GasLimit: int64(tx.GasLimit),
|
||||
GasFeeCap: tx.MaxFeePerGas,
|
||||
|
@ -63,7 +63,7 @@ func TestTxArgs(t *testing.T) {
|
||||
|
||||
func TestTransformParams(t *testing.T) {
|
||||
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
|
||||
Bytecode: mustDecodeHex("0x1122334455"),
|
||||
Initcode: mustDecodeHex("0x1122334455"),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
@ -86,7 +86,7 @@ func TestTransformParams(t *testing.T) {
|
||||
err1 = evmParams.UnmarshalCBOR(reader1)
|
||||
require.Nil(t, err1)
|
||||
|
||||
require.Equal(t, mustDecodeHex("0x1122334455"), evmParams.Bytecode)
|
||||
require.Equal(t, mustDecodeHex("0x1122334455"), evmParams.Initcode)
|
||||
}
|
||||
func TestEcRecover(t *testing.T) {
|
||||
rHex := "0x479ff7fa64cf8bf641eb81635d1e8a698530d2f219951d234539e6d074819529"
|
||||
|
@ -17,6 +17,9 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v8/eam"
|
||||
init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@ -206,10 +209,14 @@ func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxRec
|
||||
Logs: []string{},
|
||||
}
|
||||
|
||||
contractAddr, err := CheckContractCreation(lookup)
|
||||
if err == nil {
|
||||
receipt.To = nil
|
||||
receipt.ContractAddress = contractAddr
|
||||
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
|
||||
// Create and Create2 return the same things.
|
||||
var ret eam.CreateReturn
|
||||
if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
|
||||
return EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err)
|
||||
}
|
||||
addr := EthAddress(ret.EthAddress)
|
||||
receipt.ContractAddress = &addr
|
||||
}
|
||||
|
||||
if lookup.Receipt.ExitCode.IsSuccess() {
|
||||
@ -229,21 +236,6 @@ func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxRec
|
||||
return receipt, nil
|
||||
}
|
||||
|
||||
func CheckContractCreation(lookup *MsgLookup) (*EthAddress, error) {
|
||||
if lookup.Receipt.ExitCode.IsError() {
|
||||
return nil, xerrors.Errorf("message execution was not successful")
|
||||
}
|
||||
var result init8.ExecReturn
|
||||
ret := bytes.NewReader(lookup.Receipt.Return)
|
||||
if err := result.UnmarshalCBOR(ret); err == nil {
|
||||
contractAddr, err := EthAddressFromFilecoinIDAddress(result.IDAddress)
|
||||
if err == nil {
|
||||
return &contractAddr, nil
|
||||
}
|
||||
}
|
||||
return nil, xerrors.Errorf("not a contract creation tx")
|
||||
}
|
||||
|
||||
const (
|
||||
EthAddressLength = 20
|
||||
EthHashLength = 32
|
||||
|
@ -1553,7 +1553,7 @@ var ChainExecEVMCmd = &cli.Command{
|
||||
}
|
||||
|
||||
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
|
||||
Bytecode: contract,
|
||||
Initcode: contract,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to serialize constructor params: %w", err)
|
||||
|
2
go.mod
2
go.mod
@ -133,7 +133,7 @@ require (
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
github.com/urfave/cli/v2 v2.8.1
|
||||
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722
|
||||
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
||||
|
6
go.sum
6
go.sum
@ -353,6 +353,8 @@ github.com/filecoin-project/go-state-types v0.1.11-0.20220929211033-a2339f216f21
|
||||
github.com/filecoin-project/go-state-types v0.1.11-0.20220929211033-a2339f216f21/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.11-0.20221020121916-001de75ef54e h1:Bl8982sk/ZAfoPNszIddnqjfezOJmvyiuzjMR+YhqOY=
|
||||
github.com/filecoin-project/go-state-types v0.1.11-0.20221020121916-001de75ef54e/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.11-0.20221021072238-58379610cafe h1:Wmo0OMEslagGjLvRhlE64wOJIZaBGW01h1w1RATr2bo=
|
||||
github.com/filecoin-project/go-state-types v0.1.11-0.20221021072238-58379610cafe/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=
|
||||
@ -1755,8 +1757,8 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:f
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c h1:6VPKXBDRt7mDUyiHx9X8ROnPYFDf3L7OfEuKCI5dZDI=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722 h1:0HEhvpGQJ2Gd0ngPW83aduQQuF/V9v13+3zpSrR3lrA=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
|
||||
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8=
|
||||
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v8/eam"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v8/evm"
|
||||
init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
@ -232,7 +233,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr api.EthAddress) (api
|
||||
From: from,
|
||||
To: to,
|
||||
Value: big.Zero(),
|
||||
Method: abi.MethodNum(3), // GetBytecode
|
||||
Method: builtintypes.MethodsEVM.GetBytecode,
|
||||
Params: nil,
|
||||
GasLimit: build.BlockGasLimit,
|
||||
GasFeeCap: big.Zero(),
|
||||
@ -320,7 +321,7 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr api.EthAddress,
|
||||
From: from,
|
||||
To: to,
|
||||
Value: big.Zero(),
|
||||
Method: abi.MethodNum(4), // GetStorageAt
|
||||
Method: builtintypes.MethodsEVM.GetStorageAt,
|
||||
Params: params,
|
||||
GasLimit: build.BlockGasLimit,
|
||||
GasFeeCap: big.Zero(),
|
||||
@ -448,7 +449,7 @@ func (a *EthModule) applyEvmMsg(ctx context.Context, tx api.EthCall) (*api.Invoc
|
||||
// https://github.com/filecoin-project/ref-fvm/issues/992
|
||||
to = builtintypes.InitActorAddr
|
||||
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
|
||||
Bytecode: tx.Data,
|
||||
Initcode: tx.Data,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize constructor params: %w", err)
|
||||
@ -472,14 +473,18 @@ func (a *EthModule) applyEvmMsg(ctx context.Context, tx api.EthCall) (*api.Invoc
|
||||
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err)
|
||||
}
|
||||
to = addr
|
||||
params = tx.Data
|
||||
var buf bytes.Buffer
|
||||
if err := cbg.WriteByteArray(&buf, tx.Data); err != nil {
|
||||
return nil, fmt.Errorf("failed to encode tx input into a cbor byte-string")
|
||||
}
|
||||
params = buf.Bytes()
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
From: from,
|
||||
To: to,
|
||||
Value: big.Int(tx.Value),
|
||||
Method: abi.MethodNum(2),
|
||||
Method: builtintypes.MethodsEVM.InvokeContract,
|
||||
Params: params,
|
||||
GasLimit: build.BlockGasLimit,
|
||||
GasFeeCap: big.Zero(),
|
||||
@ -523,7 +528,7 @@ func (a *EthModule) EthCall(ctx context.Context, tx api.EthCall, blkParam string
|
||||
return nil, err
|
||||
}
|
||||
if len(invokeResult.MsgRct.Return) > 0 {
|
||||
return invokeResult.MsgRct.Return, nil
|
||||
return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return)))
|
||||
}
|
||||
return api.EthBytes{}, nil
|
||||
}
|
||||
@ -629,9 +634,31 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
|
||||
}
|
||||
|
||||
toAddr := &toEthAddr
|
||||
_, err = api.CheckContractCreation(msgLookup)
|
||||
if err == nil {
|
||||
input := msg.Params
|
||||
// Check to see if we need to decode as contract deployment.
|
||||
if toFilAddr == builtintypes.EthereumAddressManagerActorAddr {
|
||||
switch msg.Method {
|
||||
case builtintypes.MethodsEAM.Create:
|
||||
toAddr = nil
|
||||
var params eam.CreateParams
|
||||
err = params.UnmarshalCBOR(bytes.NewReader(msg.Params))
|
||||
input = params.Initcode
|
||||
case builtintypes.MethodsEAM.Create2:
|
||||
toAddr = nil
|
||||
var params eam.Create2Params
|
||||
err = params.UnmarshalCBOR(bytes.NewReader(msg.Params))
|
||||
input = params.Initcode
|
||||
}
|
||||
if err != nil {
|
||||
return api.EthTx{}, err
|
||||
}
|
||||
}
|
||||
// Otherwise, try to decode as a cbor byte array.
|
||||
// TODO: Actually check if this is an ethereum call. This code will work for demo purposes, but is not correct.
|
||||
if toAddr != nil {
|
||||
if decodedParams, err := cbg.ReadByteArray(bytes.NewReader(msg.Params), uint64(len(msg.Params))); err == nil {
|
||||
input = decodedParams
|
||||
}
|
||||
}
|
||||
|
||||
tx := api.EthTx{
|
||||
@ -649,7 +676,7 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
|
||||
V: api.EthBytes{},
|
||||
R: api.EthBytes{},
|
||||
S: api.EthBytes{},
|
||||
Input: msg.Params,
|
||||
Input: input,
|
||||
}
|
||||
return tx, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user