From 9747ed3befd75b63a3f86f616630dd27f0169e67 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 12 Jul 2019 13:56:41 -0700 Subject: [PATCH 1/8] integrating storage market actor, includes cross actor messaging --- chain/actor_miner.go | 98 +++++++++++++++++++++++++++++++++ chain/actor_storagemarket.go | 104 +++++++++++++++++++++++++++++++++++ chain/address/address.go | 8 +-- chain/chain.go | 26 ++++----- chain/invoker.go | 1 + chain/types/vmcontext.go | 4 +- chain/vm.go | 33 ++++++++--- chain/vm_test.go | 66 ++++++++++++++++++++++ 8 files changed, 309 insertions(+), 31 deletions(-) create mode 100644 chain/actor_miner.go create mode 100644 chain/actor_storagemarket.go diff --git a/chain/actor_miner.go b/chain/actor_miner.go new file mode 100644 index 000000000..51b1cfc51 --- /dev/null +++ b/chain/actor_miner.go @@ -0,0 +1,98 @@ +package chain + +import ( + "github.com/filecoin-project/go-lotus/chain/address" + "github.com/filecoin-project/go-lotus/chain/types" + + "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/libp2p/go-libp2p-core/peer" +) + +func init() { + cbor.RegisterCborType(StorageMinerActorState{}) + cbor.RegisterCborType(StorageMinerConstructorParams{}) +} + +type StorageMinerActor struct{} + +type StorageMinerActorState struct { + // Account that owns this miner. + // - Income and returned collateral are paid to this address. + // - This address is also allowed to change the worker address for the miner. + Owner address.Address + + // Worker account for this miner. + // This will be the key that is used to sign blocks created by this miner, and + // sign messages sent on behalf of this miner to commit sectors, submit PoSts, and + // other day to day miner activities. + Worker address.Address + + // Libp2p identity that should be used when connecting to this miner. + PeerID peer.ID + + // Amount of space in each sector committed to the network by this miner. + SectorSize types.BigInt + + // Collateral currently committed to live storage. + ActiveCollateral types.BigInt + + // Collateral that is waiting to be withdrawn. + DePledgedCollateral types.BigInt + + // Time at which the depledged collateral may be withdrawn. + DePledgeTime types.BigInt + + // All sectors this miner has committed. + //Sectors SectorSet + + // Sectors this miner is currently mining. It is only updated + // when a PoSt is submitted (not as each new sector commitment is added). + //ProvingSet SectorSet + + // Sectors reported during the last PoSt submission as being 'done'. The collateral + // for them is still being held until the next PoSt submission in case early sector + // removal penalization is needed. + //NextDoneSet BitField + + // Deals this miner has been slashed for since the last post submission. + ArbitratedDeals map[cid.Cid]struct{} + + // Amount of power this miner has. + Power types.BigInt + + // List of sectors that this miner was slashed for. + //SlashedSet SectorSet + + // The height at which this miner was slashed at. + SlashedAt types.BigInt + + // The amount of storage collateral that is owed to clients, and cannot be used for collateral anymore. + OwedStorageCollateral types.BigInt +} + +type StorageMinerConstructorParams struct { + Worker address.Address + SectorSize types.BigInt + PeerID peer.ID +} + +func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMContext, params *StorageMinerConstructorParams) (InvokeRet, error) { + var self StorageMinerActorState + self.Owner = vmctx.Message().From + self.Worker = params.Worker + self.PeerID = params.PeerID + self.SectorSize = params.SectorSize + + storage := vmctx.Storage() + c, err := storage.Put(self) + if err != nil { + return InvokeRet{}, err + } + + if err := storage.Commit(cid.Undef, c); err != nil { + return InvokeRet{}, err + } + + return InvokeRet{}, nil +} diff --git a/chain/actor_storagemarket.go b/chain/actor_storagemarket.go new file mode 100644 index 000000000..24574fb8c --- /dev/null +++ b/chain/actor_storagemarket.go @@ -0,0 +1,104 @@ +package chain + +import ( + "github.com/filecoin-project/go-lotus/chain/address" + "github.com/filecoin-project/go-lotus/chain/types" + + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/libp2p/go-libp2p-core/peer" +) + +func init() { + cbor.RegisterCborType(StorageMarketState{}) +} + +type StorageMarketActor struct{} + +func (sma StorageMarketActor) Exports() []interface{} { + return []interface{}{ + nil, + sma.CreateStorageMiner, + } +} + +type StorageMarketState struct { + Miners map[address.Address]struct{} + TotalStorage types.BigInt +} + +type CreateStorageMinerParams struct { + Worker address.Address + SectorSize types.BigInt + PeerID peer.ID +} + +func (p *CreateStorageMinerParams) UnmarshalCBOR(b []byte) (int, error) { + if err := cbor.DecodeInto(b, p); err != nil { + return 0, err + } + + return len(b), nil +} + +func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) (InvokeRet, error) { + if !SupportedSectorSize(params.SectorSize) { + //Fatal("Unsupported sector size") + return InvokeRet{ + returnCode: 1, + }, nil + } + + var smcp StorageMinerConstructorParams + smcp.Worker = params.Worker + smcp.SectorSize = params.SectorSize + smcp.PeerID = params.PeerID + + encoded, err := cbor.DumpObject(smcp) + if err != nil { + return InvokeRet{}, err + } + + ret, exit, err := vmctx.Send(InitActorAddress, 1, vmctx.Message().Value, encoded) + if err != nil { + return InvokeRet{}, err + } + + naddr, err := address.NewFromBytes(ret) + if err != nil { + return InvokeRet{}, err + } + + if exit != 0 { + return InvokeRet{ + returnCode: 2, + }, nil + } + + var self StorageMarketState + old := vmctx.Storage().GetHead() + if err := vmctx.Storage().Get(old, &self); err != nil { + return InvokeRet{}, err + } + + self.Miners[naddr] = struct{}{} + + nroot, err := vmctx.Storage().Put(self) + if err != nil { + return InvokeRet{}, err + } + + if err := vmctx.Storage().Commit(old, nroot); err != nil { + return InvokeRet{}, err + } + + return InvokeRet{ + result: naddr.Bytes(), + }, nil +} + +func SupportedSectorSize(ssize types.BigInt) bool { + if ssize.Uint64() == 1024 { + return true + } + return false +} diff --git a/chain/address/address.go b/chain/address/address.go index f085779a5..0155f2565 100644 --- a/chain/address/address.go +++ b/chain/address/address.go @@ -21,12 +21,12 @@ func init() { var addressAtlasEntry = atlas.BuildEntry(Address{}).Transform(). TransformMarshal(atlas.MakeMarshalTransformFunc( - func(a Address) ([]byte, error) { - return a.Bytes(), nil + func(a Address) (string, error) { + return string(a.Bytes()), nil })). TransformUnmarshal(atlas.MakeUnmarshalTransformFunc( - func(x []byte) (Address, error) { - return NewFromBytes(x) + func(x string) (Address, error) { + return NewFromBytes([]byte(x)) })). Complete() diff --git a/chain/chain.go b/chain/chain.go index 55633c569..fb3333b63 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -103,16 +103,14 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types return nil, err } - /* - smact, err := SetupStorageMarketActor(bs) - if err != nil { - return nil, err - } + smact, err := SetupStorageMarketActor(bs) + if err != nil { + return nil, err + } - if err := state.SetActor(StorageMarketAddress, smact); err != nil { - return nil, err - } - */ + if err := state.SetActor(StorageMarketAddress, smact); err != nil { + return nil, err + } err = state.SetActor(NetworkAddress, &types.Actor{ Code: AccountActorCodeCid, @@ -137,11 +135,10 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types return state, nil } -/* -func SetupStorageMarketActor(bs bstore.Blockstore) (*Actor, error) { +func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) { sms := &StorageMarketState{ Miners: make(map[address.Address]struct{}), - TotalStorage: NewInt(0), + TotalStorage: types.NewInt(0), } stcid, err := hamt.CSTFromBstore(bs).Put(context.TODO(), sms) @@ -149,14 +146,13 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*Actor, error) { return nil, err } - return &Actor{ + return &types.Actor{ Code: StorageMarketActorCodeCid, Head: stcid, Nonce: 0, - Balance: NewInt(0), + Balance: types.NewInt(0), }, nil } -*/ func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error) { fmt.Println("at end of make Genesis block") diff --git a/chain/invoker.go b/chain/invoker.go index cf0ff87b2..1a7ccd281 100644 --- a/chain/invoker.go +++ b/chain/invoker.go @@ -27,6 +27,7 @@ func newInvoker() *invoker { // add builtInCode using: register(cid, singleton) inv.register(InitActorCodeCid, InitActor{}) + inv.register(StorageMarketActorCodeCid, StorageMarketActor{}) return inv } diff --git a/chain/types/vmcontext.go b/chain/types/vmcontext.go index 1353ba627..2e638185a 100644 --- a/chain/types/vmcontext.go +++ b/chain/types/vmcontext.go @@ -1,8 +1,6 @@ package types import ( - "math/big" - "github.com/filecoin-project/go-lotus/chain/address" "github.com/ipfs/go-cid" "github.com/ipfs/go-hamt-ipld" @@ -27,7 +25,7 @@ type StateTree interface { type VMContext interface { Message() *Message Ipld() *hamt.CborIpldStore - Send(to address.Address, method string, value *big.Int, params []interface{}) ([][]byte, uint8, error) + Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, uint8, error) BlockHeight() uint64 GasUsed() BigInt Storage() Storage diff --git a/chain/vm.go b/chain/vm.go index f4fd06466..dde175936 100644 --- a/chain/vm.go +++ b/chain/vm.go @@ -5,7 +5,6 @@ import ( "context" "encoding/binary" "fmt" - "math/big" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" @@ -14,13 +13,13 @@ import ( bserv "github.com/ipfs/go-blockservice" cid "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" - bstore "github.com/ipfs/go-ipfs-blockstore" ipld "github.com/ipfs/go-ipld-format" dag "github.com/ipfs/go-merkledag" "github.com/pkg/errors" ) type VMContext struct { + vm *VM state *StateTree msg *types.Message height uint64 @@ -75,8 +74,22 @@ func (vmc *VMContext) Ipld() *hamt.CborIpldStore { } // Send allows the current execution context to invoke methods on other actors in the system -func (vmc *VMContext) Send(to address.Address, method string, value *big.Int, params []interface{}) ([][]byte, uint8, error) { - panic("nyi") +func (vmc *VMContext) Send(to address.Address, method uint64, value types.BigInt, params []byte) ([]byte, uint8, error) { + msg := &types.Message{ + To: to, + Method: method, + Value: value, + Params: params, + } + + toAct, err := vmc.state.GetActor(to) + if err != nil { + return nil, 0, err + } + + nvmctx := vmc.vm.makeVMContext(toAct.Head, msg) + + return vmc.vm.Invoke(toAct, nvmctx, method, params) } // BlockHeight returns the height of the block this message was added to the chain in @@ -96,13 +109,15 @@ func (vmc *VMContext) StateTree() (types.StateTree, error) { return vmc.state, nil } -func makeVMContext(state *StateTree, bs bstore.Blockstore, sroot cid.Cid, msg *types.Message, height uint64) *VMContext { - cst := hamt.CSTFromBstore(bs) +func (vm *VM) makeVMContext(sroot cid.Cid, msg *types.Message) *VMContext { + cst := hamt.CSTFromBstore(vm.cs.bs) + return &VMContext{ - state: state, + vm: vm, + state: vm.cstate, sroot: sroot, msg: msg, - height: height, + height: vm.blockHeight, cst: cst, storage: &storage{ cst: cst, @@ -177,7 +192,7 @@ func (vm *VM) ApplyMessage(msg *types.Message) (*types.MessageReceipt, error) { } DepositFunds(toActor, msg.Value) - vmctx := makeVMContext(st, vm.cs.bs, toActor.Head, msg, vm.blockHeight) + vmctx := vm.makeVMContext(toActor.Head, msg) var errcode byte var ret []byte diff --git a/chain/vm_test.go b/chain/vm_test.go index 882d5a6a8..46b3b44dd 100644 --- a/chain/vm_test.go +++ b/chain/vm_test.go @@ -89,3 +89,69 @@ func TestVMInvokeMethod(t *testing.T) { t.Fatal("hold up") } } + +func TestStorageMarketActorCreateMiner(t *testing.T) { + ////////// BOILERPLATE ////////// + bs := bstore.NewBlockstore(dstore.NewMapDatastore()) + + from := blsaddr(0) + maddr := blsaddr(1) + + actors := map[address.Address]types.BigInt{ + from: types.NewInt(1000000), + maddr: types.NewInt(0), + } + st, err := MakeInitialStateTree(bs, actors) + if err != nil { + t.Fatal(err) + } + + stateroot, err := st.Flush() + if err != nil { + t.Fatal(err) + } + + cs := &ChainStore{ + bs: bs, + } + + vm, err := NewVM(stateroot, 1, maddr, cs) + if err != nil { + t.Fatal(err) + } + ////// END BOILERPLATE ////////// + + params := &StorageMinerConstructorParams{} + enc, err := cbor.DumpObject(params) + if err != nil { + t.Fatal(err) + } + + msg := &types.Message{ + To: StorageMarketAddress, + From: from, + Method: 1, + Params: enc, + GasPrice: types.NewInt(1), + GasLimit: types.NewInt(1), + Value: types.NewInt(0), + } + + ret, err := vm.ApplyMessage(msg) + if err != nil { + t.Fatal(err) + } + + if ret.ExitCode != 0 { + t.Fatal("invocation failed") + } + + outaddr, err := address.NewFromBytes(ret.Return) + if err != nil { + t.Fatal(err) + } + + if outaddr.String() != "t0102" { + t.Fatal("hold up") + } +} From c5e9a8a550beae4d95d70e08e07b57c0bf84a600 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 12 Jul 2019 14:36:49 -0700 Subject: [PATCH 2/8] finish wiring, test passes! --- chain/actor_storagemarket.go | 13 ++++++++++++- chain/vm_test.go | 8 ++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/chain/actor_storagemarket.go b/chain/actor_storagemarket.go index 24574fb8c..72d0d4c0d 100644 --- a/chain/actor_storagemarket.go +++ b/chain/actor_storagemarket.go @@ -10,6 +10,8 @@ import ( func init() { cbor.RegisterCborType(StorageMarketState{}) + cbor.RegisterCborType(CreateStorageMinerParams{}) + cbor.RegisterCborType(struct{}{}) } type StorageMarketActor struct{} @@ -53,7 +55,16 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V smcp.SectorSize = params.SectorSize smcp.PeerID = params.PeerID - encoded, err := cbor.DumpObject(smcp) + encsmcp, err := cbor.DumpObject(smcp) + if err != nil { + return InvokeRet{}, err + } + + var ep ExecParams + ep.Code = StorageMinerCodeCid + ep.Params = encsmcp + + encoded, err := cbor.DumpObject(ep) if err != nil { return InvokeRet{}, err } diff --git a/chain/vm_test.go b/chain/vm_test.go index 46b3b44dd..a881c7fe3 100644 --- a/chain/vm_test.go +++ b/chain/vm_test.go @@ -121,7 +121,11 @@ func TestStorageMarketActorCreateMiner(t *testing.T) { } ////// END BOILERPLATE ////////// - params := &StorageMinerConstructorParams{} + params := &StorageMinerConstructorParams{ + Worker: maddr, + SectorSize: types.NewInt(1024), + PeerID: "fakepeerid", + } enc, err := cbor.DumpObject(params) if err != nil { t.Fatal(err) @@ -143,7 +147,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) { } if ret.ExitCode != 0 { - t.Fatal("invocation failed") + t.Fatal("invocation failed: ", ret.ExitCode) } outaddr, err := address.NewFromBytes(ret.Return) From a5428d5c199d41ba14913ec07c55965794c0b5f8 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 12 Jul 2019 14:57:49 -0700 Subject: [PATCH 3/8] pull out test boilerplate --- chain/vm_test.go | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/chain/vm_test.go b/chain/vm_test.go index a881c7fe3..2121bd180 100644 --- a/chain/vm_test.go +++ b/chain/vm_test.go @@ -23,7 +23,7 @@ func blsaddr(n uint64) address.Address { return addr } -func TestVMInvokeMethod(t *testing.T) { +func setupVMTestEnv(t *testing.T) (*VM, []address.Address) { bs := bstore.NewBlockstore(dstore.NewMapDatastore()) from := blsaddr(0) @@ -51,6 +51,12 @@ func TestVMInvokeMethod(t *testing.T) { if err != nil { t.Fatal(err) } + return vm, []address.Address{from, maddr} +} + +func TestVMInvokeMethod(t *testing.T) { + vm, addrs := setupVMTestEnv(t) + from := addrs[0] execparams := &ExecParams{ Code: StorageMinerCodeCid, @@ -91,35 +97,9 @@ func TestVMInvokeMethod(t *testing.T) { } func TestStorageMarketActorCreateMiner(t *testing.T) { - ////////// BOILERPLATE ////////// - bs := bstore.NewBlockstore(dstore.NewMapDatastore()) - - from := blsaddr(0) - maddr := blsaddr(1) - - actors := map[address.Address]types.BigInt{ - from: types.NewInt(1000000), - maddr: types.NewInt(0), - } - st, err := MakeInitialStateTree(bs, actors) - if err != nil { - t.Fatal(err) - } - - stateroot, err := st.Flush() - if err != nil { - t.Fatal(err) - } - - cs := &ChainStore{ - bs: bs, - } - - vm, err := NewVM(stateroot, 1, maddr, cs) - if err != nil { - t.Fatal(err) - } - ////// END BOILERPLATE ////////// + vm, addrs := setupVMTestEnv(t) + from := addrs[0] + maddr := addrs[1] params := &StorageMinerConstructorParams{ Worker: maddr, From e62816dd15295e20140a2353b432782c11e2739f Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 12 Jul 2019 16:12:06 -0700 Subject: [PATCH 4/8] some cleanup --- chain/actor_init.go | 13 +++++++++++++ chain/actor_storagemarket.go | 20 +++++--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/chain/actor_init.go b/chain/actor_init.go index ee0bde4bc..600177535 100644 --- a/chain/actor_init.go +++ b/chain/actor_init.go @@ -46,6 +46,19 @@ func (ep *ExecParams) UnmarshalCBOR(b []byte) (int, error) { return len(b), nil } +func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, error) { + encparams, err := cbor.DumpObject(obj) + if err != nil { + return nil, err + } + + var ep ExecParams + ep.Code = act + ep.Params = encparams + + return cbor.DumpObject(ep) +} + func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) (InvokeRet, error) { beginState := vmctx.Storage().GetHead() diff --git a/chain/actor_storagemarket.go b/chain/actor_storagemarket.go index 72d0d4c0d..f0c192d0b 100644 --- a/chain/actor_storagemarket.go +++ b/chain/actor_storagemarket.go @@ -50,21 +50,11 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V }, nil } - var smcp StorageMinerConstructorParams - smcp.Worker = params.Worker - smcp.SectorSize = params.SectorSize - smcp.PeerID = params.PeerID - - encsmcp, err := cbor.DumpObject(smcp) - if err != nil { - return InvokeRet{}, err - } - - var ep ExecParams - ep.Code = StorageMinerCodeCid - ep.Params = encsmcp - - encoded, err := cbor.DumpObject(ep) + encoded, err := CreateExecParams(StorageMinerCodeCid, &StorageMinerConstructorParams{ + Worker: params.Worker, + SectorSize: params.SectorSize, + PeerID: params.PeerID, + }) if err != nil { return InvokeRet{}, err } From 0ac35450130bd2b94862f38100fd720948e45936 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 12 Jul 2019 16:52:25 -0700 Subject: [PATCH 5/8] move actors to separate package --- chain/{ => actors}/actor_init.go | 50 ++++++++++++++------- chain/{ => actors}/actor_miner.go | 10 ++--- chain/{ => actors}/actor_storagemarket.go | 28 ++++++------ chain/{ => actors}/actors.go | 5 +-- chain/{vm_test.go => actors/actors_test.go} | 14 +++--- chain/chain.go | 27 +++++------ chain/invoker.go | 21 ++++----- chain/invoker_test.go | 18 ++++---- chain/mining.go | 3 +- chain/statetree.go | 9 ++-- chain/sync.go | 9 ++-- chain/types/invokeret.go | 6 +++ chain/vm.go | 22 ++------- 13 files changed, 115 insertions(+), 107 deletions(-) rename chain/{ => actors}/actor_init.go (81%) rename chain/{ => actors}/actor_miner.go (95%) rename chain/{ => actors}/actor_storagemarket.go (81%) rename chain/{ => actors}/actors.go (96%) rename chain/{vm_test.go => actors/actors_test.go} (88%) create mode 100644 chain/types/invokeret.go diff --git a/chain/actor_init.go b/chain/actors/actor_init.go similarity index 81% rename from chain/actor_init.go rename to chain/actors/actor_init.go index 600177535..2424ecd7a 100644 --- a/chain/actor_init.go +++ b/chain/actors/actor_init.go @@ -1,7 +1,9 @@ -package chain +package actors import ( + "bytes" "context" + "encoding/binary" "fmt" "github.com/filecoin-project/go-lotus/chain/address" @@ -10,9 +12,12 @@ import ( "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" cbor "github.com/ipfs/go-ipld-cbor" + logging "github.com/ipfs/go-log" "github.com/pkg/errors" ) +var log = logging.Logger("actors") + func init() { cbor.RegisterCborType(ExecParams{}) } @@ -59,19 +64,19 @@ func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, error) { return cbor.DumpObject(ep) } -func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) (InvokeRet, error) { +func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) (types.InvokeRet, error) { beginState := vmctx.Storage().GetHead() var self InitActorState if err := vmctx.Storage().Get(beginState, &self); err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } // Make sure that only the actors defined in the spec can be launched. if !IsBuiltinActor(p.Code) { log.Error("cannot launch actor instance that is not a builtin actor") - return InvokeRet{ - returnCode: 1, + return types.InvokeRet{ + ReturnCode: 1, }, nil } @@ -79,8 +84,8 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) // TODO: do we want to enforce this? If so how should actors be marked as such? if IsSingletonActor(p.Code) { log.Error("cannot launch another actor of this type") - return InvokeRet{ - returnCode: 1, + return types.InvokeRet{ + ReturnCode: 1, }, nil } @@ -90,7 +95,7 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) nonce := vmctx.Message().Nonce addr, err := ComputeActorAddress(creator, nonce) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } // Set up the actor itself @@ -109,31 +114,31 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) // Store the mapping of address to actor ID. idAddr, err := self.AddActor(vmctx, addr) if err != nil { - return InvokeRet{}, errors.Wrap(err, "adding new actor mapping") + return types.InvokeRet{}, errors.Wrap(err, "adding new actor mapping") } // NOTE: This is a privileged call that only the init actor is allowed to make // FIXME: Had to comment this because state is not in interface state, err := vmctx.StateTree() if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } if err := state.SetActor(idAddr, &actor); err != nil { - return InvokeRet{}, errors.Wrap(err, "inserting new actor into state tree") + return types.InvokeRet{}, errors.Wrap(err, "inserting new actor into state tree") } c, err := vmctx.Storage().Put(self) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } if err := vmctx.Storage().Commit(beginState, c); err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } - return InvokeRet{ - result: idAddr.Bytes(), + return types.InvokeRet{ + Result: idAddr.Bytes(), }, nil } @@ -198,3 +203,18 @@ func (ias *InitActorState) Lookup(cst *hamt.CborIpldStore, addr address.Address) type AccountActorState struct { Address address.Address } + +func ComputeActorAddress(creator address.Address, nonce uint64) (address.Address, error) { + buf := new(bytes.Buffer) + _, err := buf.Write(creator.Bytes()) + if err != nil { + return address.Address{}, err + } + + err = binary.Write(buf, binary.BigEndian, nonce) + if err != nil { + return address.Address{}, err + } + + return address.NewActorAddress(buf.Bytes()) +} diff --git a/chain/actor_miner.go b/chain/actors/actor_miner.go similarity index 95% rename from chain/actor_miner.go rename to chain/actors/actor_miner.go index 51b1cfc51..9154b9fc7 100644 --- a/chain/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -1,4 +1,4 @@ -package chain +package actors import ( "github.com/filecoin-project/go-lotus/chain/address" @@ -77,7 +77,7 @@ type StorageMinerConstructorParams struct { PeerID peer.ID } -func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMContext, params *StorageMinerConstructorParams) (InvokeRet, error) { +func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMContext, params *StorageMinerConstructorParams) (types.InvokeRet, error) { var self StorageMinerActorState self.Owner = vmctx.Message().From self.Worker = params.Worker @@ -87,12 +87,12 @@ func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMC storage := vmctx.Storage() c, err := storage.Put(self) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } if err := storage.Commit(cid.Undef, c); err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } - return InvokeRet{}, nil + return types.InvokeRet{}, nil } diff --git a/chain/actor_storagemarket.go b/chain/actors/actor_storagemarket.go similarity index 81% rename from chain/actor_storagemarket.go rename to chain/actors/actor_storagemarket.go index f0c192d0b..772d8d9f9 100644 --- a/chain/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -1,4 +1,4 @@ -package chain +package actors import ( "github.com/filecoin-project/go-lotus/chain/address" @@ -42,11 +42,11 @@ func (p *CreateStorageMinerParams) UnmarshalCBOR(b []byte) (int, error) { return len(b), nil } -func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) (InvokeRet, error) { +func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) (types.InvokeRet, error) { if !SupportedSectorSize(params.SectorSize) { //Fatal("Unsupported sector size") - return InvokeRet{ - returnCode: 1, + return types.InvokeRet{ + ReturnCode: 1, }, nil } @@ -56,44 +56,44 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V PeerID: params.PeerID, }) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } ret, exit, err := vmctx.Send(InitActorAddress, 1, vmctx.Message().Value, encoded) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } naddr, err := address.NewFromBytes(ret) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } if exit != 0 { - return InvokeRet{ - returnCode: 2, + return types.InvokeRet{ + ReturnCode: 2, }, nil } var self StorageMarketState old := vmctx.Storage().GetHead() if err := vmctx.Storage().Get(old, &self); err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } self.Miners[naddr] = struct{}{} nroot, err := vmctx.Storage().Put(self) if err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } if err := vmctx.Storage().Commit(old, nroot); err != nil { - return InvokeRet{}, err + return types.InvokeRet{}, err } - return InvokeRet{ - result: naddr.Bytes(), + return types.InvokeRet{ + Result: naddr.Bytes(), }, nil } diff --git a/chain/actors.go b/chain/actors/actors.go similarity index 96% rename from chain/actors.go rename to chain/actors/actors.go index 2883b8820..06b30be91 100644 --- a/chain/actors.go +++ b/chain/actors/actors.go @@ -1,4 +1,4 @@ -package chain +package actors import ( "github.com/filecoin-project/go-lotus/chain/address" @@ -47,6 +47,3 @@ func init() { MultisigActorCodeCid = mustSum("multisig") InitActorCodeCid = mustSum("init") } - -type VMActor struct { -} diff --git a/chain/vm_test.go b/chain/actors/actors_test.go similarity index 88% rename from chain/vm_test.go rename to chain/actors/actors_test.go index 2121bd180..bd12be01b 100644 --- a/chain/vm_test.go +++ b/chain/actors/actors_test.go @@ -1,9 +1,11 @@ -package chain +package actors_test import ( "encoding/binary" "testing" + "github.com/filecoin-project/go-lotus/chain" + . "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" dstore "github.com/ipfs/go-datastore" @@ -23,7 +25,7 @@ func blsaddr(n uint64) address.Address { return addr } -func setupVMTestEnv(t *testing.T) (*VM, []address.Address) { +func setupVMTestEnv(t *testing.T) (*chain.VM, []address.Address) { bs := bstore.NewBlockstore(dstore.NewMapDatastore()) from := blsaddr(0) @@ -33,7 +35,7 @@ func setupVMTestEnv(t *testing.T) (*VM, []address.Address) { from: types.NewInt(1000000), maddr: types.NewInt(0), } - st, err := MakeInitialStateTree(bs, actors) + st, err := chain.MakeInitialStateTree(bs, actors) if err != nil { t.Fatal(err) } @@ -43,11 +45,9 @@ func setupVMTestEnv(t *testing.T) (*VM, []address.Address) { t.Fatal(err) } - cs := &ChainStore{ - bs: bs, - } + cs := chain.NewChainStore(bs, nil) - vm, err := NewVM(stateroot, 1, maddr, cs) + vm, err := chain.NewVM(stateroot, 1, maddr, cs) if err != nil { t.Fatal(err) } diff --git a/chain/chain.go b/chain/chain.go index fb3333b63..790379600 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -5,6 +5,7 @@ import ( "fmt" "sync" + actors "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" @@ -28,7 +29,7 @@ type GenesisBootstrap struct { } func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) { - var ias InitActorState + var ias actors.InitActorState ias.NextID = 100 cst := hamt.CSTFromBstore(bs) @@ -57,7 +58,7 @@ func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor } act := &types.Actor{ - Code: InitActorCodeCid, + Code: actors.InitActorCodeCid, Head: statecid, } @@ -77,7 +78,7 @@ func init() { var EmptyObjectCid cid.Cid -func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types.BigInt) (*StateTree, error) { +func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types.BigInt) (*StateTree, error) { cst := hamt.CSTFromBstore(bs) state, err := NewStateTree(cst) if err != nil { @@ -90,7 +91,7 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types } var addrs []address.Address - for a := range actors { + for a := range actmap { addrs = append(addrs, a) } @@ -99,7 +100,7 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types return nil, err } - if err := state.SetActor(InitActorAddress, initact); err != nil { + if err := state.SetActor(actors.InitActorAddress, initact); err != nil { return nil, err } @@ -108,12 +109,12 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types return nil, err } - if err := state.SetActor(StorageMarketAddress, smact); err != nil { + if err := state.SetActor(actors.StorageMarketAddress, smact); err != nil { return nil, err } - err = state.SetActor(NetworkAddress, &types.Actor{ - Code: AccountActorCodeCid, + err = state.SetActor(actors.NetworkAddress, &types.Actor{ + Code: actors.AccountActorCodeCid, Balance: types.NewInt(100000000000), Head: emptyobject, }) @@ -121,9 +122,9 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types return nil, err } - for a, v := range actors { + for a, v := range actmap { err = state.SetActor(a, &types.Actor{ - Code: AccountActorCodeCid, + Code: actors.AccountActorCodeCid, Balance: v, Head: emptyobject, }) @@ -136,7 +137,7 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types } func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) { - sms := &StorageMarketState{ + sms := &actors.StorageMarketState{ Miners: make(map[address.Address]struct{}), TotalStorage: types.NewInt(0), } @@ -147,7 +148,7 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) { } return &types.Actor{ - Code: StorageMarketActorCodeCid, + Code: actors.StorageMarketActorCodeCid, Head: stcid, Nonce: 0, Balance: types.NewInt(0), @@ -184,7 +185,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error fmt.Println("Empty Genesis root: ", emptyroot) b := &BlockHeader{ - Miner: InitActorAddress, + Miner: actors.InitActorAddress, Tickets: []Ticket{}, ElectionProof: []byte("the Genesis block"), Parents: []cid.Cid{}, diff --git a/chain/invoker.go b/chain/invoker.go index 1a7ccd281..e9acb6a0c 100644 --- a/chain/invoker.go +++ b/chain/invoker.go @@ -5,6 +5,7 @@ import ( "fmt" "reflect" + actors "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/types" "github.com/ipfs/go-cid" ) @@ -13,12 +14,8 @@ type invoker struct { builtInCode map[cid.Cid]nativeCode } -type invokeFunc func(act *types.Actor, vmctx *VMContext, params []byte) (InvokeRet, error) +type invokeFunc func(act *types.Actor, vmctx *VMContext, params []byte) (types.InvokeRet, error) type nativeCode []invokeFunc -type InvokeRet struct { - result []byte - returnCode byte -} func newInvoker() *invoker { inv := &invoker{ @@ -26,20 +23,20 @@ func newInvoker() *invoker { } // add builtInCode using: register(cid, singleton) - inv.register(InitActorCodeCid, InitActor{}) - inv.register(StorageMarketActorCodeCid, StorageMarketActor{}) + inv.register(actors.InitActorCodeCid, actors.InitActor{}) + inv.register(actors.StorageMarketActorCodeCid, actors.StorageMarketActor{}) return inv } -func (inv *invoker) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params []byte) (InvokeRet, error) { +func (inv *invoker) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params []byte) (types.InvokeRet, error) { code, ok := inv.builtInCode[act.Code] if !ok { - return InvokeRet{}, errors.New("no code for actor") + return types.InvokeRet{}, errors.New("no code for actor") } if method >= uint64(len(code)) || code[method] == nil { - return InvokeRet{}, fmt.Errorf("no method %d on actor", method) + return types.InvokeRet{}, fmt.Errorf("no method %d on actor", method) } return code[method](act, vmctx, params) @@ -104,7 +101,7 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) { return nil, newErr("wrong number of outputs should be: " + "(InvokeRet, error)") } - if t.Out(0) != reflect.TypeOf(InvokeRet{}) { + if t.Out(0) != reflect.TypeOf(types.InvokeRet{}) { return nil, newErr("first output should be of type InvokeRet") } if !t.Out(1).Implements(tError) { @@ -124,7 +121,7 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) { _, err := param.Interface().(unmarshalCBOR).UnmarshalCBOR(inBytes) if err != nil { return []reflect.Value{ - reflect.ValueOf(InvokeRet{}), + reflect.ValueOf(types.InvokeRet{}), // Below is a hack, fixed in Go 1.13 // https://git.io/fjXU6 reflect.ValueOf(&err).Elem(), diff --git a/chain/invoker_test.go b/chain/invoker_test.go index 4d5a56b14..d2514b55c 100644 --- a/chain/invoker_test.go +++ b/chain/invoker_test.go @@ -43,20 +43,20 @@ func (b basicContract) Exports() []interface{} { } func (basicContract) InvokeSomething0(act *types.Actor, vmctx types.VMContext, - params *basicParams) (InvokeRet, error) { - return InvokeRet{ - returnCode: params.b, + params *basicParams) (types.InvokeRet, error) { + return types.InvokeRet{ + ReturnCode: params.b, }, nil } func (basicContract) BadParam(act *types.Actor, vmctx types.VMContext, - params *badParam) (InvokeRet, error) { + params *badParam) (types.InvokeRet, error) { panic("should not execute") } func (basicContract) InvokeSomething10(act *types.Actor, vmctx types.VMContext, - params *basicParams) (InvokeRet, error) { - return InvokeRet{ - returnCode: params.b + 10, + params *basicParams) (types.InvokeRet, error) { + return types.InvokeRet{ + ReturnCode: params.b + 10, }, nil } @@ -66,11 +66,11 @@ func TestInvokerBasic(t *testing.T) { assert.NoError(t, err) ret, err := code[0](nil, nil, []byte{1}) assert.NoError(t, err) - assert.Equal(t, byte(1), ret.returnCode, "return code should be 1") + assert.Equal(t, byte(1), ret.ReturnCode, "return code should be 1") ret, err = code[10](nil, &VMContext{}, []byte{2}) assert.NoError(t, err) - assert.Equal(t, byte(12), ret.returnCode, "return code should be 1") + assert.Equal(t, byte(12), ret.ReturnCode, "return code should be 1") ret, err = code[1](nil, &VMContext{}, []byte{2}) assert.Error(t, err) diff --git a/chain/mining.go b/chain/mining.go index aaabbad24..ec6ef8afd 100644 --- a/chain/mining.go +++ b/chain/mining.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" sharray "github.com/whyrusleeping/sharray" + "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" bls "github.com/filecoin-project/go-lotus/lib/bls-signatures" @@ -32,7 +33,7 @@ func MinerCreateBlock(cs *ChainStore, miner address.Address, parents *TipSet, ti } // apply miner reward - if err := vm.TransferFunds(NetworkAddress, miner, miningRewardForBlock(parents)); err != nil { + if err := vm.TransferFunds(actors.NetworkAddress, miner, miningRewardForBlock(parents)); err != nil { return nil, err } diff --git a/chain/statetree.go b/chain/statetree.go index 5cbeca65c..a19397141 100644 --- a/chain/statetree.go +++ b/chain/statetree.go @@ -8,6 +8,7 @@ import ( hamt "github.com/ipfs/go-hamt-ipld" cbor "github.com/ipfs/go-ipld-cbor" + "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" ) @@ -64,12 +65,12 @@ func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error { } func (st *StateTree) lookupID(addr address.Address) (address.Address, error) { - act, err := st.GetActor(InitActorAddress) + act, err := st.GetActor(actors.InitActorAddress) if err != nil { return address.Undef, err } - var ias InitActorState + var ias actors.InitActorState if err := st.store.Get(context.TODO(), act.Head, &ias); err != nil { return address.Undef, err } @@ -144,8 +145,8 @@ func (st *StateTree) Snapshot() error { func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor) (address.Address, error) { var out address.Address - err := st.MutateActor(InitActorAddress, func(initact *types.Actor) error { - var ias InitActorState + err := st.MutateActor(actors.InitActorAddress, func(initact *types.Actor) error { + var ias actors.InitActorState if err := st.store.Get(context.TODO(), initact.Head, &ias); err != nil { return err } diff --git a/chain/sync.go b/chain/sync.go index bcb176f7e..bb6dba613 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -5,6 +5,7 @@ import ( "fmt" "sync" + "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" @@ -569,7 +570,7 @@ func (syncer *Syncer) ValidateBlock(b *FullBlock) error { return err } - if err := vm.TransferFunds(NetworkAddress, b.Header.Miner, miningRewardForBlock(baseTs)); err != nil { + if err := vm.TransferFunds(actors.NetworkAddress, b.Header.Miner, miningRewardForBlock(baseTs)); err != nil { return err } @@ -648,7 +649,7 @@ func makeActor(st *StateTree, addr address.Address) (*types.Actor, error) { } func NewBLSAccountActor(st *StateTree, addr address.Address) (*types.Actor, error) { - var acstate AccountActorState + var acstate actors.AccountActorState acstate.Address = addr c, err := st.store.Put(context.TODO(), acstate) @@ -657,7 +658,7 @@ func NewBLSAccountActor(st *StateTree, addr address.Address) (*types.Actor, erro } nact := &types.Actor{ - Code: AccountActorCodeCid, + Code: actors.AccountActorCodeCid, Balance: types.NewInt(0), Head: c, } @@ -667,7 +668,7 @@ func NewBLSAccountActor(st *StateTree, addr address.Address) (*types.Actor, erro func NewSecp256k1AccountActor(st *StateTree, addr address.Address) (*types.Actor, error) { nact := &types.Actor{ - Code: AccountActorCodeCid, + Code: actors.AccountActorCodeCid, Balance: types.NewInt(0), Head: EmptyObjectCid, } diff --git a/chain/types/invokeret.go b/chain/types/invokeret.go new file mode 100644 index 000000000..030b728ae --- /dev/null +++ b/chain/types/invokeret.go @@ -0,0 +1,6 @@ +package types + +type InvokeRet struct { + Result []byte + ReturnCode byte +} diff --git a/chain/vm.go b/chain/vm.go index dde175936..32f4d9a62 100644 --- a/chain/vm.go +++ b/chain/vm.go @@ -1,11 +1,10 @@ package chain import ( - "bytes" "context" - "encoding/binary" "fmt" + "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/lib/bufbstore" @@ -102,7 +101,7 @@ func (vmc *VMContext) GasUsed() types.BigInt { } func (vmc *VMContext) StateTree() (types.StateTree, error) { - if vmc.msg.To != InitActorAddress { + if vmc.msg.To != actors.InitActorAddress { return nil, fmt.Errorf("only init actor can access state tree directly") } @@ -276,20 +275,5 @@ func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params [ if err != nil { return nil, 0, err } - return ret.result, ret.returnCode, nil -} - -func ComputeActorAddress(creator address.Address, nonce uint64) (address.Address, error) { - buf := new(bytes.Buffer) - _, err := buf.Write(creator.Bytes()) - if err != nil { - return address.Address{}, err - } - - err = binary.Write(buf, binary.BigEndian, nonce) - if err != nil { - return address.Address{}, err - } - - return address.NewActorAddress(buf.Bytes()) + return ret.Result, ret.ReturnCode, nil } From 2364a73b92846b9dfa2c76474b1c9cf55ba5d3c7 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 15 Jul 2019 16:44:30 +0200 Subject: [PATCH 6/8] Switch from UnmarshalCBOR interface to calling CBOR Now invoker is calling CBOR directly. License: MIT Signed-off-by: Jakub Sztandera --- chain/invoker.go | 15 ++++--------- chain/invoker_test.go | 52 ++++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/chain/invoker.go b/chain/invoker.go index e9acb6a0c..0eaba5948 100644 --- a/chain/invoker.go +++ b/chain/invoker.go @@ -8,6 +8,7 @@ import ( actors "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/types" "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" ) type invoker struct { @@ -50,15 +51,10 @@ func (inv *invoker) register(c cid.Cid, instance Invokee) { inv.builtInCode[c] = code } -type unmarshalCBOR interface { - UnmarshalCBOR([]byte) (int, error) -} - type Invokee interface { Exports() []interface{} } -var tUnmarhsalCBOR = reflect.TypeOf((*unmarshalCBOR)(nil)).Elem() var tVMContext = reflect.TypeOf((*types.VMContext)(nil)).Elem() var tError = reflect.TypeOf((*error)(nil)).Elem() @@ -89,12 +85,8 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) { return nil, newErr("second argument should be types.VMContext") } - if !t.In(2).Implements(tUnmarhsalCBOR) { - return nil, newErr("parameter doesn't implement UnmarshalCBOR") - } - if t.In(2).Kind() != reflect.Ptr { - return nil, newErr("parameter has to be a pointer") + return nil, newErr("parameter has to be a pointer to parameter") } if t.NumOut() != 2 { @@ -118,7 +110,7 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) { param := reflect.New(paramT) inBytes := in[2].Interface().([]byte) - _, err := param.Interface().(unmarshalCBOR).UnmarshalCBOR(inBytes) + err := cbor.DecodeInto(inBytes, param.Interface()) if err != nil { return []reflect.Value{ reflect.ValueOf(types.InvokeRet{}), @@ -127,6 +119,7 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) { reflect.ValueOf(&err).Elem(), } } + return meth.Call([]reflect.Value{ in[0], in[1], param, }) diff --git a/chain/invoker_test.go b/chain/invoker_test.go index d2514b55c..e6f64aed7 100644 --- a/chain/invoker_test.go +++ b/chain/invoker_test.go @@ -1,9 +1,9 @@ package chain import ( - "errors" "testing" + cbor "github.com/ipfs/go-ipld-cbor" "github.com/stretchr/testify/assert" "github.com/filecoin-project/go-lotus/chain/types" @@ -11,19 +11,11 @@ import ( type basicContract struct{} type basicParams struct { - b byte + B byte } -func (b *basicParams) UnmarshalCBOR(in []byte) (int, error) { - b.b = in[0] - return 1, nil -} - -type badParam struct { -} - -func (b *badParam) UnmarshalCBOR(in []byte) (int, error) { - return -1, errors.New("some error") +func init() { + cbor.RegisterCborType(basicParams{}) } func (b basicContract) Exports() []interface{} { @@ -45,18 +37,20 @@ func (b basicContract) Exports() []interface{} { func (basicContract) InvokeSomething0(act *types.Actor, vmctx types.VMContext, params *basicParams) (types.InvokeRet, error) { return types.InvokeRet{ - ReturnCode: params.b, + ReturnCode: params.B, }, nil } func (basicContract) BadParam(act *types.Actor, vmctx types.VMContext, - params *badParam) (types.InvokeRet, error) { - panic("should not execute") + params *basicParams) (types.InvokeRet, error) { + return types.InvokeRet{ + ReturnCode: 255, + }, nil } func (basicContract) InvokeSomething10(act *types.Actor, vmctx types.VMContext, params *basicParams) (types.InvokeRet, error) { return types.InvokeRet{ - ReturnCode: params.b + 10, + ReturnCode: params.B + 10, }, nil } @@ -64,14 +58,26 @@ func TestInvokerBasic(t *testing.T) { inv := invoker{} code, err := inv.transform(basicContract{}) assert.NoError(t, err) - ret, err := code[0](nil, nil, []byte{1}) - assert.NoError(t, err) - assert.Equal(t, byte(1), ret.ReturnCode, "return code should be 1") - ret, err = code[10](nil, &VMContext{}, []byte{2}) - assert.NoError(t, err) - assert.Equal(t, byte(12), ret.ReturnCode, "return code should be 1") + { + bParam, err := cbor.DumpObject(basicParams{B: 1}) + assert.NoError(t, err) - ret, err = code[1](nil, &VMContext{}, []byte{2}) + ret, err := code[0](nil, &VMContext{}, bParam) + assert.NoError(t, err) + assert.Equal(t, byte(1), ret.ReturnCode, "return code should be 1") + } + + { + bParam, err := cbor.DumpObject(basicParams{B: 2}) + assert.NoError(t, err) + + ret, err := code[10](nil, &VMContext{}, bParam) + assert.NoError(t, err) + assert.Equal(t, byte(12), ret.ReturnCode, "return code should be 12") + } + + _, err = code[1](nil, &VMContext{}, []byte{0}) assert.Error(t, err) + } From 1aa3cf304323ced4e90bbad623dd11e580e42af9 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 15 Jul 2019 17:51:46 +0200 Subject: [PATCH 7/8] Remove UnmarshalCBOR functions License: MIT Signed-off-by: Jakub Sztandera --- chain/actors/actor_init.go | 8 -------- chain/actors/actor_storagemarket.go | 8 -------- 2 files changed, 16 deletions(-) diff --git a/chain/actors/actor_init.go b/chain/actors/actor_init.go index 2424ecd7a..4e5c1fe57 100644 --- a/chain/actors/actor_init.go +++ b/chain/actors/actor_init.go @@ -43,14 +43,6 @@ type ExecParams struct { Params []byte } -func (ep *ExecParams) UnmarshalCBOR(b []byte) (int, error) { - if err := cbor.DecodeInto(b, ep); err != nil { - return 0, err - } - - return len(b), nil -} - func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, error) { encparams, err := cbor.DumpObject(obj) if err != nil { diff --git a/chain/actors/actor_storagemarket.go b/chain/actors/actor_storagemarket.go index 772d8d9f9..2ae622a09 100644 --- a/chain/actors/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -34,14 +34,6 @@ type CreateStorageMinerParams struct { PeerID peer.ID } -func (p *CreateStorageMinerParams) UnmarshalCBOR(b []byte) (int, error) { - if err := cbor.DecodeInto(b, p); err != nil { - return 0, err - } - - return len(b), nil -} - func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) (types.InvokeRet, error) { if !SupportedSectorSize(params.SectorSize) { //Fatal("Unsupported sector size") From c44eeab51a7e1459ea85cf6ee7d7a2cc13907217 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 15 Jul 2019 10:48:59 -0700 Subject: [PATCH 8/8] pull out constant --- chain/actors/actor_storagemarket.go | 4 +++- chain/actors/actors_test.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/chain/actors/actor_storagemarket.go b/chain/actors/actor_storagemarket.go index 2ae622a09..35da19350 100644 --- a/chain/actors/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -8,6 +8,8 @@ import ( "github.com/libp2p/go-libp2p-core/peer" ) +const SectorSize = 1024 + func init() { cbor.RegisterCborType(StorageMarketState{}) cbor.RegisterCborType(CreateStorageMinerParams{}) @@ -90,7 +92,7 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V } func SupportedSectorSize(ssize types.BigInt) bool { - if ssize.Uint64() == 1024 { + if ssize.Uint64() == SectorSize { return true } return false diff --git a/chain/actors/actors_test.go b/chain/actors/actors_test.go index bd12be01b..8a5fcabbc 100644 --- a/chain/actors/actors_test.go +++ b/chain/actors/actors_test.go @@ -103,7 +103,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) { params := &StorageMinerConstructorParams{ Worker: maddr, - SectorSize: types.NewInt(1024), + SectorSize: types.NewInt(SectorSize), PeerID: "fakepeerid", } enc, err := cbor.DumpObject(params)