commit
ff94e7680d
@ -1 +1 @@
|
|||||||
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWLM9S94b9mnHD2fbWvQzXudoapHjbBbFA1T4QVft65Kym
|
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWFCkQdiJEMBVA6RrWq22ZXVFfM41YX8soQ5QVvNFjMJT8
|
||||||
|
@ -1 +1 @@
|
|||||||
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWB4pVpuRAcW2873V6m3uPWevKcZ1VWr1FGPUTwDZUN5mg
|
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWSw9h3e6YrYZfRWDcir8qMV7ctZG9VmtXwSaP2ntsKXYf
|
||||||
|
Binary file not shown.
@ -37,13 +37,13 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
|
|||||||
// Consensus / Network
|
// Consensus / Network
|
||||||
|
|
||||||
// Seconds
|
// Seconds
|
||||||
const BlockDelay = 10
|
const BlockDelay = 12
|
||||||
|
|
||||||
// Seconds
|
// Seconds
|
||||||
const AllowableClockDrift = BlockDelay * 2
|
const AllowableClockDrift = BlockDelay * 2
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
const ForkLengthThreshold = 100
|
const ForkLengthThreshold = Finality
|
||||||
|
|
||||||
// Blocks (e)
|
// Blocks (e)
|
||||||
const BlocksPerEpoch = 5
|
const BlocksPerEpoch = 5
|
||||||
@ -60,7 +60,7 @@ const WRatioDen = 2
|
|||||||
// Proofs
|
// Proofs
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
const ProvingPeriodDuration = 160
|
const ProvingPeriodDuration uint64 = 300
|
||||||
|
|
||||||
// PoStChallangeTime sets the window in which post computation should happen
|
// PoStChallangeTime sets the window in which post computation should happen
|
||||||
// Blocks
|
// Blocks
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -62,14 +63,11 @@ type StorageMinerActorState struct {
|
|||||||
// Amount of power this miner has.
|
// Amount of power this miner has.
|
||||||
Power types.BigInt
|
Power types.BigInt
|
||||||
|
|
||||||
// List of sectors that this miner was slashed for.
|
// Active is set to true after the miner has submitted their first PoSt
|
||||||
//SlashedSet SectorSet
|
Active bool
|
||||||
|
|
||||||
// The height at which this miner was slashed at.
|
// The height at which this miner was slashed at.
|
||||||
SlashedAt types.BigInt
|
SlashedAt uint64
|
||||||
|
|
||||||
// The amount of storage collateral that is owed to clients, and cannot be used for collateral anymore.
|
|
||||||
OwedStorageCollateral types.BigInt
|
|
||||||
|
|
||||||
ProvingPeriodEnd uint64
|
ProvingPeriodEnd uint64
|
||||||
}
|
}
|
||||||
@ -132,7 +130,7 @@ type maMethods struct {
|
|||||||
UpdatePeerID uint64
|
UpdatePeerID uint64
|
||||||
ChangeWorker uint64
|
ChangeWorker uint64
|
||||||
IsSlashed uint64
|
IsSlashed uint64
|
||||||
IsLate uint64
|
CheckMiner uint64
|
||||||
DeclareFaults uint64
|
DeclareFaults uint64
|
||||||
SlashConsensusFault uint64
|
SlashConsensusFault uint64
|
||||||
}
|
}
|
||||||
@ -156,8 +154,8 @@ 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.IsSlashed,
|
16: sma.IsSlashed,
|
||||||
//17: sma.IsLate,
|
17: sma.CheckMiner,
|
||||||
18: sma.DeclareFaults,
|
18: sma.DeclareFaults,
|
||||||
19: sma.SlashConsensusFault,
|
19: sma.SlashConsensusFault,
|
||||||
}
|
}
|
||||||
@ -529,7 +527,23 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
|
|||||||
self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))),
|
self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))),
|
||||||
types.NewInt(mi.SectorSize))
|
types.NewInt(mi.SectorSize))
|
||||||
|
|
||||||
enc, err := SerializeParams(&UpdateStorageParams{Delta: types.BigSub(self.Power, oldPower)})
|
delta := types.BigSub(self.Power, oldPower)
|
||||||
|
if self.SlashedAt != 0 {
|
||||||
|
self.SlashedAt = 0
|
||||||
|
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: prevPE,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -734,9 +748,68 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte
|
|||||||
return types.NewInt(mi.SectorSize).Bytes(), nil
|
return types.NewInt(mi.SectorSize).Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaymentVerifyParams struct {
|
func isLate(height uint64, self *StorageMinerActorState) bool {
|
||||||
Extra []byte
|
return self.ProvingPeriodEnd > 0 && height >= self.ProvingPeriodEnd // TODO: review: maybe > ?
|
||||||
Proof []byte
|
}
|
||||||
|
|
||||||
|
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(self.SlashedAt != 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CheckMinerParams struct {
|
||||||
|
NetworkPower types.BigInt
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: better name
|
||||||
|
func (sma StorageMinerActor) CheckMiner(act *types.Actor, vmctx types.VMContext, params *CheckMinerParams) ([]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 !isLate(vmctx.BlockHeight(), self) {
|
||||||
|
// Everything's fine
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.SlashedAt != 0 {
|
||||||
|
// Don't slash more than necessary
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.NetworkPower.Equals(self.Power) {
|
||||||
|
// Don't break the network when there's only one miner left
|
||||||
|
|
||||||
|
log.Warnf("can't slash miner %s for missed PoSt, no power would be left in the network", vmctx.Message().To)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
|
if err := self.Power.MarshalCBOR(&out); err != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(err, "marshaling return value")
|
||||||
|
}
|
||||||
|
return out.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeclareFaultsParams struct {
|
type DeclareFaultsParams struct {
|
||||||
|
@ -97,6 +97,11 @@ func hash(b []byte) []byte {
|
|||||||
panic("blake 2b hash pls")
|
panic("blake 2b hash pls")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PaymentVerifyParams struct {
|
||||||
|
Extra []byte
|
||||||
|
Proof []byte
|
||||||
|
}
|
||||||
|
|
||||||
func (pca PaymentChannelActor) UpdateChannelState(act *types.Actor, vmctx types.VMContext, params *PCAUpdateChannelStateParams) ([]byte, ActorError) {
|
func (pca PaymentChannelActor) UpdateChannelState(act *types.Actor, vmctx types.VMContext, params *PCAUpdateChannelStateParams) ([]byte, ActorError) {
|
||||||
var self PaymentChannelActorState
|
var self PaymentChannelActorState
|
||||||
oldstate := vmctx.Storage().GetHead()
|
oldstate := vmctx.Storage().GetHead()
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"go.opencensus.io/trace"
|
||||||
|
xerrors "golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||||
"github.com/filecoin-project/lotus/chain/address"
|
"github.com/filecoin-project/lotus/chain/address"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
|
||||||
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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StoragePowerActor struct{}
|
type StoragePowerActor struct{}
|
||||||
@ -24,11 +28,12 @@ type spaMethods struct {
|
|||||||
UpdateStorage uint64
|
UpdateStorage uint64
|
||||||
GetTotalStorage uint64
|
GetTotalStorage uint64
|
||||||
PowerLookup uint64
|
PowerLookup uint64
|
||||||
IsMiner uint64
|
IsValidMiner uint64
|
||||||
PledgeCollateralForSize 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{} {
|
func (spa StoragePowerActor) Exports() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
@ -38,14 +43,17 @@ func (spa StoragePowerActor) Exports() []interface{} {
|
|||||||
4: spa.UpdateStorage,
|
4: spa.UpdateStorage,
|
||||||
5: spa.GetTotalStorage,
|
5: spa.GetTotalStorage,
|
||||||
6: spa.PowerLookup,
|
6: spa.PowerLookup,
|
||||||
7: spa.IsMiner,
|
7: spa.IsValidMiner,
|
||||||
8: spa.PledgeCollateralForSize,
|
8: spa.PledgeCollateralForSize,
|
||||||
|
9: spa.CheckProofSubmissions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type StoragePowerState struct {
|
type StoragePowerState struct {
|
||||||
Miners cid.Cid
|
Miners cid.Cid
|
||||||
MinerCount uint64
|
ProvingBuckets cid.Cid // amt[ProvingPeriodBucket]hamt[minerAddress]struct{}
|
||||||
|
MinerCount uint64
|
||||||
|
LastMinerCheck uint64
|
||||||
|
|
||||||
TotalStorage types.BigInt
|
TotalStorage types.BigInt
|
||||||
}
|
}
|
||||||
@ -259,7 +267,9 @@ func shouldSlash(block1, block2 *types.BlockHeader) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UpdateStorageParams struct {
|
type UpdateStorageParams struct {
|
||||||
Delta types.BigInt
|
Delta types.BigInt
|
||||||
|
NextProvingPeriodEnd uint64
|
||||||
|
PreviousProvingPeriodEnd uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
|
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
|
||||||
@ -273,13 +283,50 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has {
|
if !has {
|
||||||
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
|
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
|
||||||
}
|
}
|
||||||
|
|
||||||
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
|
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
|
||||||
|
|
||||||
|
previousBucket := params.PreviousProvingPeriodEnd % build.ProvingPeriodDuration
|
||||||
|
nextBucket := params.NextProvingPeriodEnd % build.ProvingPeriodDuration
|
||||||
|
|
||||||
|
if previousBucket == nextBucket && params.PreviousProvingPeriodEnd != 0 {
|
||||||
|
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 // Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
buckets, eerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingBuckets)
|
||||||
|
if eerr != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(eerr, "loading proving buckets amt")
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.PreviousProvingPeriodEnd != 0 { // delete from previous bucket
|
||||||
|
err := deleteMinerFromBucket(vmctx, buckets, previousBucket)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = addMinerToBucket(vmctx, buckets, nextBucket)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ProvingBuckets, eerr = buckets.Flush()
|
||||||
|
if eerr != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(eerr, "flushing proving buckets")
|
||||||
|
}
|
||||||
|
|
||||||
nroot, err := vmctx.Storage().Put(&self)
|
nroot, err := vmctx.Storage().Put(&self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -292,6 +339,82 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteMinerFromBucket(vmctx types.VMContext, buckets *amt.Root, previousBucket uint64) aerrors.ActorError {
|
||||||
|
var bucket cid.Cid
|
||||||
|
err := buckets.Get(previousBucket, &bucket)
|
||||||
|
switch err.(type) {
|
||||||
|
case *amt.ErrNotFound:
|
||||||
|
return aerrors.HandleExternalError(err, "proving bucket missing")
|
||||||
|
case nil: // noop
|
||||||
|
default:
|
||||||
|
return aerrors.HandleExternalError(err, "getting proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "failed to load proving bucket")
|
||||||
|
}
|
||||||
|
err = bhamt.Delete(vmctx.Context(), string(vmctx.Message().From.Bytes()))
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "deleting miner from proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bhamt.Flush(vmctx.Context())
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "flushing previous proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket, err = vmctx.Ipld().Put(vmctx.Context(), bhamt)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "putting previous proving bucket hamt")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = buckets.Set(previousBucket, bucket)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "setting previous proving bucket cid in amt")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addMinerToBucket(vmctx types.VMContext, buckets *amt.Root, nextBucket uint64) aerrors.ActorError {
|
||||||
|
var bhamt *hamt.Node
|
||||||
|
var bucket cid.Cid
|
||||||
|
err := buckets.Get(nextBucket, &bucket)
|
||||||
|
switch err.(type) {
|
||||||
|
case *amt.ErrNotFound:
|
||||||
|
bhamt = hamt.NewNode(vmctx.Ipld())
|
||||||
|
case nil:
|
||||||
|
bhamt, err = hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "failed to load proving bucket")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return aerrors.HandleExternalError(err, "getting proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), cborNull)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "setting miner in proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bhamt.Flush(vmctx.Context())
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "flushing previous proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket, err = vmctx.Ipld().Put(vmctx.Context(), bhamt)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "putting previous proving bucket hamt")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = buckets.Set(nextBucket, bucket)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "setting previous proving bucket cid in amt")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]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 {
|
||||||
@ -338,11 +461,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) IsMiner(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
|
||||||
@ -353,7 +476,24 @@ func (spa StoragePowerActor) IsMiner(act *types.Actor, vmctx types.VMContext, pa
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cbg.EncodeBool(has), nil
|
if !has {
|
||||||
|
log.Warnf("Miner INVALID: not in set: %s", param.Addr)
|
||||||
|
|
||||||
|
return cbg.CborBoolFalse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := vmctx.Send(param.Addr, MAMethods.IsSlashed, types.NewInt(0), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
slashed := bytes.Equal(ret, cbg.CborBoolTrue)
|
||||||
|
|
||||||
|
if slashed {
|
||||||
|
log.Warnf("Miner INVALID: /SLASHED/ : %s", param.Addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cbg.EncodeBool(!slashed), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PledgeCollateralParams struct {
|
type PledgeCollateralParams struct {
|
||||||
@ -426,6 +566,108 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big
|
|||||||
return types.BigAdd(powerCollateral, perCapCollateral), nil
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
var self StoragePowerState
|
||||||
|
old := vmctx.Storage().GetHead()
|
||||||
|
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := self.LastMinerCheck; i < vmctx.BlockHeight(); i++ {
|
||||||
|
height := i + 1
|
||||||
|
|
||||||
|
err := checkProofSubmissionsAtH(vmctx, &self, height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.LastMinerCheck = vmctx.BlockHeight()
|
||||||
|
|
||||||
|
nroot, aerr := vmctx.Storage().Put(&self)
|
||||||
|
if aerr != nil {
|
||||||
|
return nil, aerr
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, height uint64) aerrors.ActorError {
|
||||||
|
bucketID := height % build.ProvingPeriodDuration
|
||||||
|
|
||||||
|
buckets, eerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingBuckets)
|
||||||
|
if eerr != nil {
|
||||||
|
return aerrors.HandleExternalError(eerr, "loading proving buckets amt")
|
||||||
|
}
|
||||||
|
|
||||||
|
var bucket cid.Cid
|
||||||
|
err := buckets.Get(bucketID, &bucket)
|
||||||
|
switch err.(type) {
|
||||||
|
case *amt.ErrNotFound:
|
||||||
|
return nil // nothing to do
|
||||||
|
case nil:
|
||||||
|
default:
|
||||||
|
return aerrors.HandleExternalError(err, "getting proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "failed to load proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error {
|
||||||
|
_, span := trace.StartSpan(vmctx.Context(), "StoragePowerActor.CheckProofSubmissions.loop")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
maddr, err := address.NewFromBytes([]byte(k))
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.Escalate(err, "parsing miner address")
|
||||||
|
}
|
||||||
|
|
||||||
|
span.AddAttributes(trace.StringAttribute("miner", maddr.String()))
|
||||||
|
|
||||||
|
params, err := SerializeParams(&CheckMinerParams{NetworkPower: self.TotalStorage})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := vmctx.Send(maddr, MAMethods.CheckMiner, types.NewInt(0), params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
return nil // miner is fine
|
||||||
|
}
|
||||||
|
|
||||||
|
var power types.BigInt
|
||||||
|
if err := power.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
|
||||||
|
return xerrors.Errorf("unmarshaling CheckMiner response (%x): %w", ret, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if power.GreaterThan(types.NewInt(0)) {
|
||||||
|
log.Warnf("slashing miner %s for missed PoSt (%s B, H: %d, Bucket: %d)", maddr, power, height, bucketID)
|
||||||
|
|
||||||
|
self.TotalStorage = types.BigSub(self.TotalStorage, power)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return aerrors.HandleExternalError(err, "iterating miners in proving bucket")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
|
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
|
||||||
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
|
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -523,3 +765,33 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
|
|||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cbgNull struct{}
|
||||||
|
|
||||||
|
var cborNull = &cbgNull{}
|
||||||
|
|
||||||
|
func (cbgNull) MarshalCBOR(w io.Writer) error {
|
||||||
|
n, err := w.Write(cbg.CborNull)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if n != 1 {
|
||||||
|
return xerrors.New("expected to write 1 byte")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cbgNull) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
b := [1]byte{}
|
||||||
|
n, err := r.Read(b[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if n != 1 {
|
||||||
|
return xerrors.New("expected 1 byte")
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b[:], cbg.CborNull) {
|
||||||
|
return xerrors.New("expected cbor null")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -52,8 +52,8 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsMiner,
|
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
|
||||||
@ -63,7 +63,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !output {
|
if !output {
|
||||||
t.Fatalf("%s is miner but IsMiner call returned false", minerAddr)
|
t.Fatalf("%s is miner but IsValidMiner call returned false", minerAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsMiner, &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)
|
||||||
}
|
}
|
||||||
|
@ -268,13 +268,13 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.SlashedAt (types.BigInt) (struct)
|
// t.t.Active (bool) (bool)
|
||||||
if err := t.SlashedAt.MarshalCBOR(w); err != nil {
|
if err := cbg.WriteBool(w, t.Active); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.OwedStorageCollateral (types.BigInt) (struct)
|
// t.t.SlashedAt (uint64) (uint64)
|
||||||
if err := t.OwedStorageCollateral.MarshalCBOR(w); err != nil {
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SlashedAt))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,24 +425,33 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.t.SlashedAt (types.BigInt) (struct)
|
// t.t.Active (bool) (bool)
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.SlashedAt.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
// t.t.OwedStorageCollateral (types.BigInt) (struct)
|
if maj != cbg.MajOther {
|
||||||
|
return fmt.Errorf("booleans must be major type 7")
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.OwedStorageCollateral.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.SlashedAt = uint64(extra)
|
||||||
// t.t.ProvingPeriodEnd (uint64) (uint64)
|
// t.t.ProvingPeriodEnd (uint64) (uint64)
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
@ -2408,7 +2417,7 @@ func (t *StoragePowerState) MarshalCBOR(w io.Writer) error {
|
|||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write([]byte{131}); err != nil {
|
if _, err := w.Write([]byte{133}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2418,11 +2427,22 @@ func (t *StoragePowerState) MarshalCBOR(w io.Writer) error {
|
|||||||
return xerrors.Errorf("failed to write cid field t.Miners: %w", err)
|
return xerrors.Errorf("failed to write cid field t.Miners: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// t.t.ProvingBuckets (cid.Cid) (struct)
|
||||||
|
|
||||||
|
if err := cbg.WriteCid(w, t.ProvingBuckets); err != nil {
|
||||||
|
return xerrors.Errorf("failed to write cid field t.ProvingBuckets: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// t.t.MinerCount (uint64) (uint64)
|
// t.t.MinerCount (uint64) (uint64)
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.MinerCount))); err != nil {
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.MinerCount))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// t.t.LastMinerCheck (uint64) (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.LastMinerCheck))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// t.t.TotalStorage (types.BigInt) (struct)
|
// t.t.TotalStorage (types.BigInt) (struct)
|
||||||
if err := t.TotalStorage.MarshalCBOR(w); err != nil {
|
if err := t.TotalStorage.MarshalCBOR(w); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -2441,7 +2461,7 @@ func (t *StoragePowerState) 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 != 3 {
|
if extra != 5 {
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2456,6 +2476,18 @@ func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
|
|||||||
|
|
||||||
t.Miners = c
|
t.Miners = c
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.t.ProvingBuckets (cid.Cid) (struct)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(br)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to read cid field t.ProvingBuckets: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ProvingBuckets = c
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.t.MinerCount (uint64) (uint64)
|
// t.t.MinerCount (uint64) (uint64)
|
||||||
|
|
||||||
@ -2467,6 +2499,16 @@ func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return fmt.Errorf("wrong type for uint64 field")
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
}
|
}
|
||||||
t.MinerCount = uint64(extra)
|
t.MinerCount = uint64(extra)
|
||||||
|
// t.t.LastMinerCheck (uint64) (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.LastMinerCheck = uint64(extra)
|
||||||
// t.t.TotalStorage (types.BigInt) (struct)
|
// t.t.TotalStorage (types.BigInt) (struct)
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -2569,7 +2611,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
|
||||||
@ -2585,7 +2627,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)
|
||||||
@ -2660,7 +2702,7 @@ func (t *UpdateStorageParams) MarshalCBOR(w io.Writer) error {
|
|||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write([]byte{129}); err != nil {
|
if _, err := w.Write([]byte{131}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2668,6 +2710,16 @@ func (t *UpdateStorageParams) MarshalCBOR(w io.Writer) error {
|
|||||||
if err := t.Delta.MarshalCBOR(w); err != nil {
|
if err := t.Delta.MarshalCBOR(w); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// t.t.NextProvingPeriodEnd (uint64) (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.NextProvingPeriodEnd))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.PreviousProvingPeriodEnd (uint64) (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.PreviousProvingPeriodEnd))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2682,7 +2734,7 @@ func (t *UpdateStorageParams) 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 != 1 {
|
if extra != 3 {
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2695,6 +2747,26 @@ func (t *UpdateStorageParams) UnmarshalCBOR(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// t.t.NextProvingPeriodEnd (uint64) (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.NextProvingPeriodEnd = uint64(extra)
|
||||||
|
// t.t.PreviousProvingPeriodEnd (uint64) (uint64)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.PreviousProvingPeriodEnd = uint64(extra)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3861,3 +3933,46 @@ func (t *SectorProveCommitInfo) UnmarshalCBOR(r io.Reader) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *CheckMinerParams) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{129}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.NetworkPower (types.BigInt) (struct)
|
||||||
|
if err := t.NetworkPower.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CheckMinerParams) 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 != 1 {
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.NetworkPower (types.BigInt) (struct)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
if err := t.NetworkPower.UnmarshalCBOR(br); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
xerrors "golang.org/x/xerrors"
|
xerrors "golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
@ -861,7 +861,7 @@ func (t *StorageDataTransferVoucher) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.Proposal (cid.Cid)
|
// t.t.Proposal (cid.Cid) (struct)
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Proposal); err != nil {
|
if err := cbg.WriteCid(w, t.Proposal); err != nil {
|
||||||
return xerrors.Errorf("failed to write cid field t.Proposal: %w", err)
|
return xerrors.Errorf("failed to write cid field t.Proposal: %w", err)
|
||||||
@ -885,7 +885,7 @@ func (t *StorageDataTransferVoucher) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.Proposal (cid.Cid)
|
// t.t.Proposal (cid.Cid) (struct)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
bls "github.com/filecoin-project/go-bls-sigs"
|
bls "github.com/filecoin-project/go-bls-sigs"
|
||||||
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/pkg/errors"
|
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ import (
|
|||||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
|
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
|
||||||
st, recpts, err := sm.TipSetState(ctx, parents)
|
st, recpts, err := sm.TipSetState(ctx, parents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to load tipset state")
|
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
height := parents.Height() + uint64(len(tickets))
|
height := parents.Height() + uint64(len(tickets))
|
||||||
|
@ -152,9 +152,16 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blks := amt.WrapBlockstore(bs)
|
||||||
|
emptyamt, err := amt.FromArray(blks, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("amt build failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
sms := &actors.StoragePowerState{
|
sms := &actors.StoragePowerState{
|
||||||
Miners: emptyhamt,
|
Miners: emptyhamt,
|
||||||
TotalStorage: types.NewInt(0),
|
ProvingBuckets: emptyamt,
|
||||||
|
TotalStorage: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
stcid, err := cst.Put(context.TODO(), sms)
|
stcid, err := cst.Put(context.TODO(), sms)
|
||||||
|
@ -197,6 +197,30 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this nonce-getting is a ting bit ugly
|
||||||
|
spa, err := vmi.StateTree().GetActor(actors.StoragePowerAddress)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: cron actor
|
||||||
|
ret, err := vmi.ApplyMessage(ctx, &types.Message{
|
||||||
|
To: actors.StoragePowerAddress,
|
||||||
|
From: actors.StoragePowerAddress,
|
||||||
|
Nonce: spa.Nonce,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
GasPrice: types.NewInt(0),
|
||||||
|
GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little
|
||||||
|
Method: actors.SPAMethods.CheckProofSubmissions,
|
||||||
|
Params: nil,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, err
|
||||||
|
}
|
||||||
|
if ret.ExitCode != 0 {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("CheckProofSubmissions exit was non-zero: %d", ret.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
bs := amt.WrapBlockstore(sm.cs.Blockstore())
|
bs := amt.WrapBlockstore(sm.cs.Blockstore())
|
||||||
rectroot, err := amt.FromArray(bs, receipts)
|
rectroot, err := amt.FromArray(bs, receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
@ -426,7 +427,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
|
|||||||
ret, err := syncer.sm.Call(ctx, &types.Message{
|
ret, err := syncer.sm.Call(ctx, &types.Message{
|
||||||
To: actors.StoragePowerAddress,
|
To: actors.StoragePowerAddress,
|
||||||
From: maddr,
|
From: maddr,
|
||||||
Method: actors.SPAMethods.IsMiner,
|
Method: actors.SPAMethods.IsValidMiner,
|
||||||
Params: enc,
|
Params: enc,
|
||||||
}, baseTs)
|
}, baseTs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -434,10 +435,12 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ret.ExitCode != 0 {
|
if ret.ExitCode != 0 {
|
||||||
return xerrors.Errorf("StorageMarket.IsMiner 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
|
||||||
}
|
}
|
||||||
|
@ -92,11 +92,16 @@ func (bi BigInt) LessThan(o BigInt) bool {
|
|||||||
return BigCmp(bi, o) < 0
|
return BigCmp(bi, o) < 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// LessThan returns true if bi > o
|
// GreaterThan returns true if bi > o
|
||||||
func (bi BigInt) GreaterThan(o BigInt) bool {
|
func (bi BigInt) GreaterThan(o BigInt) bool {
|
||||||
return BigCmp(bi, o) > 0
|
return BigCmp(bi, o) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equals returns true if bi == o
|
||||||
|
func (bi BigInt) Equals(o BigInt) bool {
|
||||||
|
return BigCmp(bi, o) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (bi *BigInt) MarshalJSON() ([]byte, error) {
|
func (bi *BigInt) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(bi.String())
|
return json.Marshal(bi.String())
|
||||||
}
|
}
|
||||||
@ -186,7 +191,7 @@ func (bi *BigInt) UnmarshalCBOR(br io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if maj != cbg.MajByteString {
|
if maj != cbg.MajByteString {
|
||||||
return fmt.Errorf("cbor input for fil big int was not a byte string")
|
return fmt.Errorf("cbor input for fil big int was not a byte string (%x)", maj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if extra == 0 {
|
if extra == 0 {
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
xerrors "golang.org/x/xerrors"
|
xerrors "golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
@ -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{},
|
||||||
@ -128,6 +128,7 @@ func main() {
|
|||||||
actors.OnChainDeal{},
|
actors.OnChainDeal{},
|
||||||
actors.ComputeDataCommitmentParams{},
|
actors.ComputeDataCommitmentParams{},
|
||||||
actors.SectorProveCommitInfo{},
|
actors.SectorProveCommitInfo{},
|
||||||
|
actors.CheckMinerParams{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -74,18 +74,26 @@ class PowerState extends React.Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = {actors: []}
|
this.state = {actors: [], state: {State: {}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
|
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
|
||||||
const actors = await this.props.client.call("Filecoin.StateListMiners", [tipset])
|
const actors = await this.props.client.call("Filecoin.StateListMiners", [tipset])
|
||||||
this.setState({actors: actors})
|
const state = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset])
|
||||||
|
|
||||||
|
this.setState({actors, state})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.state.actors.sort((a, b) => (Number(a.substr(1)) > Number(b.substr(1))))
|
return <div>
|
||||||
.map(addr => <div key={addr}><Address miner={true} addr={addr} client={this.props.client} mountWindow={this.props.mountWindow}/></div>)
|
<div>
|
||||||
|
<div>Total Power: <b>{this.state.state.State.TotalStorage}</b></div>
|
||||||
|
</div>
|
||||||
|
<div>---</div>
|
||||||
|
<div>{this.state.actors.sort((a, b) => (Number(a.substr(1)) > Number(b.substr(1))))
|
||||||
|
.map(addr => <div key={addr}><Address miner={true} addr={addr} client={this.props.client} mountWindow={this.props.mountWindow}/></div>)}</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +182,7 @@ class MinerState extends React.Component {
|
|||||||
<div>Sector Size: <b>{this.state.sectorSize/1024}</b> KiB</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>Power: <b>{state.Power}</b> (<b>{state.Power/this.state.networkPower*100}</b>%)</div>
|
||||||
<div>Proving Period End: <b>{state.ProvingPeriodEnd}</b></div>
|
<div>Proving Period End: <b>{state.ProvingPeriodEnd}</b></div>
|
||||||
|
<div>Slashed: <b>{state.SlashedAt === 0 ? "NO" : state.SlashedAt}</b></div>
|
||||||
<div>
|
<div>
|
||||||
<div>----</div>
|
<div>----</div>
|
||||||
<div>Sectors:</div>
|
<div>Sectors:</div>
|
||||||
|
@ -89,7 +89,7 @@ func (pmgr *PeerMgr) Run(ctx context.Context) {
|
|||||||
if pcount < pmgr.minFilPeers {
|
if pcount < pmgr.minFilPeers {
|
||||||
pmgr.expandPeers()
|
pmgr.expandPeers()
|
||||||
} else if pcount > pmgr.maxFilPeers {
|
} else if pcount > pmgr.maxFilPeers {
|
||||||
log.Infof("peer count about threshold: %d > %d", pcount, pmgr.maxFilPeers)
|
log.Debug("peer count about threshold: %d > %d", pcount, pmgr.maxFilPeers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,8 @@ scp scripts/bootstrap.toml "${GENESIS_HOST}:.lotus/config.toml" &
|
|||||||
ssh < "${GENPATH}/wallet.key" $GENESIS_HOST '/usr/local/bin/lotus wallet import' &
|
ssh < "${GENPATH}/wallet.key" $GENESIS_HOST '/usr/local/bin/lotus wallet import' &
|
||||||
wait
|
wait
|
||||||
|
|
||||||
|
ssh $GENESIS_HOST "echo -e '[Metrics]\nNickname=\"Boot-genesis\"' >> .lotus/config.toml"
|
||||||
|
|
||||||
ssh $GENESIS_HOST 'systemctl restart lotus-daemon'
|
ssh $GENESIS_HOST 'systemctl restart lotus-daemon'
|
||||||
|
|
||||||
log 'Starting genesis mining'
|
log 'Starting genesis mining'
|
||||||
@ -109,9 +111,24 @@ do
|
|||||||
|
|
||||||
ssh "$host" 'systemctl start lotus-daemon'
|
ssh "$host" 'systemctl start lotus-daemon'
|
||||||
scp scripts/bootstrap.toml "${host}:.lotus/config.toml"
|
scp scripts/bootstrap.toml "${host}:.lotus/config.toml"
|
||||||
|
ssh "$host" "echo -e '[Metrics]\nNickname=\"Boot-$host\"' >> .lotus/config.toml"
|
||||||
ssh "$host" 'systemctl restart lotus-daemon'
|
ssh "$host" 'systemctl restart lotus-daemon'
|
||||||
|
|
||||||
log 'Extracting addr info'
|
log 'Extracting addr info'
|
||||||
|
|
||||||
ssh "$host" 'lotus net listen' | grep -v '/10' | grep -v '/127' >> build/bootstrap/bootstrappers.pi
|
ssh "$host" 'lotus net listen' | grep -v '/10' | grep -v '/127' >> build/bootstrap/bootstrappers.pi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
log 'Updating genesis node with bootstrapable binaries'
|
||||||
|
|
||||||
|
ssh "$GENESIS_HOST" 'systemctl stop lotus-daemon' &
|
||||||
|
ssh "$GENESIS_HOST" 'systemctl stop lotus-storage-miner' &
|
||||||
|
wait
|
||||||
|
|
||||||
|
scp -C lotus "${GENESIS_HOST}":/usr/local/bin/lotus &
|
||||||
|
scp -C lotus-storage-miner "${GENESIS_HOST}":/usr/local/bin/lotus-storage-miner &
|
||||||
|
wait
|
||||||
|
|
||||||
|
ssh "$GENESIS_HOST" 'systemctl start lotus-daemon' &
|
||||||
|
ssh "$GENESIS_HOST" 'systemctl start lotus-storage-miner' &
|
||||||
|
wait
|
||||||
|
Loading…
Reference in New Issue
Block a user