2019-07-12 23:52:25 +00:00
|
|
|
package actors
|
2019-07-12 20:56:41 +00:00
|
|
|
|
|
|
|
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"
|
2019-07-17 16:00:59 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-07-12 20:56:41 +00:00
|
|
|
)
|
|
|
|
|
2019-07-15 17:48:59 +00:00
|
|
|
const SectorSize = 1024
|
|
|
|
|
2019-07-12 20:56:41 +00:00
|
|
|
func init() {
|
|
|
|
cbor.RegisterCborType(StorageMarketState{})
|
2019-07-12 21:36:49 +00:00
|
|
|
cbor.RegisterCborType(CreateStorageMinerParams{})
|
2019-07-17 14:30:55 +00:00
|
|
|
cbor.RegisterCborType(IsMinerParam{})
|
2019-07-17 16:00:59 +00:00
|
|
|
cbor.RegisterCborType(PowerLookupParams{})
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type StorageMarketActor struct{}
|
|
|
|
|
|
|
|
func (sma StorageMarketActor) Exports() []interface{} {
|
|
|
|
return []interface{}{
|
2019-07-17 13:48:20 +00:00
|
|
|
//0: sma.StorageMarketConstructor,
|
|
|
|
1: sma.CreateStorageMiner,
|
|
|
|
//2: sma.SlashConsensusFault,
|
|
|
|
3: sma.UpdateStorage,
|
|
|
|
4: sma.GetTotalStorage,
|
|
|
|
5: sma.PowerLookup,
|
2019-07-17 14:30:55 +00:00
|
|
|
6: sma.IsMiner,
|
2019-07-17 13:48:20 +00:00
|
|
|
//7: sma.StorageCollateralForSize,
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type StorageMarketState struct {
|
|
|
|
Miners map[address.Address]struct{}
|
|
|
|
TotalStorage types.BigInt
|
|
|
|
}
|
|
|
|
|
|
|
|
type CreateStorageMinerParams struct {
|
2019-07-16 16:40:25 +00:00
|
|
|
Owner address.Address
|
2019-07-12 20:56:41 +00:00
|
|
|
Worker address.Address
|
|
|
|
SectorSize types.BigInt
|
|
|
|
PeerID peer.ID
|
|
|
|
}
|
|
|
|
|
2019-07-12 23:52:25 +00:00
|
|
|
func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) (types.InvokeRet, error) {
|
2019-07-12 20:56:41 +00:00
|
|
|
if !SupportedSectorSize(params.SectorSize) {
|
|
|
|
//Fatal("Unsupported sector size")
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{
|
|
|
|
ReturnCode: 1,
|
2019-07-12 20:56:41 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-07-12 23:12:06 +00:00
|
|
|
encoded, err := CreateExecParams(StorageMinerCodeCid, &StorageMinerConstructorParams{
|
2019-07-16 16:40:25 +00:00
|
|
|
Owner: params.Owner,
|
2019-07-12 23:12:06 +00:00
|
|
|
Worker: params.Worker,
|
|
|
|
SectorSize: params.SectorSize,
|
|
|
|
PeerID: params.PeerID,
|
|
|
|
})
|
2019-07-12 20:56:41 +00:00
|
|
|
if err != nil {
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{}, err
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret, exit, err := vmctx.Send(InitActorAddress, 1, vmctx.Message().Value, encoded)
|
|
|
|
if err != nil {
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{}, err
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if exit != 0 {
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{
|
|
|
|
ReturnCode: 2,
|
2019-07-12 20:56:41 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-07-17 14:30:55 +00:00
|
|
|
naddr, err := address.NewFromBytes(ret)
|
|
|
|
if err != nil {
|
|
|
|
return types.InvokeRet{}, err
|
|
|
|
}
|
|
|
|
|
2019-07-12 20:56:41 +00:00
|
|
|
var self StorageMarketState
|
|
|
|
old := vmctx.Storage().GetHead()
|
|
|
|
if err := vmctx.Storage().Get(old, &self); err != nil {
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{}, err
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.Miners[naddr] = struct{}{}
|
|
|
|
|
|
|
|
nroot, err := vmctx.Storage().Put(self)
|
|
|
|
if err != nil {
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{}, err
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{}, err
|
2019-07-12 20:56:41 +00:00
|
|
|
}
|
|
|
|
|
2019-07-12 23:52:25 +00:00
|
|
|
return types.InvokeRet{
|
|
|
|
Result: naddr.Bytes(),
|
2019-07-12 20:56:41 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func SupportedSectorSize(ssize types.BigInt) bool {
|
2019-07-15 17:48:59 +00:00
|
|
|
if ssize.Uint64() == SectorSize {
|
2019-07-12 20:56:41 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2019-07-16 06:07:03 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-07-17 13:48:20 +00:00
|
|
|
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) (types.InvokeRet, error) {
|
2019-07-16 06:07:03 +00:00
|
|
|
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 {
|
2019-07-17 16:00:59 +00:00
|
|
|
return types.InvokeRet{}, xerrors.Errorf("getting head: %w", err)
|
2019-07-16 06:07:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := self.Miners[params.Miner]; !ok {
|
|
|
|
//Fatal("miner not registered with storage market")
|
|
|
|
return types.InvokeRet{
|
|
|
|
ReturnCode: 1,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-07-17 16:00:59 +00:00
|
|
|
ret, code, err := vmctx.Send(params.Miner, 9, types.NewInt(0), EmptyStructCBOR)
|
2019-07-16 06:07:03 +00:00
|
|
|
if err != nil {
|
2019-07-17 16:00:59 +00:00
|
|
|
return types.InvokeRet{}, xerrors.Errorf("invoke Miner.GetPower: %w", err)
|
2019-07-16 06:07:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2019-07-17 14:30:55 +00:00
|
|
|
|
|
|
|
type IsMinerParam struct {
|
|
|
|
Addr address.Address
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sma StorageMarketActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) (types.InvokeRet, error) {
|
|
|
|
var self StorageMarketState
|
|
|
|
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
|
|
|
return types.InvokeRet{}, err
|
|
|
|
}
|
|
|
|
_, ok := self.Miners[param.Addr]
|
|
|
|
out, err := SerializeParams(ok)
|
|
|
|
if err != nil {
|
|
|
|
return types.InvokeRet{}, err
|
|
|
|
}
|
|
|
|
return types.InvokeRet{
|
|
|
|
Result: out,
|
|
|
|
}, nil
|
|
|
|
}
|