actors: CheckMiner methods on Miner/Power actors

This commit is contained in:
Łukasz Magiera 2019-11-13 23:40:51 +01:00
parent 6b398cba74
commit e094ace303
3 changed files with 114 additions and 129 deletions

View File

@ -62,14 +62,8 @@ type StorageMinerActorState 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
SlashedAt uint64
ProvingPeriodEnd uint64
}
@ -131,13 +125,12 @@ type maMethods struct {
GetSectorSize uint64
UpdatePeerID uint64
ChangeWorker uint64
IsSlashed uint64
IsLate uint64
CheckMiner uint64
DeclareFaults uint64
SlashConsensusFault uint64
}
var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}
func (sma StorageMinerActor) Exports() []interface{} {
return []interface{}{
@ -156,10 +149,9 @@ func (sma StorageMinerActor) Exports() []interface{} {
13: sma.GetSectorSize,
14: sma.UpdatePeerID,
//15: sma.ChangeWorker,
//16: sma.IsSlashed,
//17: sma.IsLate,
18: sma.DeclareFaults,
19: sma.SlashConsensusFault,
16: sma.CheckMiner,
17: sma.DeclareFaults,
18: sma.SlashConsensusFault,
}
}
@ -529,8 +521,14 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))),
types.NewInt(mi.SectorSize))
delta := types.BigSub(self.Power, oldPower)
if self.SlashedAt != 0 {
self.SlashedAt = 0
delta = self.Power
}
enc, err := SerializeParams(&UpdateStorageParams{
Delta: types.BigSub(self.Power, oldPower),
Delta: delta,
NextProvingPeriodEnd: currentProvingPeriodEnd + build.ProvingPeriodDuration,
PreviousProvingPeriodEnd: currentProvingPeriodEnd,
})
@ -738,9 +736,40 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte
return types.NewInt(mi.SectorSize).Bytes(), nil
}
type PaymentVerifyParams struct {
Extra []byte
Proof []byte
// TODO: better name
func (sma StorageMinerActor) CheckMiner(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
if vmctx.Message().From != StoragePowerAddress {
return nil, aerrors.New(2, "only the storage power actor can check miner")
}
oldstate, self, err := loadState(vmctx)
if err != nil {
return nil, err
}
if vmctx.BlockHeight() < self.ProvingPeriodEnd {
// Everything's fine
return cbg.EncodeBool(true), nil
}
if self.SlashedAt != 0 {
// Don't slash more than necessary
return nil, nil
}
// Slash for being late
self.SlashedAt = vmctx.BlockHeight()
nstate, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
return nil, err
}
return self.Power.Bytes(), nil
}
type DeclareFaultsParams struct {

View File

@ -27,9 +27,10 @@ type spaMethods struct {
PowerLookup uint64
IsMiner uint64
PledgeCollateralForSize uint64
CheckProofSubmissions uint64
}
var SPAMethods = spaMethods{1, 2, 3, 4, 5, 6, 7, 8}
var SPAMethods = spaMethods{1, 2, 3, 4, 5, 6, 7, 8, 9}
func (spa StoragePowerActor) Exports() []interface{} {
return []interface{}{
@ -41,6 +42,7 @@ func (spa StoragePowerActor) Exports() []interface{} {
6: spa.PowerLookup,
7: spa.IsMiner,
8: spa.PledgeCollateralForSize,
9: spa.CheckProofSubmissions,
}
}
@ -273,13 +275,8 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
return nil, err
}
has, err := MinerSetHas(vmctx, self.Miners, vmctx.Message().From)
if err != nil {
return nil, err
}
if !has {
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
if vmctx.Message().From.Protocol() != address.Actor {
return nil, aerrors.New(1, "update storage must only be called by an actor")
}
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
@ -529,6 +526,68 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big
return types.BigAdd(powerCollateral, perCapCollateral), nil
}
func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types.VMContext, param *struct{}) ([]byte, ActorError) {
if vmctx.Message().From != StoragePowerAddress {
return nil, aerrors.New(1, "CheckProofSubmissions is only callable as a part of tipset state computation")
}
bucketID := vmctx.BlockHeight() % build.ProvingPeriodDuration
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
buckets, eerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingBuckets)
if eerr != nil {
return nil, aerrors.HandleExternalError(eerr, "loading proving buckets amt")
}
var bucket cid.Cid
err := buckets.Get(bucketID, &bucket)
switch err.(type) {
case amt.ErrNotFound:
return nil, nil // nothing to do
case nil:
default:
return nil, aerrors.HandleExternalError(err, "getting proving bucket")
}
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
if err != nil {
return nil, aerrors.HandleExternalError(err, "failed to load proving bucket")
}
err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error {
maddr, err := address.NewFromBytes([]byte(k))
if err != nil {
return aerrors.Escalate(err, "parsing miner address")
}
ret, err := vmctx.Send(maddr, MAMethods.CheckMiner, vmctx.Message().Value, nil)
if err != nil {
return err
}
if len(ret) == 0 {
return nil // miner is fine
}
power := types.NewInt(0)
power.SetBytes(ret)
self.TotalStorage = types.BigSub(self.TotalStorage, power)
return nil
})
if err != nil {
return nil, aerrors.HandleExternalError(err, "iterating miners in proving bucket")
}
return nil, nil
}
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
if err != nil {

View File

@ -268,15 +268,6 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.SlashedAt (types.BigInt) (struct)
if err := t.SlashedAt.MarshalCBOR(w); err != nil {
return err
}
// t.t.OwedStorageCollateral (types.BigInt) (struct)
if err := t.OwedStorageCollateral.MarshalCBOR(w); err != nil {
return err
}
// t.t.ProvingPeriodEnd (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ProvingPeriodEnd))); err != nil {
@ -427,22 +418,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
}
// t.t.SlashedAt (types.BigInt) (struct)
{
if err := t.SlashedAt.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.t.OwedStorageCollateral (types.BigInt) (struct)
{
if err := t.OwedStorageCollateral.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.t.ProvingPeriodEnd (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
@ -886,85 +862,6 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *PaymentVerifyParams) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{130}); err != nil {
return err
}
// t.t.Extra ([]uint8) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Extra)))); err != nil {
return err
}
if _, err := w.Write(t.Extra); err != nil {
return err
}
// t.t.Proof ([]uint8) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
if _, err := w.Write(t.Proof); err != nil {
return err
}
return nil
}
func (t *PaymentVerifyParams) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 2 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.t.Extra ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Extra: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.Extra = make([]byte, extra)
if _, err := io.ReadFull(br, t.Extra); err != nil {
return err
}
// t.t.Proof ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Proof: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.Proof = make([]byte, extra)
if _, err := io.ReadFull(br, t.Proof); err != nil {
return err
}
return nil
}
func (t *UpdatePeerIDParams) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)