Eth JSON-RPC API: Add EAM as contract creator (#9528)
This commit is contained in:
parent
98e534cc77
commit
7e7fff1dc5
@ -7,14 +7,12 @@ import (
|
|||||||
mathbig "math/big"
|
mathbig "math/big"
|
||||||
|
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"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/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"
|
||||||
"github.com/filecoin-project/go-state-types/builtin/v8/evm"
|
"github.com/filecoin-project/go-state-types/builtin/v8/eam"
|
||||||
init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
|
|
||||||
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
@ -60,21 +58,16 @@ type EthTxArgs struct {
|
|||||||
func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||||
var to *EthAddress
|
var to *EthAddress
|
||||||
params := msg.Params
|
params := msg.Params
|
||||||
if msg.To == builtintypes.InitActorAddr {
|
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||||
to = nil
|
to = nil
|
||||||
|
|
||||||
var exec init8.ExecParams
|
var create2 eam.Create2Params
|
||||||
reader := bytes.NewReader(msg.Params)
|
reader := bytes.NewReader(msg.Params)
|
||||||
if err := exec.UnmarshalCBOR(reader); err != nil {
|
if err := create2.UnmarshalCBOR(reader); err != nil {
|
||||||
return EthTxArgs{}, err
|
return EthTxArgs{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var evmParams evm.ConstructorParams
|
params = create2.Initcode
|
||||||
reader1 := bytes.NewReader(exec.ConstructorParams)
|
|
||||||
if err := evmParams.UnmarshalCBOR(reader1); err != nil {
|
|
||||||
return EthTxArgs{}, err
|
|
||||||
}
|
|
||||||
params = evmParams.Bytecode
|
|
||||||
} else {
|
} else {
|
||||||
addr, err := EthAddressFromFilecoinIDAddress(msg.To)
|
addr, err := EthAddressFromFilecoinIDAddress(msg.To)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,27 +106,19 @@ func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
|
|||||||
// TODO unify with applyEvmMsg
|
// TODO unify with applyEvmMsg
|
||||||
|
|
||||||
// this is a contract creation
|
// this is a contract creation
|
||||||
to = builtintypes.InitActorAddr
|
to = builtintypes.EthereumAddressManagerActorAddr
|
||||||
|
|
||||||
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
|
var salt [32]byte
|
||||||
Bytecode: tx.Input,
|
binary.BigEndian.PutUint64(salt[:], uint64(tx.Nonce))
|
||||||
|
|
||||||
|
params2, err := actors.SerializeParams(&eam.Create2Params{
|
||||||
|
Initcode: tx.Input,
|
||||||
|
Salt: salt,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to serialize constructor params: %w", err)
|
return nil, fmt.Errorf("failed to serialize Create2 params: %w", err)
|
||||||
}
|
|
||||||
|
|
||||||
evmActorCid, ok := actors.GetActorCodeID(actors.Version8, "evm")
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("failed to lookup evm actor code CID")
|
|
||||||
}
|
|
||||||
|
|
||||||
params, err = actors.SerializeParams(&init8.ExecParams{
|
|
||||||
CodeCID: evmActorCid,
|
|
||||||
ConstructorParams: constructorParams,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to serialize init actor exec params: %w", err)
|
|
||||||
}
|
}
|
||||||
|
params = params2
|
||||||
} else {
|
} else {
|
||||||
addr, err := tx.To.ToFilecoinAddress()
|
addr, err := tx.To.ToFilecoinAddress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -276,7 +261,7 @@ func (tx *EthTxArgs) Sender() (address.Address, error) {
|
|||||||
|
|
||||||
func parseEip1559Tx(data []byte) (*EthTxArgs, error) {
|
func parseEip1559Tx(data []byte) (*EthTxArgs, error) {
|
||||||
if data[0] != 2 {
|
if data[0] != 2 {
|
||||||
return nil, xerrors.Errorf("not an EIP-1559 transaction: first byte is not 2")
|
return nil, fmt.Errorf("not an EIP-1559 transaction: first byte is not 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := DecodeRLP(data[1:])
|
d, err := DecodeRLP(data[1:])
|
||||||
@ -285,11 +270,11 @@ func parseEip1559Tx(data []byte) (*EthTxArgs, error) {
|
|||||||
}
|
}
|
||||||
decoded, ok := d.([]interface{})
|
decoded, ok := d.([]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, xerrors.Errorf("not an EIP-1559 transaction: decoded data is not a list")
|
return nil, fmt.Errorf("not an EIP-1559 transaction: decoded data is not a list")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(decoded) != 9 && len(decoded) != 12 {
|
if len(decoded) != 9 && len(decoded) != 12 {
|
||||||
return nil, xerrors.Errorf("not an EIP-1559 transaction: should have 6 or 9 elements in the list")
|
return nil, fmt.Errorf("not an EIP-1559 transaction: should have 6 or 9 elements in the list")
|
||||||
}
|
}
|
||||||
|
|
||||||
chainId, err := parseInt(decoded[0])
|
chainId, err := parseInt(decoded[0])
|
||||||
@ -375,15 +360,15 @@ func parseEip1559Tx(data []byte) (*EthTxArgs, error) {
|
|||||||
func ParseEthTxArgs(data []byte) (*EthTxArgs, error) {
|
func ParseEthTxArgs(data []byte) (*EthTxArgs, error) {
|
||||||
if data[0] > 0x7f {
|
if data[0] > 0x7f {
|
||||||
// legacy transaction
|
// legacy transaction
|
||||||
return nil, xerrors.Errorf("legacy transaction is not supported")
|
return nil, fmt.Errorf("legacy transaction is not supported")
|
||||||
} else if data[0] == 1 {
|
} else if data[0] == 1 {
|
||||||
// EIP-2930
|
// EIP-2930
|
||||||
return nil, xerrors.Errorf("EIP-2930 transaction is not supported")
|
return nil, fmt.Errorf("EIP-2930 transaction is not supported")
|
||||||
} else if data[0] == 2 {
|
} else if data[0] == 2 {
|
||||||
// EIP-1559
|
// EIP-1559
|
||||||
return parseEip1559Tx(data)
|
return parseEip1559Tx(data)
|
||||||
}
|
}
|
||||||
return nil, xerrors.Errorf("unsupported transaction type")
|
return nil, fmt.Errorf("unsupported transaction type")
|
||||||
}
|
}
|
||||||
|
|
||||||
func padLeadingZeros(data []byte, length int) []byte {
|
func padLeadingZeros(data []byte, length int) []byte {
|
||||||
@ -432,18 +417,18 @@ func formatBigInt(val big.Int) ([]byte, error) {
|
|||||||
func parseInt(v interface{}) (int, error) {
|
func parseInt(v interface{}) (int, error) {
|
||||||
data, ok := v.([]byte)
|
data, ok := v.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, xerrors.Errorf("cannot parse interface to int: input is not a byte array")
|
return 0, fmt.Errorf("cannot parse interface to int: input is not a byte array")
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if len(data) > 8 {
|
if len(data) > 8 {
|
||||||
return 0, xerrors.Errorf("cannot parse interface to int: length is more than 8 bytes")
|
return 0, fmt.Errorf("cannot parse interface to int: length is more than 8 bytes")
|
||||||
}
|
}
|
||||||
var value int64
|
var value int64
|
||||||
r := bytes.NewReader(append(make([]byte, 8-len(data)), data...))
|
r := bytes.NewReader(append(make([]byte, 8-len(data)), data...))
|
||||||
if err := binary.Read(r, binary.BigEndian, &value); err != nil {
|
if err := binary.Read(r, binary.BigEndian, &value); err != nil {
|
||||||
return 0, xerrors.Errorf("cannot parse interface to EthUint64: %w", err)
|
return 0, fmt.Errorf("cannot parse interface to EthUint64: %w", err)
|
||||||
}
|
}
|
||||||
return int(value), nil
|
return int(value), nil
|
||||||
}
|
}
|
||||||
@ -451,7 +436,7 @@ func parseInt(v interface{}) (int, error) {
|
|||||||
func parseBigInt(v interface{}) (big.Int, error) {
|
func parseBigInt(v interface{}) (big.Int, error) {
|
||||||
data, ok := v.([]byte)
|
data, ok := v.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return big.Zero(), xerrors.Errorf("cannot parse interface to big.Int: input is not a byte array")
|
return big.Zero(), fmt.Errorf("cannot parse interface to big.Int: input is not a byte array")
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return big.Zero(), nil
|
return big.Zero(), nil
|
||||||
@ -464,7 +449,7 @@ func parseBigInt(v interface{}) (big.Int, error) {
|
|||||||
func parseBytes(v interface{}) ([]byte, error) {
|
func parseBytes(v interface{}) ([]byte, error) {
|
||||||
val, ok := v.([]byte)
|
val, ok := v.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, xerrors.Errorf("cannot parse interface into bytes: input is not a byte array")
|
return nil, fmt.Errorf("cannot parse interface into bytes: input is not a byte array")
|
||||||
}
|
}
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user