Fix the rest of power slashing issues
This commit is contained in:
parent
f4fc3bcc29
commit
e9631601e3
@ -63,6 +63,9 @@ type StorageMinerActorState struct {
|
|||||||
// Amount of power this miner has.
|
// Amount of power this miner has.
|
||||||
Power types.BigInt
|
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.
|
// The height at which this miner was slashed at.
|
||||||
SlashedAt uint64
|
SlashedAt uint64
|
||||||
|
|
||||||
@ -126,7 +129,7 @@ type maMethods struct {
|
|||||||
GetSectorSize uint64
|
GetSectorSize uint64
|
||||||
UpdatePeerID uint64
|
UpdatePeerID uint64
|
||||||
ChangeWorker uint64
|
ChangeWorker uint64
|
||||||
IsLate uint64
|
IsSlashed uint64
|
||||||
CheckMiner uint64
|
CheckMiner uint64
|
||||||
DeclareFaults uint64
|
DeclareFaults uint64
|
||||||
SlashConsensusFault uint64
|
SlashConsensusFault uint64
|
||||||
@ -151,7 +154,7 @@ func (sma StorageMinerActor) Exports() []interface{} {
|
|||||||
13: sma.GetSectorSize,
|
13: sma.GetSectorSize,
|
||||||
14: sma.UpdatePeerID,
|
14: sma.UpdatePeerID,
|
||||||
//15: sma.ChangeWorker,
|
//15: sma.ChangeWorker,
|
||||||
16: sma.IsLate,
|
16: sma.IsSlashed,
|
||||||
17: sma.CheckMiner,
|
17: sma.CheckMiner,
|
||||||
18: sma.DeclareFaults,
|
18: sma.DeclareFaults,
|
||||||
19: sma.SlashConsensusFault,
|
19: sma.SlashConsensusFault,
|
||||||
@ -530,10 +533,16 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
|
|||||||
delta = self.Power
|
delta = self.Power
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevPE := self.ProvingPeriodEnd
|
||||||
|
if !self.Active {
|
||||||
|
self.Active = true
|
||||||
|
prevPE = 0
|
||||||
|
}
|
||||||
|
|
||||||
enc, err := SerializeParams(&UpdateStorageParams{
|
enc, err := SerializeParams(&UpdateStorageParams{
|
||||||
Delta: delta,
|
Delta: delta,
|
||||||
NextProvingPeriodEnd: currentProvingPeriodEnd + build.ProvingPeriodDuration,
|
NextProvingPeriodEnd: currentProvingPeriodEnd + build.ProvingPeriodDuration,
|
||||||
PreviousProvingPeriodEnd: currentProvingPeriodEnd,
|
PreviousProvingPeriodEnd: prevPE,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -740,16 +749,16 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isLate(height uint64, self *StorageMinerActorState) bool {
|
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)
|
_, self, err := loadState(vmctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cbg.EncodeBool(isLate(vmctx.BlockHeight(), self)), nil
|
return cbg.EncodeBool(self.SlashedAt != 0), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckMinerParams struct {
|
type CheckMinerParams struct {
|
||||||
|
@ -3,19 +3,19 @@ package actors
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"github.com/filecoin-project/go-amt-ipld"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/go-amt-ipld"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/address"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
xerrors "golang.org/x/xerrors"
|
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{}
|
type StoragePowerActor struct{}
|
||||||
@ -444,11 +444,11 @@ func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerS
|
|||||||
return types.BigFromBytes(ret), nil
|
return types.BigFromBytes(ret), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type IsMinerParam struct {
|
type IsValidMinerParam struct {
|
||||||
Addr address.Address
|
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
|
var self StoragePowerState
|
||||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -460,17 +460,23 @@ func (spa StoragePowerActor) IsValidMiner(act *types.Actor, vmctx types.VMContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !has {
|
if !has {
|
||||||
|
log.Warnf("Miner INVALID: not in set: %s", param.Addr)
|
||||||
|
|
||||||
return cbg.CborBoolFalse, nil
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
type PledgeCollateralParams struct {
|
||||||
@ -602,7 +608,7 @@ func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types
|
|||||||
}
|
}
|
||||||
|
|
||||||
if power.GreaterThan(types.NewInt(0)) {
|
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)
|
self.TotalStorage = types.BigSub(self.TotalStorage, power)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner,
|
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner,
|
||||||
&IsMinerParam{Addr: minerAddr})
|
&IsValidMinerParam{Addr: minerAddr})
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
|
|
||||||
var output bool
|
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)
|
ApplyOK(t, ret)
|
||||||
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
|
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
|
|||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write([]byte{138}); err != nil {
|
if _, err := w.Write([]byte{139}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +268,11 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// t.t.Active (bool) (bool)
|
||||||
|
if err := cbg.WriteBool(w, t.Active); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// t.t.SlashedAt (uint64) (uint64)
|
// t.t.SlashedAt (uint64) (uint64)
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SlashedAt))); err != nil {
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SlashedAt))); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -291,7 +296,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return fmt.Errorf("cbor input should be of type array")
|
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")
|
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)
|
// t.t.SlashedAt (uint64) (uint64)
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
@ -2574,7 +2596,7 @@ func (t *CreateStorageMinerParams) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *IsMinerParam) MarshalCBOR(w io.Writer) error {
|
func (t *IsValidMinerParam) MarshalCBOR(w io.Writer) error {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
@ -2590,7 +2612,7 @@ func (t *IsMinerParam) MarshalCBOR(w io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *IsMinerParam) UnmarshalCBOR(r io.Reader) error {
|
func (t *IsValidMinerParam) UnmarshalCBOR(r io.Reader) error {
|
||||||
br := cbg.GetPeeker(r)
|
br := cbg.GetPeeker(r)
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
maj, extra, err := cbg.CborReadHeader(br)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package chain
|
package chain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"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 {
|
func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error {
|
||||||
var err error
|
var err error
|
||||||
enc, err := actors.SerializeParams(&actors.IsMinerParam{Addr: maddr})
|
enc, err := actors.SerializeParams(&actors.IsValidMinerParam{Addr: maddr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -516,6 +519,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
|
|
||||||
minerCheck := async.Err(func() error {
|
minerCheck := async.Err(func() error {
|
||||||
if err := syncer.minerIsValid(ctx, h.Miner, baseTs); err != nil {
|
if err := syncer.minerIsValid(ctx, h.Miner, baseTs); err != nil {
|
||||||
|
log.Errorf("minerIsValid: %+v", err)
|
||||||
return xerrors.Errorf("minerIsValid failed: %w", err)
|
return xerrors.Errorf("minerIsValid failed: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -589,7 +593,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
var merr error
|
var merr error
|
||||||
for _, fut := range await {
|
for _, fut := range await {
|
||||||
if err := fut.AwaitContext(ctx); err != nil {
|
if err := fut.AwaitContext(ctx); err != nil {
|
||||||
err = multierror.Append(merr, err)
|
merr = multierror.Append(merr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ func main() {
|
|||||||
actors.PaymentInfo{},
|
actors.PaymentInfo{},
|
||||||
actors.StoragePowerState{},
|
actors.StoragePowerState{},
|
||||||
actors.CreateStorageMinerParams{},
|
actors.CreateStorageMinerParams{},
|
||||||
actors.IsMinerParam{},
|
actors.IsValidMinerParam{},
|
||||||
actors.PowerLookupParams{},
|
actors.PowerLookupParams{},
|
||||||
actors.UpdateStorageParams{},
|
actors.UpdateStorageParams{},
|
||||||
actors.ArbitrateConsensusFaultParams{},
|
actors.ArbitrateConsensusFaultParams{},
|
||||||
|
Loading…
Reference in New Issue
Block a user