Fix the rest of power slashing issues

This commit is contained in:
Łukasz Magiera 2019-11-14 17:14:52 +01:00
parent f4fc3bcc29
commit e9631601e3
6 changed files with 69 additions and 28 deletions

View File

@ -63,6 +63,9 @@ type StorageMinerActorState struct {
// Amount of power this miner has.
Power types.BigInt
// Active is set to true after the miner has submitted their first PoSt
Active bool
// The height at which this miner was slashed at.
SlashedAt uint64
@ -126,7 +129,7 @@ type maMethods struct {
GetSectorSize uint64
UpdatePeerID uint64
ChangeWorker uint64
IsLate uint64
IsSlashed uint64
CheckMiner uint64
DeclareFaults uint64
SlashConsensusFault uint64
@ -151,7 +154,7 @@ func (sma StorageMinerActor) Exports() []interface{} {
13: sma.GetSectorSize,
14: sma.UpdatePeerID,
//15: sma.ChangeWorker,
16: sma.IsLate,
16: sma.IsSlashed,
17: sma.CheckMiner,
18: sma.DeclareFaults,
19: sma.SlashConsensusFault,
@ -530,10 +533,16 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
delta = self.Power
}
prevPE := self.ProvingPeriodEnd
if !self.Active {
self.Active = true
prevPE = 0
}
enc, err := SerializeParams(&UpdateStorageParams{
Delta: delta,
NextProvingPeriodEnd: currentProvingPeriodEnd + build.ProvingPeriodDuration,
PreviousProvingPeriodEnd: currentProvingPeriodEnd,
PreviousProvingPeriodEnd: prevPE,
})
if err != nil {
return nil, err
@ -740,16 +749,16 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte
}
func isLate(height uint64, self *StorageMinerActorState) bool {
return self.ProvingPeriodEnd == 0 || height >= self.ProvingPeriodEnd // TODO: review: maybe > ?
return self.ProvingPeriodEnd > 0 && height >= self.ProvingPeriodEnd // TODO: review: maybe > ?
}
func (sma StorageMinerActor) IsLate(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
func (sma StorageMinerActor) IsSlashed(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
_, self, err := loadState(vmctx)
if err != nil {
return nil, err
}
return cbg.EncodeBool(isLate(vmctx.BlockHeight(), self)), nil
return cbg.EncodeBool(self.SlashedAt != 0), nil
}
type CheckMinerParams struct {

View File

@ -3,19 +3,19 @@ package actors
import (
"bytes"
"context"
"github.com/filecoin-project/go-amt-ipld"
"io"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/go-amt-ipld"
cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)
type StoragePowerActor struct{}
@ -444,11 +444,11 @@ func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerS
return types.BigFromBytes(ret), nil
}
type IsMinerParam struct {
type IsValidMinerParam struct {
Addr address.Address
}
func (spa StoragePowerActor) IsValidMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
func (spa StoragePowerActor) IsValidMiner(act *types.Actor, vmctx types.VMContext, param *IsValidMinerParam) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
@ -460,17 +460,23 @@ func (spa StoragePowerActor) IsValidMiner(act *types.Actor, vmctx types.VMContex
}
if !has {
log.Warnf("Miner INVALID: not in set: %s", param.Addr)
return cbg.CborBoolFalse, nil
}
ret, err := vmctx.Send(param.Addr, MAMethods.IsLate, types.NewInt(0), nil)
ret, err := vmctx.Send(param.Addr, MAMethods.IsSlashed, types.NewInt(0), nil)
if err != nil {
return nil, err
}
late := bytes.Equal(ret, cbg.CborBoolTrue)
slashed := bytes.Equal(ret, cbg.CborBoolTrue)
return cbg.EncodeBool(!late), nil
if slashed {
log.Warnf("Miner INVALID: /SLASHED/ : %s", param.Addr)
}
return cbg.EncodeBool(!slashed), nil
}
type PledgeCollateralParams struct {
@ -602,7 +608,7 @@ func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types
}
if power.GreaterThan(types.NewInt(0)) {
log.Warnf("slashing miner %s for missed PoSt (%s B)", maddr, power)
log.Warnf("slashing miner %s for missed PoSt (%s B, H: %d, Bucket: %d)", maddr, power, vmctx.BlockHeight(), bucketID)
self.TotalStorage = types.BigSub(self.TotalStorage, power)
}

View File

@ -53,7 +53,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
{
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner,
&IsMinerParam{Addr: minerAddr})
&IsValidMinerParam{Addr: minerAddr})
ApplyOK(t, ret)
var output bool
@ -108,7 +108,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
}
{
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner, &IsMinerParam{minerAddr})
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner, &IsValidMinerParam{minerAddr})
ApplyOK(t, ret)
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
}

View File

@ -198,7 +198,7 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{138}); err != nil {
if _, err := w.Write([]byte{139}); err != nil {
return err
}
@ -268,6 +268,11 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.Active (bool) (bool)
if err := cbg.WriteBool(w, t.Active); err != nil {
return err
}
// t.t.SlashedAt (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SlashedAt))); err != nil {
return err
@ -291,7 +296,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 10 {
if extra != 11 {
return fmt.Errorf("cbor input had wrong number of fields")
}
@ -420,6 +425,23 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
}
}
// t.t.Active (bool) (bool)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajOther {
return fmt.Errorf("booleans must be major type 7")
}
switch extra {
case 20:
t.Active = false
case 21:
t.Active = true
default:
return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
}
// t.t.SlashedAt (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
@ -2574,7 +2596,7 @@ func (t *CreateStorageMinerParams) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *IsMinerParam) MarshalCBOR(w io.Writer) error {
func (t *IsValidMinerParam) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
@ -2590,7 +2612,7 @@ func (t *IsMinerParam) MarshalCBOR(w io.Writer) error {
return nil
}
func (t *IsMinerParam) UnmarshalCBOR(r io.Reader) error {
func (t *IsValidMinerParam) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)

View File

@ -1,6 +1,7 @@
package chain
import (
"bytes"
"context"
"errors"
"fmt"
@ -418,7 +419,7 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error {
var err error
enc, err := actors.SerializeParams(&actors.IsMinerParam{Addr: maddr})
enc, err := actors.SerializeParams(&actors.IsValidMinerParam{Addr: maddr})
if err != nil {
return err
}
@ -437,7 +438,9 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
return xerrors.Errorf("StorageMarket.IsValidMiner check failed (exit code %d)", ret.ExitCode)
}
// TODO: ensure the miner is currently not late on their PoSt submission (this hasnt landed in the spec yet)
if !bytes.Equal(ret.Return, cbg.CborBoolTrue) {
return xerrors.New("miner isn't valid")
}
return nil
}
@ -516,6 +519,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
minerCheck := async.Err(func() error {
if err := syncer.minerIsValid(ctx, h.Miner, baseTs); err != nil {
log.Errorf("minerIsValid: %+v", err)
return xerrors.Errorf("minerIsValid failed: %w", err)
}
return nil
@ -589,7 +593,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
var merr error
for _, fut := range await {
if err := fut.AwaitContext(ctx); err != nil {
err = multierror.Append(merr, err)
merr = multierror.Append(merr, err)
}
}

View File

@ -110,7 +110,7 @@ func main() {
actors.PaymentInfo{},
actors.StoragePowerState{},
actors.CreateStorageMinerParams{},
actors.IsMinerParam{},
actors.IsValidMinerParam{},
actors.PowerLookupParams{},
actors.UpdateStorageParams{},
actors.ArbitrateConsensusFaultParams{},