implement commit sector and some storage market methods
This commit is contained in:
parent
4f8326f711
commit
ef5b54fe7f
@ -1,9 +1,13 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"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"
|
||||||
|
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
)
|
)
|
||||||
@ -11,8 +15,12 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
cbor.RegisterCborType(StorageMinerActorState{})
|
cbor.RegisterCborType(StorageMinerActorState{})
|
||||||
cbor.RegisterCborType(StorageMinerConstructorParams{})
|
cbor.RegisterCborType(StorageMinerConstructorParams{})
|
||||||
|
cbor.RegisterCborType(CommitSectorParams{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ProvingPeriodDuration = uint64(2 * 60) // an hour, for now
|
||||||
|
const POST_SECTORS_COUNT = 8192
|
||||||
|
|
||||||
type StorageMinerActor struct{}
|
type StorageMinerActor struct{}
|
||||||
|
|
||||||
type StorageMinerActorState struct {
|
type StorageMinerActorState struct {
|
||||||
@ -33,9 +41,6 @@ type StorageMinerActorState struct {
|
|||||||
// Amount of space in each sector committed to the network by this miner.
|
// Amount of space in each sector committed to the network by this miner.
|
||||||
SectorSize types.BigInt
|
SectorSize types.BigInt
|
||||||
|
|
||||||
// Collateral currently committed to live storage.
|
|
||||||
ActiveCollateral types.BigInt
|
|
||||||
|
|
||||||
// Collateral that is waiting to be withdrawn.
|
// Collateral that is waiting to be withdrawn.
|
||||||
DePledgedCollateral types.BigInt
|
DePledgedCollateral types.BigInt
|
||||||
|
|
||||||
@ -43,11 +48,13 @@ type StorageMinerActorState struct {
|
|||||||
DePledgeTime types.BigInt
|
DePledgeTime types.BigInt
|
||||||
|
|
||||||
// All sectors this miner has committed.
|
// All sectors this miner has committed.
|
||||||
//Sectors SectorSet
|
Sectors cid.Cid // TODO: Using a HAMT for now, needs to be an AMT once we implement it
|
||||||
|
SectorSetSize uint64 // TODO: the AMT should be able to tell us how many items are in it. This field won't be needed at that point
|
||||||
|
|
||||||
// Sectors this miner is currently mining. It is only updated
|
// Sectors this miner is currently mining. It is only updated
|
||||||
// when a PoSt is submitted (not as each new sector commitment is added).
|
// when a PoSt is submitted (not as each new sector commitment is added).
|
||||||
//ProvingSet SectorSet
|
ProvingSet cid.Cid
|
||||||
|
ProvingSetSize uint64
|
||||||
|
|
||||||
// Sectors reported during the last PoSt submission as being 'done'. The collateral
|
// 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
|
// for them is still being held until the next PoSt submission in case early sector
|
||||||
@ -61,6 +68,8 @@ type StorageMinerActorState struct {
|
|||||||
// Amount of power this miner has.
|
// Amount of power this miner has.
|
||||||
Power types.BigInt
|
Power types.BigInt
|
||||||
|
|
||||||
|
ProvingPeriodEnd uint64
|
||||||
|
|
||||||
// List of sectors that this miner was slashed for.
|
// List of sectors that this miner was slashed for.
|
||||||
//SlashedSet SectorSet
|
//SlashedSet SectorSet
|
||||||
|
|
||||||
@ -81,6 +90,7 @@ type StorageMinerConstructorParams struct {
|
|||||||
func (sma StorageMinerActor) Exports() []interface{} {
|
func (sma StorageMinerActor) Exports() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
sma.StorageMinerActor,
|
sma.StorageMinerActor,
|
||||||
|
sma.CommitSector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +101,14 @@ func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMC
|
|||||||
self.PeerID = params.PeerID
|
self.PeerID = params.PeerID
|
||||||
self.SectorSize = params.SectorSize
|
self.SectorSize = params.SectorSize
|
||||||
|
|
||||||
|
nd := hamt.NewNode(vmctx.Ipld())
|
||||||
|
sectors, err := vmctx.Ipld().Put(context.TODO(), nd)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
self.Sectors = sectors
|
||||||
|
self.ProvingSet = sectors
|
||||||
|
|
||||||
storage := vmctx.Storage()
|
storage := vmctx.Storage()
|
||||||
c, err := storage.Put(self)
|
c, err := storage.Put(self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -103,3 +121,127 @@ func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMC
|
|||||||
|
|
||||||
return types.InvokeRet{}, nil
|
return types.InvokeRet{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CommitSectorParams struct {
|
||||||
|
SectorId types.BigInt
|
||||||
|
CommD []byte
|
||||||
|
CommR []byte
|
||||||
|
CommRStar []byte
|
||||||
|
Proof []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContext, params *CommitSectorParams) (types.InvokeRet, error) {
|
||||||
|
var self StorageMinerActorState
|
||||||
|
oldstate := vmctx.Storage().GetHead()
|
||||||
|
if err := vmctx.Storage().Get(oldstate, &self); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ValidatePoRep(self.SectorSize, params) {
|
||||||
|
//Fatal("bad proof!")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 1,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the miner isnt trying to submit a pre-existing sector
|
||||||
|
unique, err := SectorIsUnique(vmctx.Ipld(), self.Sectors, params.SectorId)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
if !unique {
|
||||||
|
//Fatal("sector already committed!")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 2,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Power of the miner after adding this sector
|
||||||
|
futurePower := types.BigAdd(self.Power, self.SectorSize)
|
||||||
|
collateralRequired := CollateralForPower(futurePower)
|
||||||
|
|
||||||
|
if types.BigCmp(collateralRequired, act.Balance) < 0 {
|
||||||
|
//Fatal("not enough collateral")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 3,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that the miner cannot commit more sectors than can be proved with a single PoSt
|
||||||
|
if self.SectorSetSize >= POST_SECTORS_COUNT {
|
||||||
|
// Fatal("too many sectors")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 4,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: There must exist a unique index in the miner's sector set for each
|
||||||
|
// sector ID. The `faults`, `recovered`, and `done` parameters of the
|
||||||
|
// SubmitPoSt method express indices into this sector set.
|
||||||
|
nssroot, err := AddToSectorSet(self.Sectors, params.SectorId, params.CommR, params.CommD)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
self.Sectors = nssroot
|
||||||
|
|
||||||
|
// if miner is not mining, start their proving period now
|
||||||
|
// Note: As written here, every miners first PoSt will only be over one sector.
|
||||||
|
// We could set up a 'grace period' for starting mining that would allow miners
|
||||||
|
// to submit several sectors for their first proving period. Alternatively, we
|
||||||
|
// could simply make the 'CommitSector' call take multiple sectors at a time.
|
||||||
|
//
|
||||||
|
// Note: Proving period is a function of sector size; small sectors take less
|
||||||
|
// time to prove than large sectors do. Sector size is selected when pledging.
|
||||||
|
if self.ProvingSetSize == 0 {
|
||||||
|
self.ProvingSet = self.Sectors
|
||||||
|
self.ProvingSetSize = self.SectorSetSize
|
||||||
|
self.ProvingPeriodEnd = vmctx.BlockHeight() + ProvingPeriodDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
nstate, err := vmctx.Storage().Put(self)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.InvokeRet{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SectorIsUnique(cst *hamt.CborIpldStore, sroot cid.Cid, sid types.BigInt) (bool, error) {
|
||||||
|
nd, err := hamt.LoadNode(context.TODO(), cst, sroot)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := nd.Find(context.TODO(), sid.String()); err != nil {
|
||||||
|
if err == hamt.ErrNotFound {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddToSectorSet(ss cid.Cid, sectorID types.BigInt, commR, commD []byte) (cid.Cid, error) {
|
||||||
|
panic("NYI")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidatePoRep(ssize types.BigInt, params *CommitSectorParams) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func CollateralForPower(power types.BigInt) types.BigInt {
|
||||||
|
return types.BigMul(power, types.NewInt(10))
|
||||||
|
/* TODO: this
|
||||||
|
availableFil = FakeGlobalMethods.GetAvailableFil()
|
||||||
|
totalNetworkPower = StorageMinerActor.GetTotalStorage()
|
||||||
|
numMiners = StorageMarket.GetMinerCount()
|
||||||
|
powerCollateral = availableFil * NetworkConstants.POWER_COLLATERAL_PROPORTION * power / totalNetworkPower
|
||||||
|
perCapitaCollateral = availableFil * NetworkConstants.PER_CAPITA_COLLATERAL_PROPORTION / numMiners
|
||||||
|
collateralRequired = math.Ceil(minerPowerCollateral + minerPerCapitaCollateral)
|
||||||
|
return collateralRequired
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
@ -21,6 +21,8 @@ func (sma StorageMarketActor) Exports() []interface{} {
|
|||||||
return []interface{}{
|
return []interface{}{
|
||||||
nil,
|
nil,
|
||||||
sma.CreateStorageMiner,
|
sma.CreateStorageMiner,
|
||||||
|
nil, // TODO: slash consensus fault
|
||||||
|
sma.UpdateStorage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,3 +100,70 @@ func SupportedSectorSize(ssize types.BigInt) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateStorageParams struct {
|
||||||
|
Delta types.BigInt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) (types.InvokeRet, error) {
|
||||||
|
var self StorageMarketState
|
||||||
|
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := self.Miners[vmctx.Message().From]
|
||||||
|
if !ok {
|
||||||
|
//Fatal("update storage must only be called by a miner actor")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 1,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
|
||||||
|
return types.InvokeRet{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params struct{}) (types.InvokeRet, error) {
|
||||||
|
var self StorageMarketState
|
||||||
|
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.InvokeRet{
|
||||||
|
Result: self.TotalStorage.Bytes(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PowerLookupParams struct {
|
||||||
|
Miner address.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) (types.InvokeRet, error) {
|
||||||
|
var self StorageMarketState
|
||||||
|
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := self.Miners[params.Miner]; !ok {
|
||||||
|
//Fatal("miner not registered with storage market")
|
||||||
|
return types.InvokeRet{
|
||||||
|
ReturnCode: 1,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, code, err := vmctx.Send(params.Miner, 9999, types.NewInt(0), nil)
|
||||||
|
if err != nil {
|
||||||
|
return types.InvokeRet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if code != 0 {
|
||||||
|
return types.InvokeRet{
|
||||||
|
// TODO: error handling... these codes really don't tell us what the problem is very well
|
||||||
|
ReturnCode: code,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.InvokeRet{
|
||||||
|
Result: ret,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user