Merge pull request #26 from filecoin-project/feat/storage-market-actor
integrating storage market actor, includes cross actor messaging
This commit is contained in:
commit
c4c571cfa6
@ -1,7 +1,9 @@
|
|||||||
package chain
|
package actors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
@ -10,9 +12,12 @@ import (
|
|||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
|
logging "github.com/ipfs/go-log"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var log = logging.Logger("actors")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cbor.RegisterCborType(ExecParams{})
|
cbor.RegisterCborType(ExecParams{})
|
||||||
}
|
}
|
||||||
@ -38,27 +43,32 @@ type ExecParams struct {
|
|||||||
Params []byte
|
Params []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ep *ExecParams) UnmarshalCBOR(b []byte) (int, error) {
|
func CreateExecParams(act cid.Cid, obj interface{}) ([]byte, error) {
|
||||||
if err := cbor.DecodeInto(b, ep); err != nil {
|
encparams, err := cbor.DumpObject(obj)
|
||||||
return 0, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(b), nil
|
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) {
|
func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) (types.InvokeRet, error) {
|
||||||
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 InvokeRet{}, err
|
return types.InvokeRet{}, 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")
|
log.Error("cannot launch actor instance that is not a builtin actor")
|
||||||
return InvokeRet{
|
return types.InvokeRet{
|
||||||
returnCode: 1,
|
ReturnCode: 1,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,8 +76,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?
|
// 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")
|
log.Error("cannot launch another actor of this type")
|
||||||
return InvokeRet{
|
return types.InvokeRet{
|
||||||
returnCode: 1,
|
ReturnCode: 1,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +87,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 InvokeRet{}, err
|
return types.InvokeRet{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the actor itself
|
// Set up the actor itself
|
||||||
@ -96,31 +106,31 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams)
|
|||||||
// Store the mapping of address to actor ID.
|
// Store the mapping of address to actor ID.
|
||||||
idAddr, err := self.AddActor(vmctx, addr)
|
idAddr, err := self.AddActor(vmctx, addr)
|
||||||
if err != nil {
|
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
|
// 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 InvokeRet{}, err
|
return types.InvokeRet{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := state.SetActor(idAddr, &actor); err != nil {
|
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)
|
c, err := vmctx.Storage().Put(self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InvokeRet{}, err
|
return types.InvokeRet{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := vmctx.Storage().Commit(beginState, c); err != nil {
|
if err := vmctx.Storage().Commit(beginState, c); err != nil {
|
||||||
return InvokeRet{}, err
|
return types.InvokeRet{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return InvokeRet{
|
return types.InvokeRet{
|
||||||
result: idAddr.Bytes(),
|
Result: idAddr.Bytes(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,3 +195,18 @@ func (ias *InitActorState) Lookup(cst *hamt.CborIpldStore, addr address.Address)
|
|||||||
type AccountActorState struct {
|
type AccountActorState struct {
|
||||||
Address address.Address
|
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())
|
||||||
|
}
|
98
chain/actors/actor_miner.go
Normal file
98
chain/actors/actor_miner.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package actors
|
||||||
|
|
||||||
|
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) (types.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 types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := storage.Commit(cid.Undef, c); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.InvokeRet{}, nil
|
||||||
|
}
|
99
chain/actors/actor_storagemarket.go
Normal file
99
chain/actors/actor_storagemarket.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package actors
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
const SectorSize = 1024
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cbor.RegisterCborType(StorageMarketState{})
|
||||||
|
cbor.RegisterCborType(CreateStorageMinerParams{})
|
||||||
|
cbor.RegisterCborType(struct{}{})
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) (types.InvokeRet, error) {
|
||||||
|
if !SupportedSectorSize(params.SectorSize) {
|
||||||
|
//Fatal("Unsupported sector size")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 1,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded, err := CreateExecParams(StorageMinerCodeCid, &StorageMinerConstructorParams{
|
||||||
|
Worker: params.Worker,
|
||||||
|
SectorSize: params.SectorSize,
|
||||||
|
PeerID: params.PeerID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, exit, err := vmctx.Send(InitActorAddress, 1, vmctx.Message().Value, encoded)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
naddr, err := address.NewFromBytes(ret)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exit != 0 {
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 2,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var self StorageMarketState
|
||||||
|
old := vmctx.Storage().GetHead()
|
||||||
|
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
self.Miners[naddr] = struct{}{}
|
||||||
|
|
||||||
|
nroot, err := vmctx.Storage().Put(self)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.InvokeRet{
|
||||||
|
Result: naddr.Bytes(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SupportedSectorSize(ssize types.BigInt) bool {
|
||||||
|
if ssize.Uint64() == SectorSize {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package chain
|
package actors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
@ -47,6 +47,3 @@ func init() {
|
|||||||
MultisigActorCodeCid = mustSum("multisig")
|
MultisigActorCodeCid = mustSum("multisig")
|
||||||
InitActorCodeCid = mustSum("init")
|
InitActorCodeCid = mustSum("init")
|
||||||
}
|
}
|
||||||
|
|
||||||
type VMActor struct {
|
|
||||||
}
|
|
@ -1,9 +1,11 @@
|
|||||||
package chain
|
package actors_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"testing"
|
"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/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
dstore "github.com/ipfs/go-datastore"
|
dstore "github.com/ipfs/go-datastore"
|
||||||
@ -23,7 +25,7 @@ func blsaddr(n uint64) address.Address {
|
|||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVMInvokeMethod(t *testing.T) {
|
func setupVMTestEnv(t *testing.T) (*chain.VM, []address.Address) {
|
||||||
bs := bstore.NewBlockstore(dstore.NewMapDatastore())
|
bs := bstore.NewBlockstore(dstore.NewMapDatastore())
|
||||||
|
|
||||||
from := blsaddr(0)
|
from := blsaddr(0)
|
||||||
@ -33,7 +35,7 @@ func TestVMInvokeMethod(t *testing.T) {
|
|||||||
from: types.NewInt(1000000),
|
from: types.NewInt(1000000),
|
||||||
maddr: types.NewInt(0),
|
maddr: types.NewInt(0),
|
||||||
}
|
}
|
||||||
st, err := MakeInitialStateTree(bs, actors)
|
st, err := chain.MakeInitialStateTree(bs, actors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -43,14 +45,18 @@ func TestVMInvokeMethod(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := &ChainStore{
|
cs := chain.NewChainStore(bs, nil)
|
||||||
bs: bs,
|
|
||||||
}
|
|
||||||
|
|
||||||
vm, err := NewVM(stateroot, 1, maddr, cs)
|
vm, err := chain.NewVM(stateroot, 1, maddr, cs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
return vm, []address.Address{from, maddr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMInvokeMethod(t *testing.T) {
|
||||||
|
vm, addrs := setupVMTestEnv(t)
|
||||||
|
from := addrs[0]
|
||||||
|
|
||||||
execparams := &ExecParams{
|
execparams := &ExecParams{
|
||||||
Code: StorageMinerCodeCid,
|
Code: StorageMinerCodeCid,
|
||||||
@ -89,3 +95,47 @@ func TestVMInvokeMethod(t *testing.T) {
|
|||||||
t.Fatal("hold up")
|
t.Fatal("hold up")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStorageMarketActorCreateMiner(t *testing.T) {
|
||||||
|
vm, addrs := setupVMTestEnv(t)
|
||||||
|
from := addrs[0]
|
||||||
|
maddr := addrs[1]
|
||||||
|
|
||||||
|
params := &StorageMinerConstructorParams{
|
||||||
|
Worker: maddr,
|
||||||
|
SectorSize: types.NewInt(SectorSize),
|
||||||
|
PeerID: "fakepeerid",
|
||||||
|
}
|
||||||
|
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: ", ret.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
outaddr, err := address.NewFromBytes(ret.Return)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if outaddr.String() != "t0102" {
|
||||||
|
t.Fatal("hold up")
|
||||||
|
}
|
||||||
|
}
|
@ -21,12 +21,12 @@ func init() {
|
|||||||
|
|
||||||
var addressAtlasEntry = atlas.BuildEntry(Address{}).Transform().
|
var addressAtlasEntry = atlas.BuildEntry(Address{}).Transform().
|
||||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||||
func(a Address) ([]byte, error) {
|
func(a Address) (string, error) {
|
||||||
return a.Bytes(), nil
|
return string(a.Bytes()), nil
|
||||||
})).
|
})).
|
||||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||||
func(x []byte) (Address, error) {
|
func(x string) (Address, error) {
|
||||||
return NewFromBytes(x)
|
return NewFromBytes([]byte(x))
|
||||||
})).
|
})).
|
||||||
Complete()
|
Complete()
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"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/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"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) {
|
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) {
|
||||||
var ias InitActorState
|
var ias actors.InitActorState
|
||||||
ias.NextID = 100
|
ias.NextID = 100
|
||||||
|
|
||||||
cst := hamt.CSTFromBstore(bs)
|
cst := hamt.CSTFromBstore(bs)
|
||||||
@ -57,7 +58,7 @@ func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor
|
|||||||
}
|
}
|
||||||
|
|
||||||
act := &types.Actor{
|
act := &types.Actor{
|
||||||
Code: InitActorCodeCid,
|
Code: actors.InitActorCodeCid,
|
||||||
Head: statecid,
|
Head: statecid,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ func init() {
|
|||||||
|
|
||||||
var EmptyObjectCid cid.Cid
|
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)
|
cst := hamt.CSTFromBstore(bs)
|
||||||
state, err := NewStateTree(cst)
|
state, err := NewStateTree(cst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -90,7 +91,7 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
|||||||
}
|
}
|
||||||
|
|
||||||
var addrs []address.Address
|
var addrs []address.Address
|
||||||
for a := range actors {
|
for a := range actmap {
|
||||||
addrs = append(addrs, a)
|
addrs = append(addrs, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,23 +100,21 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := state.SetActor(InitActorAddress, initact); err != nil {
|
if err := state.SetActor(actors.InitActorAddress, initact); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
smact, err := SetupStorageMarketActor(bs)
|
smact, err := SetupStorageMarketActor(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := state.SetActor(StorageMarketAddress, smact); err != nil {
|
if err := state.SetActor(actors.StorageMarketAddress, smact); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
err = state.SetActor(NetworkAddress, &types.Actor{
|
err = state.SetActor(actors.NetworkAddress, &types.Actor{
|
||||||
Code: AccountActorCodeCid,
|
Code: actors.AccountActorCodeCid,
|
||||||
Balance: types.NewInt(100000000000),
|
Balance: types.NewInt(100000000000),
|
||||||
Head: emptyobject,
|
Head: emptyobject,
|
||||||
})
|
})
|
||||||
@ -123,9 +122,9 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for a, v := range actors {
|
for a, v := range actmap {
|
||||||
err = state.SetActor(a, &types.Actor{
|
err = state.SetActor(a, &types.Actor{
|
||||||
Code: AccountActorCodeCid,
|
Code: actors.AccountActorCodeCid,
|
||||||
Balance: v,
|
Balance: v,
|
||||||
Head: emptyobject,
|
Head: emptyobject,
|
||||||
})
|
})
|
||||||
@ -137,11 +136,10 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
|||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||||
func SetupStorageMarketActor(bs bstore.Blockstore) (*Actor, error) {
|
sms := &actors.StorageMarketState{
|
||||||
sms := &StorageMarketState{
|
|
||||||
Miners: make(map[address.Address]struct{}),
|
Miners: make(map[address.Address]struct{}),
|
||||||
TotalStorage: NewInt(0),
|
TotalStorage: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
stcid, err := hamt.CSTFromBstore(bs).Put(context.TODO(), sms)
|
stcid, err := hamt.CSTFromBstore(bs).Put(context.TODO(), sms)
|
||||||
@ -149,14 +147,13 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*Actor, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Actor{
|
return &types.Actor{
|
||||||
Code: StorageMarketActorCodeCid,
|
Code: actors.StorageMarketActorCodeCid,
|
||||||
Head: stcid,
|
Head: stcid,
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
Balance: NewInt(0),
|
Balance: types.NewInt(0),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error) {
|
func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error) {
|
||||||
fmt.Println("at end of make Genesis block")
|
fmt.Println("at end of make Genesis block")
|
||||||
@ -188,7 +185,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error
|
|||||||
fmt.Println("Empty Genesis root: ", emptyroot)
|
fmt.Println("Empty Genesis root: ", emptyroot)
|
||||||
|
|
||||||
b := &BlockHeader{
|
b := &BlockHeader{
|
||||||
Miner: InitActorAddress,
|
Miner: actors.InitActorAddress,
|
||||||
Tickets: []Ticket{},
|
Tickets: []Ticket{},
|
||||||
ElectionProof: []byte("the Genesis block"),
|
ElectionProof: []byte("the Genesis block"),
|
||||||
Parents: []cid.Cid{},
|
Parents: []cid.Cid{},
|
||||||
|
@ -5,20 +5,18 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
actors "github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
)
|
)
|
||||||
|
|
||||||
type invoker struct {
|
type invoker struct {
|
||||||
builtInCode map[cid.Cid]nativeCode
|
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 nativeCode []invokeFunc
|
||||||
type InvokeRet struct {
|
|
||||||
result []byte
|
|
||||||
returnCode byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func newInvoker() *invoker {
|
func newInvoker() *invoker {
|
||||||
inv := &invoker{
|
inv := &invoker{
|
||||||
@ -26,19 +24,20 @@ func newInvoker() *invoker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add builtInCode using: register(cid, singleton)
|
// add builtInCode using: register(cid, singleton)
|
||||||
inv.register(InitActorCodeCid, InitActor{})
|
inv.register(actors.InitActorCodeCid, actors.InitActor{})
|
||||||
|
inv.register(actors.StorageMarketActorCodeCid, actors.StorageMarketActor{})
|
||||||
|
|
||||||
return inv
|
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]
|
code, ok := inv.builtInCode[act.Code]
|
||||||
if !ok {
|
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 {
|
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)
|
return code[method](act, vmctx, params)
|
||||||
|
|
||||||
@ -52,15 +51,10 @@ func (inv *invoker) register(c cid.Cid, instance Invokee) {
|
|||||||
inv.builtInCode[c] = code
|
inv.builtInCode[c] = code
|
||||||
}
|
}
|
||||||
|
|
||||||
type unmarshalCBOR interface {
|
|
||||||
UnmarshalCBOR([]byte) (int, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Invokee interface {
|
type Invokee interface {
|
||||||
Exports() []interface{}
|
Exports() []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var tUnmarhsalCBOR = reflect.TypeOf((*unmarshalCBOR)(nil)).Elem()
|
|
||||||
var tVMContext = reflect.TypeOf((*types.VMContext)(nil)).Elem()
|
var tVMContext = reflect.TypeOf((*types.VMContext)(nil)).Elem()
|
||||||
var tError = reflect.TypeOf((*error)(nil)).Elem()
|
var tError = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
|
|
||||||
@ -91,19 +85,15 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) {
|
|||||||
return nil, newErr("second argument should be types.VMContext")
|
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 {
|
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 {
|
if t.NumOut() != 2 {
|
||||||
return nil, newErr("wrong number of outputs should be: " +
|
return nil, newErr("wrong number of outputs should be: " +
|
||||||
"(InvokeRet, error)")
|
"(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")
|
return nil, newErr("first output should be of type InvokeRet")
|
||||||
}
|
}
|
||||||
if !t.Out(1).Implements(tError) {
|
if !t.Out(1).Implements(tError) {
|
||||||
@ -120,15 +110,16 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) {
|
|||||||
param := reflect.New(paramT)
|
param := reflect.New(paramT)
|
||||||
|
|
||||||
inBytes := in[2].Interface().([]byte)
|
inBytes := in[2].Interface().([]byte)
|
||||||
_, err := param.Interface().(unmarshalCBOR).UnmarshalCBOR(inBytes)
|
err := cbor.DecodeInto(inBytes, param.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []reflect.Value{
|
return []reflect.Value{
|
||||||
reflect.ValueOf(InvokeRet{}),
|
reflect.ValueOf(types.InvokeRet{}),
|
||||||
// Below is a hack, fixed in Go 1.13
|
// Below is a hack, fixed in Go 1.13
|
||||||
// https://git.io/fjXU6
|
// https://git.io/fjXU6
|
||||||
reflect.ValueOf(&err).Elem(),
|
reflect.ValueOf(&err).Elem(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return meth.Call([]reflect.Value{
|
return meth.Call([]reflect.Value{
|
||||||
in[0], in[1], param,
|
in[0], in[1], param,
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package chain
|
package chain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
@ -11,19 +11,11 @@ import (
|
|||||||
|
|
||||||
type basicContract struct{}
|
type basicContract struct{}
|
||||||
type basicParams struct {
|
type basicParams struct {
|
||||||
b byte
|
B byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *basicParams) UnmarshalCBOR(in []byte) (int, error) {
|
func init() {
|
||||||
b.b = in[0]
|
cbor.RegisterCborType(basicParams{})
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type badParam struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *badParam) UnmarshalCBOR(in []byte) (int, error) {
|
|
||||||
return -1, errors.New("some error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b basicContract) Exports() []interface{} {
|
func (b basicContract) Exports() []interface{} {
|
||||||
@ -43,20 +35,22 @@ func (b basicContract) Exports() []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (basicContract) InvokeSomething0(act *types.Actor, vmctx types.VMContext,
|
func (basicContract) InvokeSomething0(act *types.Actor, vmctx types.VMContext,
|
||||||
params *basicParams) (InvokeRet, error) {
|
params *basicParams) (types.InvokeRet, error) {
|
||||||
return InvokeRet{
|
return types.InvokeRet{
|
||||||
returnCode: params.b,
|
ReturnCode: params.B,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
func (basicContract) BadParam(act *types.Actor, vmctx types.VMContext,
|
func (basicContract) BadParam(act *types.Actor, vmctx types.VMContext,
|
||||||
params *badParam) (InvokeRet, error) {
|
params *basicParams) (types.InvokeRet, error) {
|
||||||
panic("should not execute")
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 255,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (basicContract) InvokeSomething10(act *types.Actor, vmctx types.VMContext,
|
func (basicContract) InvokeSomething10(act *types.Actor, vmctx types.VMContext,
|
||||||
params *basicParams) (InvokeRet, error) {
|
params *basicParams) (types.InvokeRet, error) {
|
||||||
return InvokeRet{
|
return types.InvokeRet{
|
||||||
returnCode: params.b + 10,
|
ReturnCode: params.B + 10,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,14 +58,26 @@ func TestInvokerBasic(t *testing.T) {
|
|||||||
inv := invoker{}
|
inv := invoker{}
|
||||||
code, err := inv.transform(basicContract{})
|
code, err := inv.transform(basicContract{})
|
||||||
assert.NoError(t, err)
|
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})
|
{
|
||||||
|
bParam, err := cbor.DumpObject(basicParams{B: 1})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, byte(12), ret.returnCode, "return code should be 1")
|
|
||||||
|
|
||||||
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)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
sharray "github.com/whyrusleeping/sharray"
|
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/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
bls "github.com/filecoin-project/go-lotus/lib/bls-signatures"
|
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
|
// 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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
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/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"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) {
|
func (st *StateTree) lookupID(addr address.Address) (address.Address, error) {
|
||||||
act, err := st.GetActor(InitActorAddress)
|
act, err := st.GetActor(actors.InitActorAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ias InitActorState
|
var ias actors.InitActorState
|
||||||
if err := st.store.Get(context.TODO(), act.Head, &ias); err != nil {
|
if err := st.store.Get(context.TODO(), act.Head, &ias); err != nil {
|
||||||
return address.Undef, err
|
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) {
|
func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor) (address.Address, error) {
|
||||||
var out address.Address
|
var out address.Address
|
||||||
err := st.MutateActor(InitActorAddress, func(initact *types.Actor) error {
|
err := st.MutateActor(actors.InitActorAddress, func(initact *types.Actor) error {
|
||||||
var ias InitActorState
|
var ias actors.InitActorState
|
||||||
if err := st.store.Get(context.TODO(), initact.Head, &ias); err != nil {
|
if err := st.store.Get(context.TODO(), initact.Head, &ias); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"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"
|
||||||
|
|
||||||
@ -569,7 +570,7 @@ func (syncer *Syncer) ValidateBlock(b *FullBlock) error {
|
|||||||
return err
|
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
|
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) {
|
func NewBLSAccountActor(st *StateTree, addr address.Address) (*types.Actor, error) {
|
||||||
var acstate AccountActorState
|
var acstate actors.AccountActorState
|
||||||
acstate.Address = addr
|
acstate.Address = addr
|
||||||
|
|
||||||
c, err := st.store.Put(context.TODO(), acstate)
|
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{
|
nact := &types.Actor{
|
||||||
Code: AccountActorCodeCid,
|
Code: actors.AccountActorCodeCid,
|
||||||
Balance: types.NewInt(0),
|
Balance: types.NewInt(0),
|
||||||
Head: c,
|
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) {
|
func NewSecp256k1AccountActor(st *StateTree, addr address.Address) (*types.Actor, error) {
|
||||||
nact := &types.Actor{
|
nact := &types.Actor{
|
||||||
Code: AccountActorCodeCid,
|
Code: actors.AccountActorCodeCid,
|
||||||
Balance: types.NewInt(0),
|
Balance: types.NewInt(0),
|
||||||
Head: EmptyObjectCid,
|
Head: EmptyObjectCid,
|
||||||
}
|
}
|
||||||
|
6
chain/types/invokeret.go
Normal file
6
chain/types/invokeret.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
type InvokeRet struct {
|
||||||
|
Result []byte
|
||||||
|
ReturnCode byte
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"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"
|
||||||
@ -27,7 +25,7 @@ type StateTree interface {
|
|||||||
type VMContext interface {
|
type VMContext interface {
|
||||||
Message() *Message
|
Message() *Message
|
||||||
Ipld() *hamt.CborIpldStore
|
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
|
BlockHeight() uint64
|
||||||
GasUsed() BigInt
|
GasUsed() BigInt
|
||||||
Storage() Storage
|
Storage() Storage
|
||||||
|
55
chain/vm.go
55
chain/vm.go
@ -1,12 +1,10 @@
|
|||||||
package chain
|
package chain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"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"
|
||||||
"github.com/filecoin-project/go-lotus/lib/bufbstore"
|
"github.com/filecoin-project/go-lotus/lib/bufbstore"
|
||||||
@ -14,13 +12,13 @@ import (
|
|||||||
bserv "github.com/ipfs/go-blockservice"
|
bserv "github.com/ipfs/go-blockservice"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
|
||||||
ipld "github.com/ipfs/go-ipld-format"
|
ipld "github.com/ipfs/go-ipld-format"
|
||||||
dag "github.com/ipfs/go-merkledag"
|
dag "github.com/ipfs/go-merkledag"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VMContext struct {
|
type VMContext struct {
|
||||||
|
vm *VM
|
||||||
state *StateTree
|
state *StateTree
|
||||||
msg *types.Message
|
msg *types.Message
|
||||||
height uint64
|
height uint64
|
||||||
@ -75,8 +73,22 @@ func (vmc *VMContext) Ipld() *hamt.CborIpldStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send allows the current execution context to invoke methods on other actors in the system
|
// 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) {
|
func (vmc *VMContext) Send(to address.Address, method uint64, value types.BigInt, params []byte) ([]byte, uint8, error) {
|
||||||
panic("nyi")
|
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
|
// BlockHeight returns the height of the block this message was added to the chain in
|
||||||
@ -89,20 +101,22 @@ func (vmc *VMContext) GasUsed() types.BigInt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (vmc *VMContext) StateTree() (types.StateTree, error) {
|
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")
|
return nil, fmt.Errorf("only init actor can access state tree directly")
|
||||||
}
|
}
|
||||||
|
|
||||||
return vmc.state, nil
|
return vmc.state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeVMContext(state *StateTree, bs bstore.Blockstore, sroot cid.Cid, msg *types.Message, height uint64) *VMContext {
|
func (vm *VM) makeVMContext(sroot cid.Cid, msg *types.Message) *VMContext {
|
||||||
cst := hamt.CSTFromBstore(bs)
|
cst := hamt.CSTFromBstore(vm.cs.bs)
|
||||||
|
|
||||||
return &VMContext{
|
return &VMContext{
|
||||||
state: state,
|
vm: vm,
|
||||||
|
state: vm.cstate,
|
||||||
sroot: sroot,
|
sroot: sroot,
|
||||||
msg: msg,
|
msg: msg,
|
||||||
height: height,
|
height: vm.blockHeight,
|
||||||
cst: cst,
|
cst: cst,
|
||||||
storage: &storage{
|
storage: &storage{
|
||||||
cst: cst,
|
cst: cst,
|
||||||
@ -177,7 +191,7 @@ func (vm *VM) ApplyMessage(msg *types.Message) (*types.MessageReceipt, error) {
|
|||||||
}
|
}
|
||||||
DepositFunds(toActor, msg.Value)
|
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 errcode byte
|
||||||
var ret []byte
|
var ret []byte
|
||||||
@ -261,20 +275,5 @@ func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params [
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return ret.result, ret.returnCode, nil
|
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())
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user