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().
|
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()
|
||||||
|
|
||||||
|
@ -103,16 +103,14 @@ func MakeInitialStateTree(bs bstore.Blockstore, actors map[address.Address]types
|
|||||||
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(StorageMarketAddress, smact); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
err = state.SetActor(NetworkAddress, &types.Actor{
|
err = state.SetActor(NetworkAddress, &types.Actor{
|
||||||
Code: AccountActorCodeCid,
|
Code: AccountActorCodeCid,
|
||||||
@ -137,11 +135,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 := &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 +146,13 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*Actor, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Actor{
|
return &types.Actor{
|
||||||
Code: StorageMarketActorCodeCid,
|
Code: 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")
|
||||||
|
@ -27,6 +27,7 @@ func newInvoker() *invoker {
|
|||||||
|
|
||||||
// add builtInCode using: register(cid, singleton)
|
// add builtInCode using: register(cid, singleton)
|
||||||
inv.register(InitActorCodeCid, InitActor{})
|
inv.register(InitActorCodeCid, InitActor{})
|
||||||
|
inv.register(StorageMarketActorCodeCid, StorageMarketActor{})
|
||||||
|
|
||||||
return inv
|
return inv
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
33
chain/vm.go
33
chain/vm.go
@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"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,13 +13,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 +74,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
|
||||||
@ -96,13 +109,15 @@ func (vmc *VMContext) StateTree() (types.StateTree, error) {
|
|||||||
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 +192,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
|
||||||
|
@ -89,3 +89,69 @@ func TestVMInvokeMethod(t *testing.T) {
|
|||||||
t.Fatal("hold up")
|
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