Mid rework
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
02dab3eb51
commit
020fb6f8a3
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"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/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
|
||||||
@ -14,7 +15,6 @@ import (
|
|||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
mh "github.com/multiformats/go-multihash"
|
mh "github.com/multiformats/go-multihash"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.Logger("actors")
|
var log = logging.Logger("actors")
|
||||||
@ -54,50 +54,37 @@ type ExecParams struct {
|
|||||||
Params []byte
|
Params []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ep *ExecParams) UnmarshalCBOR(b []byte) (int, error) {
|
func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, aerrors.ActorError) {
|
||||||
if err := cbor.DecodeInto(b, ep); err != nil {
|
encparams, err := SerializeParams(obj)
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, error) {
|
|
||||||
encparams, err := cbor.DumpObject(obj)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, aerrors.Wrap(err, "creating ExecParams")
|
||||||
}
|
}
|
||||||
|
|
||||||
var ep ExecParams
|
var ep ExecParams
|
||||||
ep.Code = act
|
ep.Code = act
|
||||||
ep.Params = encparams
|
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()
|
beginState := vmctx.Storage().GetHead()
|
||||||
|
|
||||||
var self InitActorState
|
var self InitActorState
|
||||||
if err := vmctx.Storage().Get(beginState, &self); err != nil {
|
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.
|
// Make sure that only the actors defined in the spec can be launched.
|
||||||
if !IsBuiltinActor(p.Code) {
|
if !IsBuiltinActor(p.Code) {
|
||||||
log.Error("cannot launch actor instance that is not a builtin actor")
|
return nil, aerrors.New(1,
|
||||||
return types.InvokeRet{
|
"cannot launch actor instance that is not a builtin actor")
|
||||||
ReturnCode: 1,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that singeltons can be only launched once.
|
// Ensure that singeltons can be only launched once.
|
||||||
// TODO: do we want to enforce this? If so how should actors be marked as such?
|
// TODO: do we want to enforce this? If so how should actors be marked as such?
|
||||||
if IsSingletonActor(p.Code) {
|
if IsSingletonActor(p.Code) {
|
||||||
log.Error("cannot launch another actor of this type")
|
return nil, aerrors.New(1, "cannot launch another actor of this type")
|
||||||
return types.InvokeRet{
|
|
||||||
ReturnCode: 1,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This generates a unique address for this actor that is stable across message
|
// 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
|
nonce := vmctx.Message().Nonce
|
||||||
addr, err := ComputeActorAddress(creator, nonce)
|
addr, err := ComputeActorAddress(creator, nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.InvokeRet{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the actor itself
|
// 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{}{})
|
_, err = vmctx.Storage().Put(struct{}{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.InvokeRet{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The call to the actors constructor will set up the initial state
|
// 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)
|
//actor.Constructor(p.Params)
|
||||||
|
|
||||||
// Store the mapping of address to actor ID.
|
// Store the mapping of address to actor ID.
|
||||||
idAddr, err := self.AddActor(vmctx, addr)
|
idAddr, nerr := self.AddActor(vmctx, addr)
|
||||||
if err != nil {
|
if nerr != nil {
|
||||||
return types.InvokeRet{}, errors.Wrap(err, "adding new actor mapping")
|
return nil, aerrors.Escalate(err, "adding new actor mapping")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This is a privileged call that only the init actor is allowed to make
|
// 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
|
// FIXME: Had to comment this because state is not in interface
|
||||||
state, err := vmctx.StateTree()
|
state, err := vmctx.StateTree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.InvokeRet{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := state.SetActor(idAddr, &actor); err != nil {
|
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 {
|
if err != nil {
|
||||||
return types.InvokeRet{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := vmctx.Storage().Put(self)
|
c, err := vmctx.Storage().Put(self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.InvokeRet{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := vmctx.Storage().Commit(beginState, c); err != nil {
|
if err := vmctx.Storage().Commit(beginState, c); err != nil {
|
||||||
return types.InvokeRet{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.InvokeRet{
|
return idAddr.Bytes(), nil
|
||||||
Result: idAddr.Bytes(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsBuiltinActor(code cid.Cid) bool {
|
func IsBuiltinActor(code cid.Cid) bool {
|
||||||
@ -198,7 +183,7 @@ func (ias *InitActorState) AddActor(vmctx types.VMContext, addr address.Address)
|
|||||||
}
|
}
|
||||||
ias.AddressMap = ncid
|
ias.AddressMap = ncid
|
||||||
|
|
||||||
return address.NewIDAddress(nid)
|
return NewIDAddress(nid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ias *InitActorState) Lookup(cst *hamt.CborIpldStore, addr address.Address) (address.Address, error) {
|
func (ias *InitActorState) Lookup(cst *hamt.CborIpldStore, addr address.Address) (address.Address, error) {
|
||||||
@ -224,17 +209,21 @@ type AccountActorState struct {
|
|||||||
Address address.Address
|
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)
|
buf := new(bytes.Buffer)
|
||||||
_, err := buf.Write(creator.Bytes())
|
_, err := buf.Write(creator.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Address{}, err
|
return address.Undef, aerrors.Escalate(err, "could not write address")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Write(buf, binary.BigEndian, nonce)
|
err = binary.Write(buf, binary.BigEndian, nonce)
|
||||||
if err != nil {
|
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
|
||||||
}
|
}
|
||||||
|
@ -63,19 +63,13 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V
|
|||||||
return types.InvokeRet{}, err
|
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 {
|
if err != nil {
|
||||||
return types.InvokeRet{}, err
|
return types.InvokeRet{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exit != 0 {
|
naddr, nerr := address.NewFromBytes(ret)
|
||||||
return types.InvokeRet{
|
if nerr != nil {
|
||||||
ReturnCode: 2,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
naddr, err := address.NewFromBytes(ret)
|
|
||||||
if err != nil {
|
|
||||||
return types.InvokeRet{}, err
|
return types.InvokeRet{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,18 +152,11 @@ func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContex
|
|||||||
}, nil
|
}, 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 {
|
if err != nil {
|
||||||
return types.InvokeRet{}, xerrors.Errorf("invoke Miner.GetPower: %w", err)
|
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{
|
return types.InvokeRet{
|
||||||
Result: ret,
|
Result: ret,
|
||||||
}, nil
|
}, nil
|
||||||
|
14
chain/actors/address.go
Normal file
14
chain/actors/address.go
Normal file
@ -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
|
||||||
|
}
|
@ -6,6 +6,15 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"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 {
|
func Wrap(err ActorError, message string) ActorError {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
5
chain/actors/error.go
Normal file
5
chain/actors/error.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package actors
|
||||||
|
|
||||||
|
import "github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||||
|
|
||||||
|
type ActorError = aerrors.ActorError
|
@ -1,6 +1,7 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -8,6 +9,10 @@ var (
|
|||||||
EmptyStructCBOR = []byte{0xa0}
|
EmptyStructCBOR = []byte{0xa0}
|
||||||
)
|
)
|
||||||
|
|
||||||
func SerializeParams(i interface{}) ([]byte, error) {
|
func SerializeParams(i interface{}) ([]byte, aerrors.ActorError) {
|
||||||
return cbor.DumpObject(i)
|
dump, err := cbor.DumpObject(i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, aerrors.Absorb(err, 1, "failed to encode parameter")
|
||||||
|
}
|
||||||
|
return dump, nil
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,35 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/ipfs/go-hamt-ipld"
|
"github.com/ipfs/go-hamt-ipld"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
Put(interface{}) (cid.Cid, error)
|
Put(interface{}) (cid.Cid, aerrors.ActorError)
|
||||||
Get(cid.Cid, interface{}) error
|
Get(cid.Cid, interface{}) aerrors.ActorError
|
||||||
|
|
||||||
GetHead() cid.Cid
|
GetHead() cid.Cid
|
||||||
|
|
||||||
// Commit sets the new head of the actors state as long as the current
|
// Commit sets the new head of the actors state as long as the current
|
||||||
// state matches 'oldh'
|
// state matches 'oldh'
|
||||||
Commit(oldh cid.Cid, newh cid.Cid) error
|
Commit(oldh cid.Cid, newh cid.Cid) aerrors.ActorError
|
||||||
}
|
}
|
||||||
|
|
||||||
type StateTree interface {
|
type StateTree interface {
|
||||||
SetActor(addr address.Address, act *Actor) error
|
SetActor(addr address.Address, act *Actor) aerrors.ActorError
|
||||||
GetActor(addr address.Address) (*Actor, error)
|
GetActor(addr address.Address) (*Actor, aerrors.ActorError)
|
||||||
}
|
}
|
||||||
|
|
||||||
type VMContext interface {
|
type VMContext interface {
|
||||||
Message() *Message
|
Message() *Message
|
||||||
Origin() address.Address
|
Origin() address.Address
|
||||||
Ipld() *hamt.CborIpldStore
|
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
|
BlockHeight() uint64
|
||||||
GasUsed() BigInt
|
GasUsed() BigInt
|
||||||
Storage() Storage
|
Storage() Storage
|
||||||
StateTree() (StateTree, error)
|
StateTree() (StateTree, aerrors.ActorError)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user