Merge pull request #612 from filecoin-project/devnet/8

Devnet/8
This commit is contained in:
Łukasz Magiera 2019-11-15 01:51:34 +01:00 committed by GitHub
commit ff94e7680d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 613 additions and 83 deletions

View File

@ -1 +1 @@
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWLM9S94b9mnHD2fbWvQzXudoapHjbBbFA1T4QVft65Kym
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWFCkQdiJEMBVA6RrWq22ZXVFfM41YX8soQ5QVvNFjMJT8

View File

@ -1 +1 @@
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWB4pVpuRAcW2873V6m3uPWevKcZ1VWr1FGPUTwDZUN5mg
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWSw9h3e6YrYZfRWDcir8qMV7ctZG9VmtXwSaP2ntsKXYf

Binary file not shown.

View File

@ -37,13 +37,13 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
// Consensus / Network
// Seconds
const BlockDelay = 10
const BlockDelay = 12
// Seconds
const AllowableClockDrift = BlockDelay * 2
// Blocks
const ForkLengthThreshold = 100
const ForkLengthThreshold = Finality
// Blocks (e)
const BlocksPerEpoch = 5
@ -60,7 +60,7 @@ const WRatioDen = 2
// Proofs
// Blocks
const ProvingPeriodDuration = 160
const ProvingPeriodDuration uint64 = 300
// PoStChallangeTime sets the window in which post computation should happen
// Blocks

View File

