lotus/chain/actors/actor_storagemarket.go
2019-08-16 13:24:37 -07:00

190 lines
4.7 KiB
Go

package actors
import (
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"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(IsMinerParam{})
cbor.RegisterCborType(PowerLookupParams{})
cbor.RegisterCborType(UpdateStorageParams{})
}
type StorageMarketActor struct{}
type smaMethods struct {
Constructor uint64
CreateStorageMiner uint64
SlashConsensusFault uint64
UpdateStorage uint64
GetTotalStorage uint64
PowerLookup uint64
IsMiner uint64
}
var SMAMethods = smaMethods{1, 2, 3, 4, 5, 6, 7}
func (sma StorageMarketActor) Exports() []interface{} {
return []interface{}{
//1: sma.StorageMarketConstructor,
2: sma.CreateStorageMiner,
//3: sma.SlashConsensusFault,
4: sma.UpdateStorage,
5: sma.GetTotalStorage,
6: sma.PowerLookup,
7: sma.IsMiner,
//8: sma.StorageCollateralForSize,
}
}
type StorageMarketState struct {
Miners map[address.Address]struct{}
TotalStorage types.BigInt
}
type CreateStorageMinerParams struct {
Owner address.Address
Worker address.Address
SectorSize types.BigInt
PeerID peer.ID
}
func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
if !SupportedSectorSize(params.SectorSize) {
return nil, aerrors.New(1, "Unsupported sector size")
}
encoded, err := CreateExecParams(StorageMinerCodeCid, &StorageMinerConstructorParams{
Owner: params.Owner,
Worker: params.Worker,
SectorSize: params.SectorSize,
PeerID: params.PeerID,
})
if err != nil {
return nil, err
}
ret, err := vmctx.Send(InitActorAddress, IAMethods.Exec, vmctx.Message().Value, encoded)
if err != nil {
return nil, err
}
naddr, nerr := address.NewFromBytes(ret)
if nerr != nil {
return nil, aerrors.Absorb(nerr, 1, "could not read address of new actor")
}
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
self.Miners[naddr] = struct{}{}
nroot, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return naddr.Bytes(), nil
}
func SupportedSectorSize(ssize types.BigInt) bool {
if ssize.Uint64() == SectorSize {
return true
}
return false
}
type UpdateStorageParams struct {
Delta types.BigInt
}
func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
_, ok := self.Miners[vmctx.Message().From]
if !ok {
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
}
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
nroot, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return nil, nil
}
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
var self StorageMarketState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
return self.TotalStorage.Bytes(), nil
}
type PowerLookupParams struct {
Miner address.Address
}
func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
var self StorageMarketState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, aerrors.Wrap(err, "getting head")
}
if _, ok := self.Miners[params.Miner]; !ok {
return nil, aerrors.New(1, "miner not registered with storage market")
}
ret, err := vmctx.Send(params.Miner, MAMethods.GetPower, types.NewInt(0), EmptyStructCBOR)
if err != nil {
return nil, aerrors.Wrap(err, "invoke Miner.GetPower")
}
return ret, nil
}
type IsMinerParam struct {
Addr address.Address
}
func (sma StorageMarketActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
var self StorageMarketState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
_, ok := self.Miners[param.Addr]
out, err := SerializeParams(ok)
if err != nil {
return nil, err
}
return out, nil
}