From 5f2a83afe255b5ab9075afa35ae4f605980c87fd Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 13 Jan 2023 17:44:26 -0800 Subject: [PATCH] FEVM: update types (#147) * feat: update state for selfdestruct * EVM: fix method numbers/signatures * add CreateExternal to eam (#149) * add CreateExternal to eam * use CborBytes instead of CreateExternalParams * Update builtin/v10/eam/eam_types.go Co-authored-by: Steven Allen * Update builtin/v10/eam/methods.go Co-authored-by: Steven Allen * add CreateExternal to eam method list Co-authored-by: Steven Allen * make gen for CreateExternalReturn (#150) * Fix copypasta Co-authored-by: vyzo Co-authored-by: Aayush Rajasekaran --- builtin/methods.go | 14 ++-- builtin/v10/eam/cbor_gen.go | 145 ++++++++++++++++++++++++++++++++++- builtin/v10/eam/eam_types.go | 7 +- builtin/v10/eam/methods.go | 7 +- builtin/v10/evm/cbor_gen.go | 141 +++++++++++++++++++++++++++++++++- builtin/v10/evm/evm_state.go | 8 ++ builtin/v10/evm/evm_types.go | 2 + builtin/v10/evm/methods.go | 10 +-- builtin/v10/gen/gen.go | 2 + 9 files changed, 315 insertions(+), 21 deletions(-) diff --git a/builtin/methods.go b/builtin/methods.go index 305c8539..df8ed107 100644 --- a/builtin/methods.go +++ b/builtin/methods.go @@ -363,11 +363,12 @@ var MethodsDatacap = struct { var MethodsEVM = struct { Constructor abi.MethodNum - InvokeContract abi.MethodNum + Resurrect abi.MethodNum GetBytecode abi.MethodNum + GetBytecodeHash abi.MethodNum GetStorageAt abi.MethodNum - InvokeContractReadOnly abi.MethodNum InvokeContractDelegate abi.MethodNum + InvokeContract abi.MethodNum }{ MethodConstructor, 2, @@ -375,16 +376,19 @@ var MethodsEVM = struct { 4, 5, 6, + MustGenerateFRCMethodNum("InvokeEVM"), } var MethodsEAM = struct { - Constructor abi.MethodNum - Create abi.MethodNum - Create2 abi.MethodNum + Constructor abi.MethodNum + Create abi.MethodNum + Create2 abi.MethodNum + CreateExternal abi.MethodNum }{ MethodConstructor, 2, 3, + 4, } var MethodsPlaceholder = struct { diff --git a/builtin/v10/eam/cbor_gen.go b/builtin/v10/eam/cbor_gen.go index bdd18d52..ce630a03 100644 --- a/builtin/v10/eam/cbor_gen.go +++ b/builtin/v10/eam/cbor_gen.go @@ -7,6 +7,7 @@ import ( "io" "sort" + address "github.com/filecoin-project/go-address" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" @@ -182,8 +183,18 @@ func (t *CreateReturn) UnmarshalCBOR(r io.Reader) error { { - if err := t.RobustAddress.UnmarshalCBOR(br); err != nil { - return xerrors.Errorf("unmarshaling t.RobustAddress: %w", err) + b, err := br.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } + t.RobustAddress = new(address.Address) + if err := t.RobustAddress.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.RobustAddress pointer: %w", err) + } } } @@ -394,8 +405,134 @@ func (t *Create2Return) UnmarshalCBOR(r io.Reader) error { { - if err := t.RobustAddress.UnmarshalCBOR(br); err != nil { - return xerrors.Errorf("unmarshaling t.RobustAddress: %w", err) + b, err := br.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } + t.RobustAddress = new(address.Address) + if err := t.RobustAddress.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.RobustAddress pointer: %w", err) + } + } + + } + // t.EthAddress ([20]uint8) (array) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.EthAddress: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra != 20 { + return fmt.Errorf("expected array to have 20 elements") + } + + t.EthAddress = [20]uint8{} + + if _, err := io.ReadFull(br, t.EthAddress[:]); err != nil { + return err + } + return nil +} + +var lengthBufCreateExternalReturn = []byte{131} + +func (t *CreateExternalReturn) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufCreateExternalReturn); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.ActorID (uint64) (uint64) + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ActorID)); err != nil { + return err + } + + // t.RobustAddress (address.Address) (struct) + if err := t.RobustAddress.MarshalCBOR(w); err != nil { + return err + } + + // t.EthAddress ([20]uint8) (array) + if len(t.EthAddress) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field t.EthAddress was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.EthAddress))); err != nil { + return err + } + + if _, err := w.Write(t.EthAddress[:]); err != nil { + return err + } + return nil +} + +func (t *CreateExternalReturn) UnmarshalCBOR(r io.Reader) error { + *t = CreateExternalReturn{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.ActorID (uint64) (uint64) + + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.ActorID = uint64(extra) + + } + // t.RobustAddress (address.Address) (struct) + + { + + b, err := br.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } + t.RobustAddress = new(address.Address) + if err := t.RobustAddress.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.RobustAddress pointer: %w", err) + } } } diff --git a/builtin/v10/eam/eam_types.go b/builtin/v10/eam/eam_types.go index e834243f..e3f65100 100644 --- a/builtin/v10/eam/eam_types.go +++ b/builtin/v10/eam/eam_types.go @@ -1,6 +1,8 @@ package eam -import "github.com/filecoin-project/go-address" +import ( + "github.com/filecoin-project/go-address" +) type CreateParams struct { Initcode []byte @@ -14,9 +16,10 @@ type Create2Params struct { type Return struct { ActorID uint64 - RobustAddress address.Address + RobustAddress *address.Address EthAddress [20]byte } type CreateReturn Return type Create2Return Return +type CreateExternalReturn Return diff --git a/builtin/v10/eam/methods.go b/builtin/v10/eam/methods.go index c1b3b5d7..32a1b393 100644 --- a/builtin/v10/eam/methods.go +++ b/builtin/v10/eam/methods.go @@ -6,7 +6,8 @@ import ( ) var Methods = map[abi.MethodNum]builtin.MethodMeta{ - 1: {"Constructor", *new(func(*abi.EmptyValue) *abi.EmptyValue)}, // Constructor - 2: {"Create", *new(func(*CreateParams) *CreateReturn)}, // Create - 3: {"Create2", *new(func(*Create2Params) *Create2Return)}, // Create2 + 1: {"Constructor", *new(func(*abi.EmptyValue) *abi.EmptyValue)}, // Constructor + 2: {"Create", *new(func(*CreateParams) *CreateReturn)}, // Create + 3: {"Create2", *new(func(*Create2Params) *Create2Return)}, // Create2 + 4: {"CreateExternal", *new(func(*abi.CborBytes) *CreateExternalReturn)}, // CreateExternal } diff --git a/builtin/v10/evm/cbor_gen.go b/builtin/v10/evm/cbor_gen.go index c06fc5b3..2abcab5f 100644 --- a/builtin/v10/evm/cbor_gen.go +++ b/builtin/v10/evm/cbor_gen.go @@ -7,6 +7,7 @@ import ( "io" "sort" + abi "github.com/filecoin-project/go-state-types/abi" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" @@ -16,7 +17,7 @@ var _ = xerrors.Errorf var _ = cid.Undef var _ = sort.Sort -var lengthBufState = []byte{131} +var lengthBufState = []byte{133} func (t *State) MarshalCBOR(w io.Writer) error { if t == nil { @@ -35,6 +36,19 @@ func (t *State) MarshalCBOR(w io.Writer) error { return xerrors.Errorf("failed to write cid field t.Bytecode: %w", err) } + // t.BytecodeHash ([32]uint8) (array) + if len(t.BytecodeHash) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field t.BytecodeHash was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.BytecodeHash))); err != nil { + return err + } + + if _, err := w.Write(t.BytecodeHash[:]); err != nil { + return err + } + // t.ContractState (cid.Cid) (struct) if err := cbg.WriteCidBuf(scratch, w, t.ContractState); err != nil { @@ -47,6 +61,10 @@ func (t *State) MarshalCBOR(w io.Writer) error { return err } + // t.Tombstone (evm.Tombstone) (struct) + if err := t.Tombstone.MarshalCBOR(w); err != nil { + return err + } return nil } @@ -64,7 +82,7 @@ func (t *State) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 3 { + if extra != 5 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -80,6 +98,29 @@ func (t *State) UnmarshalCBOR(r io.Reader) error { t.Bytecode = c } + // t.BytecodeHash ([32]uint8) (array) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.BytecodeHash: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra != 32 { + return fmt.Errorf("expected array to have 32 elements") + } + + t.BytecodeHash = [32]uint8{} + + if _, err := io.ReadFull(br, t.BytecodeHash[:]); err != nil { + return err + } // t.ContractState (cid.Cid) (struct) { @@ -94,6 +135,102 @@ func (t *State) UnmarshalCBOR(r io.Reader) error { } // t.Nonce (uint64) (uint64) + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Nonce = uint64(extra) + + } + // t.Tombstone (evm.Tombstone) (struct) + + { + + b, err := br.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } + t.Tombstone = new(Tombstone) + if err := t.Tombstone.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Tombstone pointer: %w", err) + } + } + + } + return nil +} + +var lengthBufTombstone = []byte{130} + +func (t *Tombstone) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufTombstone); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Origin (abi.ActorID) (uint64) + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Origin)); err != nil { + return err + } + + // t.Nonce (uint64) (uint64) + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Nonce)); err != nil { + return err + } + + return nil +} + +func (t *Tombstone) UnmarshalCBOR(r io.Reader) error { + *t = Tombstone{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Origin (abi.ActorID) (uint64) + + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Origin = abi.ActorID(extra) + + } + // t.Nonce (uint64) (uint64) + { maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) diff --git a/builtin/v10/evm/evm_state.go b/builtin/v10/evm/evm_state.go index 7aa74742..e0a2e4f6 100644 --- a/builtin/v10/evm/evm_state.go +++ b/builtin/v10/evm/evm_state.go @@ -4,14 +4,22 @@ import ( "github.com/ipfs/go-cid" xerrors "golang.org/x/xerrors" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin/v10/util/adt" ) +type Tombstone struct { + Origin abi.ActorID + Nonce uint64 +} + type State struct { Bytecode cid.Cid + BytecodeHash [32]byte ContractState cid.Cid Nonce uint64 + Tombstone *Tombstone } func ConstructState(store adt.Store, bytecode cid.Cid) (*State, error) { diff --git a/builtin/v10/evm/evm_types.go b/builtin/v10/evm/evm_types.go index ee75a51e..088a56ad 100644 --- a/builtin/v10/evm/evm_types.go +++ b/builtin/v10/evm/evm_types.go @@ -7,6 +7,8 @@ type ConstructorParams struct { Initcode []byte } +type ResurrectParams = ConstructorParams + type GetStorageAtParams struct { StorageKey []byte } diff --git a/builtin/v10/evm/methods.go b/builtin/v10/evm/methods.go index fb19aedd..bc281f48 100644 --- a/builtin/v10/evm/methods.go +++ b/builtin/v10/evm/methods.go @@ -2,16 +2,16 @@ package evm import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin" typegen "github.com/whyrusleeping/cbor-gen" ) var Methods = map[abi.MethodNum]builtin.MethodMeta{ 1: {"Constructor", *new(func(*ConstructorParams) *abi.EmptyValue)}, - 2: {"InvokeContract", *new(func(bytes *abi.CborBytes) *abi.CborBytes)}, + 2: {"Resurrect", *new(func(*ResurrectParams) *abi.EmptyValue)}, 3: {"GetBytecode", *new(func(*abi.EmptyValue) *typegen.CborCid)}, - 4: {"GetStorageAt", *new(func(*GetStorageAtParams) *big.Int)}, - 5: {"InvokeContractDelegate", *new(func(params *DelegateCallParams) *abi.CborBytes)}, - 6: {"GetBytecodeHash", *new(func(*abi.EmptyValue) *typegen.CborCid)}, + 4: {"GetBytecodeHash", *new(func(*abi.EmptyValue) *abi.CborBytes)}, + 5: {"GetStorageAt", *new(func(*GetStorageAtParams) *abi.CborBytes)}, + 6: {"InvokeContractDelegate", *new(func(params *DelegateCallParams) *abi.CborBytes)}, + builtin.MustGenerateFRCMethodNum("InvokeEVM"): {"InvokeContract", *new(func(bytes *abi.CborBytes) *abi.CborBytes)}, } diff --git a/builtin/v10/gen/gen.go b/builtin/v10/gen/gen.go index 2e0171a0..c604f9e7 100644 --- a/builtin/v10/gen/gen.go +++ b/builtin/v10/gen/gen.go @@ -288,6 +288,7 @@ func main() { if err := gen.WriteTupleEncodersToFile("./builtin/v10/evm/cbor_gen.go", "evm", // actor state evm.State{}, + evm.Tombstone{}, // method params and returns evm.ConstructorParams{}, evm.GetStorageAtParams{}, @@ -302,6 +303,7 @@ func main() { eam.CreateReturn{}, eam.Create2Params{}, eam.Create2Return{}, + eam.CreateExternalReturn{}, ); err != nil { panic(err) }