@ -1,6 +1,7 @@
package actors
import (
"bytes"
"context"
"encoding/binary"
"fmt"
@ -62,14 +63,11 @@ type StorageMinerActorState struct {
// Amount of power this miner has.
Power types.BigInt
// List of sectors that this miner was slashed for.
//SlashedSet SectorSet
// 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 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
}
@ -132,7 +130,7 @@ type maMethods struct {
UpdatePeerID uint64
ChangeWorker uint64
IsSlashed uint64
IsLate uint64
CheckMiner uint64
DeclareFaults uint64
SlashConsensusFault uint64
}
@ -156,8 +154,8 @@ func (sma StorageMinerActor) Exports() []interface{} {
13: sma.GetSectorSize,
14: sma.UpdatePeerID,
//15: sma.ChangeWorker,
//16: sma.IsSlashed,
//17: sma.IsLate,
16: sma.IsSlashed,
17: sma.CheckMiner,
18: sma.DeclareFaults,
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))),
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 {
return nil, err
}
@ -734,9 +748,68 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte
return types.NewInt(mi.SectorSize).Bytes(), nil
}
type PaymentVerifyParams struct {
Extra []byte
Proof []byte
func isLate(height uint64, self *StorageMinerActorState) bool {
return self.ProvingPeriodEnd > 0 && height >= self.ProvingPeriodEnd // TODO: review: maybe > ?
}
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 {

View File

@ -97,6 +97,11 @@ func hash(b []byte) []byte {
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) {
var self PaymentChannelActorState
oldstate := vmctx.Storage().GetHead()

View File

@ -1,18 +1,22 @@
package actors
import (
"bytes"
"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/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"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{}
@ -24,11 +28,12 @@ type spaMethods struct {
UpdateStorage uint64
GetTotalStorage uint64
PowerLookup uint64
IsMiner uint64
IsValidMiner 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{}{
@ -38,14 +43,17 @@ func (spa StoragePowerActor) Exports() []interface{} {
4: spa.UpdateStorage,
5: spa.GetTotalStorage,
6: spa.PowerLookup,
7: spa.IsMiner,
7: spa.IsValidMiner,
8: spa.PledgeCollateralForSize,
9: spa.CheckProofSubmissions,
}
}
type StoragePowerState struct {
Miners cid.Cid
ProvingBuckets cid.Cid // amt[ProvingPeriodBucket]hamt[minerAddress]struct{}
MinerCount uint64
LastMinerCheck uint64
TotalStorage types.BigInt
}
@ -260,6 +268,8 @@ func shouldSlash(block1, block2 *types.BlockHeader) bool {
type UpdateStorageParams struct {
Delta types.BigInt
NextProvingPeriodEnd uint64
PreviousProvingPeriodEnd uint64
}
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 {
return nil, err
}
if !has {
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
}
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)
if err != nil {
return nil, err
@ -292,6 +339,82 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
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) {
var self StoragePowerState
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
}
type IsMinerParam struct {
type IsValidMinerParam struct {
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
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
@ -353,7 +476,24 @@ func (spa StoragePowerActor) IsMiner(act *types.Actor, vmctx types.VMContext, pa
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 {
@ -426,6 +566,108 @@ 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")
}
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) {
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
if err != nil {
@ -523,3 +765,33 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
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
}

View File

@ -52,8 +52,8 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
}
{
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsMiner,
&IsMinerParam{Addr: minerAddr})
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner,
&IsValidMinerParam{Addr: minerAddr})
ApplyOK(t, ret)
var output bool
@ -63,7 +63,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
}
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)
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
}

View File

@ -268,13 +268,13 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.SlashedAt (types.BigInt) (struct)
if err := t.SlashedAt.MarshalCBOR(w); err != nil {
// t.t.Active (bool) (bool)
if err := cbg.WriteBool(w, t.Active); err != nil {
return err
}
// t.t.OwedStorageCollateral (types.BigInt) (struct)
if err := t.OwedStorageCollateral.MarshalCBOR(w); err != nil {
// t.t.SlashedAt (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SlashedAt))); err != nil {
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 {
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajOther {
return fmt.Errorf("booleans must be major type 7")
}
// t.t.OwedStorageCollateral (types.BigInt) (struct)
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)
{
if err := t.OwedStorageCollateral.UnmarshalCBOR(br); err != nil {
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)
maj, extra, err = cbg.CborReadHeader(br)
@ -2408,7 +2417,7 @@ func (t *StoragePowerState) MarshalCBOR(w io.Writer) error {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{131}); err != nil {
if _, err := w.Write([]byte{133}); err != nil {
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)
}
// 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)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.MinerCount))); err != nil {
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)
if err := t.TotalStorage.MarshalCBOR(w); err != nil {
return err
@ -2441,7 +2461,7 @@ func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
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")
}
@ -2456,6 +2476,18 @@ func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
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)
@ -2467,6 +2499,16 @@ func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("wrong type for uint64 field")
}
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)
{
@ -2569,7 +2611,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
@ -2585,7 +2627,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)
@ -2660,7 +2702,7 @@ func (t *UpdateStorageParams) MarshalCBOR(w io.Writer) error {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{129}); err != nil {
if _, err := w.Write([]byte{131}); err != nil {
return err
}
@ -2668,6 +2710,16 @@ func (t *UpdateStorageParams) MarshalCBOR(w io.Writer) error {
if err := t.Delta.MarshalCBOR(w); err != nil {
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
}
@ -2682,7 +2734,7 @@ func (t *UpdateStorageParams) UnmarshalCBOR(r io.Reader) error {
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")
}
@ -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
}
@ -3861,3 +3933,46 @@ func (t *SectorProveCommitInfo) UnmarshalCBOR(r io.Reader) error {
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
}

View File

@ -5,7 +5,7 @@ import (
"io"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)

View File

@ -861,7 +861,7 @@ func (t *StorageDataTransferVoucher) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.Proposal (cid.Cid)
// t.t.Proposal (cid.Cid) (struct)
if err := cbg.WriteCid(w, t.Proposal); err != nil {
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")
}
// t.t.Proposal (cid.Cid)
// t.t.Proposal (cid.Cid) (struct)
{

View File

@ -7,7 +7,6 @@ import (
bls "github.com/filecoin-project/go-bls-sigs"
cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
"github.com/pkg/errors"
cbg "github.com/whyrusleeping/cbor-gen"
"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) {
st, recpts, err := sm.TipSetState(ctx, parents)
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))

View File

@ -152,8 +152,15 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
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{
Miners: emptyhamt,
ProvingBuckets: emptyamt,
TotalStorage: types.NewInt(0),
}

View File

@ -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())
rectroot, err := amt.FromArray(bs, receipts)
if err != nil {

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
}
@ -426,7 +427,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
ret, err := syncer.sm.Call(ctx, &types.Message{
To: actors.StoragePowerAddress,
From: maddr,
Method: actors.SPAMethods.IsMiner,
Method: actors.SPAMethods.IsValidMiner,
Params: enc,
}, baseTs)
if err != nil {
@ -434,10 +435,12 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
}
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
}

View File

@ -92,11 +92,16 @@ func (bi BigInt) LessThan(o BigInt) bool {
return BigCmp(bi, o) < 0
}
// LessThan returns true if bi > o
// GreaterThan returns true if bi > o
func (bi BigInt) GreaterThan(o BigInt) bool {
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) {
return json.Marshal(bi.String())
}
@ -186,7 +191,7 @@ func (bi *BigInt) UnmarshalCBOR(br io.Reader) error {
}
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 {

View File

@ -5,7 +5,7 @@ import (
"io"
"math"
"github.com/ipfs/go-cid"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)

View File

@ -110,7 +110,7 @@ func main() {
actors.PaymentInfo{},
actors.StoragePowerState{},
actors.CreateStorageMinerParams{},
actors.IsMinerParam{},
actors.IsValidMinerParam{},
actors.PowerLookupParams{},
actors.UpdateStorageParams{},
actors.ArbitrateConsensusFaultParams{},
@ -128,6 +128,7 @@ func main() {
actors.OnChainDeal{},
actors.ComputeDataCommitmentParams{},
actors.SectorProveCommitInfo{},
actors.CheckMinerParams{},
)
if err != nil {
fmt.Println(err)

View File

@ -74,18 +74,26 @@ class PowerState extends React.Component {
constructor(props) {
super(props)
this.state = {actors: []}
this.state = {actors: [], state: {State: {}}}
}
async componentDidMount() {
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
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() {
return 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>)
return <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>Power: <b>{state.Power}</b> (<b>{state.Power/this.state.networkPower*100}</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>Sectors:</div>

View File

@ -89,7 +89,7 @@ func (pmgr *PeerMgr) Run(ctx context.Context) {
if pcount < pmgr.minFilPeers {
pmgr.expandPeers()
} 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)
}
}
}

View File

@ -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' &
wait
ssh $GENESIS_HOST "echo -e '[Metrics]\nNickname=\"Boot-genesis\"' >> .lotus/config.toml"
ssh $GENESIS_HOST 'systemctl restart lotus-daemon'
log 'Starting genesis mining'
@ -109,9 +111,24 @@ do
ssh "$host" 'systemctl start lotus-daemon'
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'
log 'Extracting addr info'
ssh "$host" 'lotus net listen' | grep -v '/10' | grep -v '/127' >> build/bootstrap/bootstrappers.pi
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