fix: eth: correctly convert filecoin message <-> eth txn (#10257)
1. We do allow deploying with empty initcode. 2. Make sure that the encoded "code" is non-empty, if specified. Basically, this makes everything consistent (and it's how I specified it in the FIP).
This commit is contained in:
parent
03fd703db5
commit
f427c2b566
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
gocrypto "github.com/filecoin-project/go-crypto"
|
gocrypto "github.com/filecoin-project/go-crypto"
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||||
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
||||||
@ -97,24 +98,31 @@ func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) {
|
|||||||
|
|
||||||
func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
|
func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
|
||||||
var (
|
var (
|
||||||
to *EthAddress
|
to *EthAddress
|
||||||
params []byte
|
params []byte
|
||||||
paramsReader = bytes.NewReader(msg.Params)
|
err error
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if msg.Version != 0 {
|
if msg.Version != 0 {
|
||||||
return EthTxArgs{}, xerrors.Errorf("unsupported msg version: %d", msg.Version)
|
return EthTxArgs{}, xerrors.Errorf("unsupported msg version: %d", msg.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(msg.Params) > 0 {
|
||||||
|
paramsReader := bytes.NewReader(msg.Params)
|
||||||
|
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||||
|
if err != nil {
|
||||||
|
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
||||||
|
}
|
||||||
|
if paramsReader.Len() != 0 {
|
||||||
|
return EthTxArgs{}, xerrors.Errorf("extra data found in params")
|
||||||
|
}
|
||||||
|
if len(params) == 0 {
|
||||||
|
return EthTxArgs{}, xerrors.Errorf("non-empty params encode empty byte array")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||||
switch msg.Method {
|
if msg.Method != builtintypes.MethodsEAM.CreateExternal {
|
||||||
case builtintypes.MethodsEAM.CreateExternal:
|
|
||||||
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
|
||||||
if err != nil {
|
|
||||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return EthTxArgs{}, fmt.Errorf("unsupported EAM method")
|
return EthTxArgs{}, fmt.Errorf("unsupported EAM method")
|
||||||
}
|
}
|
||||||
} else if msg.Method == builtintypes.MethodsEVM.InvokeContract {
|
} else if msg.Method == builtintypes.MethodsEVM.InvokeContract {
|
||||||
@ -123,23 +131,12 @@ func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
|
|||||||
return EthTxArgs{}, err
|
return EthTxArgs{}, err
|
||||||
}
|
}
|
||||||
to = &addr
|
to = &addr
|
||||||
|
|
||||||
if len(msg.Params) > 0 {
|
|
||||||
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
|
||||||
if err != nil {
|
|
||||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return EthTxArgs{},
|
return EthTxArgs{},
|
||||||
xerrors.Errorf("invalid methodnum %d: only allowed method is InvokeContract(%d)",
|
xerrors.Errorf("invalid methodnum %d: only allowed method is InvokeContract(%d)",
|
||||||
msg.Method, builtintypes.MethodsEVM.InvokeContract)
|
msg.Method, builtintypes.MethodsEVM.InvokeContract)
|
||||||
}
|
}
|
||||||
|
|
||||||
if paramsReader.Len() != 0 {
|
|
||||||
return EthTxArgs{}, xerrors.Errorf("extra data found in params")
|
|
||||||
}
|
|
||||||
|
|
||||||
return EthTxArgs{
|
return EthTxArgs{
|
||||||
ChainID: build.Eip155ChainId,
|
ChainID: build.Eip155ChainId,
|
||||||
Nonce: int(msg.Nonce),
|
Nonce: int(msg.Nonce),
|
||||||
@ -159,34 +156,26 @@ func (tx *EthTxArgs) ToUnsignedMessage(from address.Address) (*types.Message, er
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
var params []byte
|
var params []byte
|
||||||
var to address.Address
|
if len(tx.Input) > 0 {
|
||||||
method := builtintypes.MethodsEVM.InvokeContract
|
|
||||||
// nil indicates the EAM, only CreateExternal is allowed
|
|
||||||
if tx.To == nil {
|
|
||||||
to = builtintypes.EthereumAddressManagerActorAddr
|
|
||||||
method = builtintypes.MethodsEAM.CreateExternal
|
|
||||||
if len(tx.Input) == 0 {
|
|
||||||
return nil, xerrors.New("cannot call CreateExternal without params")
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
|
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
|
||||||
return nil, xerrors.Errorf("failed to serialize Create params: %w", err)
|
return nil, xerrors.Errorf("failed to write input args: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
params = buf.Bytes()
|
params = buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
var to address.Address
|
||||||
|
var method abi.MethodNum
|
||||||
|
// nil indicates the EAM, only CreateExternal is allowed
|
||||||
|
if tx.To == nil {
|
||||||
|
method = builtintypes.MethodsEAM.CreateExternal
|
||||||
|
to = builtintypes.EthereumAddressManagerActorAddr
|
||||||
} else {
|
} else {
|
||||||
|
method = builtintypes.MethodsEVM.InvokeContract
|
||||||
to, err = tx.To.ToFilecoinAddress()
|
to, err = tx.To.ToFilecoinAddress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to convert To into filecoin addr: %w", err)
|
return nil, xerrors.Errorf("failed to convert To into filecoin addr: %w", err)
|
||||||
}
|
}
|
||||||
if len(tx.Input) > 0 {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to write input args: %w", err)
|
|
||||||
}
|
|
||||||
params = buf.Bytes()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.Message{
|
return &types.Message{
|
||||||
|
@ -751,18 +751,20 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.Et
|
|||||||
}
|
}
|
||||||
|
|
||||||
var params []byte
|
var params []byte
|
||||||
|
if len(tx.Data) > 0 {
|
||||||
|
initcode := abi.CborBytes(tx.Data)
|
||||||
|
params2, err := actors.SerializeParams(&initcode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to serialize params: %w", err)
|
||||||
|
}
|
||||||
|
params = params2
|
||||||
|
}
|
||||||
|
|
||||||
var to address.Address
|
var to address.Address
|
||||||
var method abi.MethodNum
|
var method abi.MethodNum
|
||||||
if tx.To == nil {
|
if tx.To == nil {
|
||||||
// this is a contract creation
|
// this is a contract creation
|
||||||
to = builtintypes.EthereumAddressManagerActorAddr
|
to = builtintypes.EthereumAddressManagerActorAddr
|
||||||
|
|
||||||
initcode := abi.CborBytes(tx.Data)
|
|
||||||
params2, err := actors.SerializeParams(&initcode)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to serialize Create params: %w", err)
|
|
||||||
}
|
|
||||||
params = params2
|
|
||||||
method = builtintypes.MethodsEAM.CreateExternal
|
method = builtintypes.MethodsEAM.CreateExternal
|
||||||
} else {
|
} else {
|
||||||
addr, err := tx.To.ToFilecoinAddress()
|
addr, err := tx.To.ToFilecoinAddress()
|
||||||
@ -770,15 +772,6 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.Et
|
|||||||
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err)
|
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err)
|
||||||
}
|
}
|
||||||
to = addr
|
to = addr
|
||||||
|
|
||||||
if len(tx.Data) > 0 {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
method = builtintypes.MethodsEVM.InvokeContract
|
method = builtintypes.MethodsEVM.InvokeContract
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user