integrating storage market actor, includes cross actor messaging
This commit is contained in:
parent
60a767da7d
commit
9747ed3bef
98
chain/actor_miner.go
Normal file
98
chain/actor_miner.go
Normal file
@ -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
|
||||
}
|
104
chain/actor_storagemarket.go
Normal file
104
chain/actor_storagemarket.go
Normal file
@ -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
|
||||
}
|
@ -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()
|
||||
|
||||
|
@ -103,7 +103,6 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/*
|
||||
smact, err := SetupStorageMarketActor(bs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -112,7 +111,6 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
||||
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")
|
||||
|
@ -27,6 +27,7 @@ func newInvoker() *invoker {
|
||||
|
||||
// add builtInCode using: register(cid, singleton)
|
||||
inv.register(InitActorCodeCid, InitActor{})
|
||||
inv.register(StorageMarketActorCodeCid, StorageMarketActor{})
|
||||
|
||||
return inv
|
||||
}
|
||||
|
@ -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
|
||||
|
33
chain/vm.go
33
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
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user