From 020fb6f8a3e97e0050c703741e4121c436374974 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 22 Jul 2019 18:08:54 +0200 Subject: [PATCH] Mid rework License: MIT Signed-off-by: Jakub Sztandera --- chain/actors/actor_init.go | 73 ++++++++++++----------------- chain/actors/actor_storagemarket.go | 21 ++------- chain/actors/address.go | 14 ++++++ chain/actors/aerrors/wrap.go | 9 ++++ chain/actors/error.go | 5 ++ chain/actors/params.go | 9 +++- chain/types/vmcontext.go | 15 +++--- 7 files changed, 78 insertions(+), 68 deletions(-) create mode 100644 chain/actors/address.go create mode 100644 chain/actors/error.go diff --git a/chain/actors/actor_init.go b/chain/actors/actor_init.go index 1cbc4ebb9..714560335 100644 --- a/chain/actors/actor_init.go +++ b/chain/actors/actor_init.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" + "github.com/filecoin-project/go-lotus/chain/actors/aerrors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" @@ -14,7 +15,6 @@ import ( cbor "github.com/ipfs/go-ipld-cbor" logging "github.com/ipfs/go-log" mh "github.com/multiformats/go-multihash" - "github.com/pkg/errors" ) var log = logging.Logger("actors") @@ -54,50 +54,37 @@ 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) +func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, aerrors.ActorError) { + encparams, err := SerializeParams(obj) if err != nil { - return nil, err + return nil, aerrors.Wrap(err, "creating ExecParams") } var ep ExecParams ep.Code = act ep.Params = encparams - return cbor.DumpObject(ep) + return SerializeParams(ep) } -func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) (types.InvokeRet, error) { +func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) ([]byte, aerrors.ActorError) { beginState := vmctx.Storage().GetHead() var self InitActorState if err := vmctx.Storage().Get(beginState, &self); err != nil { - return types.InvokeRet{}, err + return nil, 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 types.InvokeRet{ - ReturnCode: 1, - }, nil + return nil, aerrors.New(1, + "cannot launch actor instance that is not a builtin actor") } // Ensure that singeltons can be only launched once. // 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 types.InvokeRet{ - ReturnCode: 1, - }, nil + return nil, aerrors.New(1, "cannot launch another actor of this type") } // This generates a unique address for this actor that is stable across message @@ -106,7 +93,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 types.InvokeRet{}, err + return nil, err } // Set up the actor itself @@ -118,7 +105,7 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) } _, err = vmctx.Storage().Put(struct{}{}) if err != nil { - return types.InvokeRet{}, err + return nil, err } // The call to the actors constructor will set up the initial state @@ -127,39 +114,37 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) //actor.Constructor(p.Params) // Store the mapping of address to actor ID. - idAddr, err := self.AddActor(vmctx, addr) - if err != nil { - return types.InvokeRet{}, errors.Wrap(err, "adding new actor mapping") + idAddr, nerr := self.AddActor(vmctx, addr) + if nerr != nil { + return nil, aerrors.Escalate(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 types.InvokeRet{}, err + return nil, err } if err := state.SetActor(idAddr, &actor); err != nil { - return types.InvokeRet{}, errors.Wrap(err, "inserting new actor into state tree") + return nil, aerrors.Wrap(err, "inserting new actor into state tree") } - _, _, err = vmctx.Send(idAddr, 0, vmctx.Message().Value, p.Params) + _, err = vmctx.Send(idAddr, 0, vmctx.Message().Value, p.Params) if err != nil { - return types.InvokeRet{}, err + return nil, err } c, err := vmctx.Storage().Put(self) if err != nil { - return types.InvokeRet{}, err + return nil, err } if err := vmctx.Storage().Commit(beginState, c); err != nil { - return types.InvokeRet{}, err + return nil, err } - return types.InvokeRet{ - Result: idAddr.Bytes(), - }, nil + return idAddr.Bytes(), nil } func IsBuiltinActor(code cid.Cid) bool { @@ -198,7 +183,7 @@ func (ias *InitActorState) AddActor(vmctx types.VMContext, addr address.Address) } ias.AddressMap = ncid - return address.NewIDAddress(nid) + return NewIDAddress(nid) } func (ias *InitActorState) Lookup(cst *hamt.CborIpldStore, addr address.Address) (address.Address, error) { @@ -224,17 +209,21 @@ type AccountActorState struct { Address address.Address } -func ComputeActorAddress(creator address.Address, nonce uint64) (address.Address, error) { +func ComputeActorAddress(creator address.Address, nonce uint64) (address.Address, ActorError) { buf := new(bytes.Buffer) _, err := buf.Write(creator.Bytes()) if err != nil { - return address.Address{}, err + return address.Undef, aerrors.Escalate(err, "could not write address") } err = binary.Write(buf, binary.BigEndian, nonce) if err != nil { - return address.Address{}, err + return address.Undef, aerrors.Escalate(err, "could not write nonce") } - return address.NewActorAddress(buf.Bytes()) + addr, err := address.NewActorAddress(buf.Bytes()) + if err != nil { + return address.Undef, aerrors.Escalate(err, "could not create address") + } + return addr, nil } diff --git a/chain/actors/actor_storagemarket.go b/chain/actors/actor_storagemarket.go index 4b7c8f618..9b3c4d664 100644 --- a/chain/actors/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -63,19 +63,13 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V return types.InvokeRet{}, err } - ret, exit, err := vmctx.Send(InitActorAddress, 1, vmctx.Message().Value, encoded) + ret, err := vmctx.Send(InitActorAddress, 1, vmctx.Message().Value, encoded) if err != nil { return types.InvokeRet{}, err } - if exit != 0 { - return types.InvokeRet{ - ReturnCode: 2, - }, nil - } - - naddr, err := address.NewFromBytes(ret) - if err != nil { + naddr, nerr := address.NewFromBytes(ret) + if nerr != nil { return types.InvokeRet{}, err } @@ -158,18 +152,11 @@ func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContex }, nil } - ret, code, err := vmctx.Send(params.Miner, 9, types.NewInt(0), EmptyStructCBOR) + ret, err := vmctx.Send(params.Miner, 9, types.NewInt(0), EmptyStructCBOR) if err != nil { return types.InvokeRet{}, xerrors.Errorf("invoke Miner.GetPower: %w", err) } - if code != 0 { - return types.InvokeRet{ - // TODO: error handling... these codes really don't tell us what the problem is very well - ReturnCode: code, - }, nil - } - return types.InvokeRet{ Result: ret, }, nil diff --git a/chain/actors/address.go b/chain/actors/address.go new file mode 100644 index 000000000..b80087a79 --- /dev/null +++ b/chain/actors/address.go @@ -0,0 +1,14 @@ +package actors + +import ( + "github.com/filecoin-project/go-lotus/chain/actors/aerrors" + "github.com/filecoin-project/go-lotus/chain/address" +) + +func NewIDAddress(id uint64) (address.Address, ActorError) { + a, err := address.NewIDAddress(id) + if err != nil { + return address.Undef, aerrors.Escalate(err, "could not create ID Address") + } + return a, nil +} diff --git a/chain/actors/aerrors/wrap.go b/chain/actors/aerrors/wrap.go index ccd0d7a85..04638d2f8 100644 --- a/chain/actors/aerrors/wrap.go +++ b/chain/actors/aerrors/wrap.go @@ -6,6 +6,15 @@ import ( "golang.org/x/xerrors" ) +func New(retCode uint8, message string) ActorError { + return &actorError{ + retCode: retCode, + + msg: message, + frame: xerrors.Caller(1), + } +} + func Wrap(err ActorError, message string) ActorError { if err == nil { return nil diff --git a/chain/actors/error.go b/chain/actors/error.go new file mode 100644 index 000000000..164e3ad78 --- /dev/null +++ b/chain/actors/error.go @@ -0,0 +1,5 @@ +package actors + +import "github.com/filecoin-project/go-lotus/chain/actors/aerrors" + +type ActorError = aerrors.ActorError diff --git a/chain/actors/params.go b/chain/actors/params.go index 83fc39fca..208673bcb 100644 --- a/chain/actors/params.go +++ b/chain/actors/params.go @@ -1,6 +1,7 @@ package actors import ( + "github.com/filecoin-project/go-lotus/chain/actors/aerrors" cbor "github.com/ipfs/go-ipld-cbor" ) @@ -8,6 +9,10 @@ var ( EmptyStructCBOR = []byte{0xa0} ) -func SerializeParams(i interface{}) ([]byte, error) { - return cbor.DumpObject(i) +func SerializeParams(i interface{}) ([]byte, aerrors.ActorError) { + dump, err := cbor.DumpObject(i) + if err != nil { + return nil, aerrors.Absorb(err, 1, "failed to encode parameter") + } + return dump, nil } diff --git a/chain/types/vmcontext.go b/chain/types/vmcontext.go index 9beffb97f..8eb2ca361 100644 --- a/chain/types/vmcontext.go +++ b/chain/types/vmcontext.go @@ -1,34 +1,35 @@ package types import ( + "github.com/filecoin-project/go-lotus/chain/actors/aerrors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/ipfs/go-cid" "github.com/ipfs/go-hamt-ipld" ) type Storage interface { - Put(interface{}) (cid.Cid, error) - Get(cid.Cid, interface{}) error + Put(interface{}) (cid.Cid, aerrors.ActorError) + Get(cid.Cid, interface{}) aerrors.ActorError GetHead() cid.Cid // Commit sets the new head of the actors state as long as the current // state matches 'oldh' - Commit(oldh cid.Cid, newh cid.Cid) error + Commit(oldh cid.Cid, newh cid.Cid) aerrors.ActorError } type StateTree interface { - SetActor(addr address.Address, act *Actor) error - GetActor(addr address.Address) (*Actor, error) + SetActor(addr address.Address, act *Actor) aerrors.ActorError + GetActor(addr address.Address) (*Actor, aerrors.ActorError) } type VMContext interface { Message() *Message Origin() address.Address Ipld() *hamt.CborIpldStore - Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, uint8, error) + Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, aerrors.ActorError) BlockHeight() uint64 GasUsed() BigInt Storage() Storage - StateTree() (StateTree, error) + StateTree() (StateTree, aerrors.ActorError) }