Fix slashing / power recovery issues

This commit is contained in:
Łukasz Magiera 2019-11-29 21:18:34 +01:00
parent adf71f502c
commit 703bc7e774
9 changed files with 58 additions and 33 deletions

View File

@ -5,10 +5,22 @@ package build
import "os"
// Seconds
const BlockDelay = 4
const BlockDelay = 6
// Blocks
const ProvingPeriodDuration uint64 = 40
// FallbackPoStDelay is the number of epochs the miner needs to wait after
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStDelay = 10
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed
//
// Epochs
const SlashablePowerDelay = 20
// Epochs
const InteractivePoRepDelay = 2
func init() {
os.Setenv("TRUST_PARAMS", "1")

View File

@ -5,5 +5,17 @@ package build
// Seconds
const BlockDelay = 12
// Blocks
const ProvingPeriodDuration uint64 = 300
// FallbackPoStDelay is the number of epochs the miner needs to wait after
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStDelay = 1000
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed
//
// Epochs
const SlashablePowerDelay = 2000
// Epochs
const InteractivePoRepDelay = 10

View File

@ -57,13 +57,6 @@ const WRatioDen = 2
// /////
// Proofs
// PoStRandomnessLookback is additional randomness lookback for PoSt computation
// To compute randomness epoch in a given proving period:
// RandH = PPE - PoStChallangeTime - PoStRandomnessLookback
//
// Epochs
const PoStRandomnessLookback = 1
// Epochs
const SealRandomnessLookback = Finality
@ -75,16 +68,6 @@ const SectorChallengeRatioDiv = 25
const MaxFallbackPostChallengeCount = 10
// FallbackPoStDelay is the number of epochs the miner needs to wait after
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStDelay = 1000
// SlashablePowerDelay is the number of epochs
// Epochs
const SlashablePowerDelay = 2000
// /////
// Mining
@ -95,9 +78,6 @@ const PowerCollateralProportion = 5
const PerCapitaCollateralProportion = 1
const CollateralPrecision = 1000
// Epochs
const InteractivePoRepDelay = 10
// /////
// Devnet settings

View File

@ -854,6 +854,10 @@ func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VM
return nil, aerr
}
if self.SlashedAt != 0 {
return nil, aerrors.New(1, "slashed miners can't perform election PoSt")
}
if err := onSuccessfulPoSt(self, vmctx); err != nil {
return nil, err
}

View File

@ -548,9 +548,7 @@ func (sma StorageMarketActor) ProcessStorageDealsPayment(act *types.Actor, vmctx
return nil, nil
}
// todo: check math (written on a plane, also tired)
// TODO: division is hard, this more than likely has some off-by-one issue
toPay := types.BigMul(dealInfo.Deal.Proposal.StoragePricePerEpoch, types.NewInt(build.ProvingPeriodDuration))
toPay := types.BigMul(dealInfo.Deal.Proposal.StoragePricePerEpoch, types.NewInt(build.SlashablePowerDelay))
b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, dealInfo.Deal.Proposal.Client, providerWorker)
if aerr != nil {

View File

@ -289,8 +289,8 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
previousBucket := params.PreviousProvingPeriodEnd % build.ProvingPeriodDuration
nextBucket := params.NextProvingPeriodEnd % build.ProvingPeriodDuration
previousBucket := params.PreviousProvingPeriodEnd % build.SlashablePowerDelay
nextBucket := params.NextProvingPeriodEnd % build.SlashablePowerDelay
if previousBucket == nextBucket && params.PreviousProvingPeriodEnd != 0 {
nroot, err := vmctx.Storage().Put(&self)
@ -601,7 +601,7 @@ func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types
}
func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, height uint64) aerrors.ActorError {
bucketID := height % build.ProvingPeriodDuration
bucketID := height % build.SlashablePowerDelay
buckets, eerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingBuckets)
if eerr != nil {

View File

@ -181,7 +181,7 @@ class MinerState extends React.Component {
<div>Worker: <Address addr={this.state.worker} client={this.props.client} mountWindow={this.props.mountWindow}/></div>
<div>Sector Size: <b>{this.state.sectorSize/1024}</b> KiB</div>
<div>Power: <b>{state.Power}</b> (<b>{state.Power/this.state.networkPower*100}</b>%)</div>
<div>Proving Period End: <b>{state.ProvingPeriodEnd}</b></div>
<div>Election Period Start: <b>{state.ElectionPeriodStart}</b></div>
<div>Slashed: <b>{state.SlashedAt === 0 ? "NO" : state.SlashedAt}</b></div>
<div>
<div>----</div>

View File

@ -120,7 +120,7 @@ class StorageNode extends React.Component {
</div>
<div>
<Address client={this.props.fullConn} addr={this.state.actor} mountWindow={this.props.mountWindow}/>
<span>&nbsp;<abbr title="Proving period end">PPE:</abbr> <b>{this.state.actorState.State.ProvingPeriodEnd}</b></span>
<span>&nbsp;<abbr title="Proving period end">EPS:</abbr> <b>{this.state.actorState.State.ElectionPeriodStart}</b></span>
</div>
<div>{this.state.statusCounts.map((c, i) => <span key={i}>{sealCodes[i]}: {c} | </span>)}</div>
<div>

View File

@ -237,10 +237,29 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
}, nil
}
func (m *Miner) isSlashed(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) {
power, err := m.api.StateMinerPower(ctx, addr, ts)
if err != nil {
return false, err
}
return power.MinerPower.Equals(types.NewInt(0)), nil
}
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids()))
start := time.Now()
slashed, err := m.isSlashed(ctx, addr, base.ts)
if err != nil {
return nil, xerrors.Errorf("checking if miner is slashed: %w", err)
}
if slashed {
log.Warnf("Slashed at epoch %d, not attempting to mine a block", base.ts.Height()+base.nullRounds)
base.nullRounds++
return nil, nil
}
ticket, err := m.computeTicket(ctx, addr, base)
if err != nil {
return nil, xerrors.Errorf("scratching ticket failed: %w", err)