WIP: election post restructuring
This commit is contained in:
parent
d57f048c2c
commit
96482f456a
@ -52,7 +52,7 @@ type FullNode interface {
|
|||||||
MinerRegister(context.Context, address.Address) error
|
MinerRegister(context.Context, address.Address) error
|
||||||
MinerUnregister(context.Context, address.Address) error
|
MinerUnregister(context.Context, address.Address) error
|
||||||
MinerAddresses(context.Context) ([]address.Address, error)
|
MinerAddresses(context.Context) ([]address.Address, error)
|
||||||
MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
|
MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
|
||||||
|
|
||||||
// // UX ?
|
// // UX ?
|
||||||
|
|
||||||
|
@ -58,10 +58,10 @@ type FullNodeStruct struct {
|
|||||||
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
|
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
|
||||||
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
|
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
|
||||||
|
|
||||||
MinerRegister func(context.Context, address.Address) error `perm:"admin"`
|
MinerRegister func(context.Context, address.Address) error `perm:"admin"`
|
||||||
MinerUnregister func(context.Context, address.Address) error `perm:"admin"`
|
MinerUnregister func(context.Context, address.Address) error `perm:"admin"`
|
||||||
MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"`
|
MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||||
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
|
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||||
|
|
||||||
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
|
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
|
||||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||||
@ -237,7 +237,7 @@ func (c *FullNodeStruct) MinerAddresses(ctx context.Context) ([]address.Address,
|
|||||||
return c.Internal.MinerAddresses(ctx)
|
return c.Internal.MinerAddresses(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
||||||
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
|
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,9 +389,8 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SubmitPoStParams struct {
|
type SubmitPoStParams struct {
|
||||||
Proof []byte
|
Proof types.EPostProof
|
||||||
DoneSet types.BitField
|
DoneSet types.BitField
|
||||||
// TODO: once the spec changes finish, we have more work to do here...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) {
|
func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) {
|
||||||
@ -402,8 +401,6 @@ func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) {
|
|||||||
return end, period
|
return end, period
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is a dummy method that allows us to plumb in other parts of the
|
|
||||||
// system for now.
|
|
||||||
func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) {
|
func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) {
|
||||||
oldstate, self, err := loadState(vmctx)
|
oldstate, self, err := loadState(vmctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -491,10 +488,20 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
faults := self.CurrentFaultSet.All()
|
faults := self.CurrentFaultSet.All()
|
||||||
|
_ = faults
|
||||||
|
|
||||||
|
_ = seed
|
||||||
|
//VerifyPoStRandomness()
|
||||||
|
|
||||||
|
convertToCandidates := func(wins []types.EPostTicket) []sectorbuilder.EPostCandidate {
|
||||||
|
panic("NYI")
|
||||||
|
}
|
||||||
|
winners := convertToCandidates(params.Proof.Winners)
|
||||||
|
|
||||||
|
proverID := vmctx.Message().To // TODO: normalize to ID address
|
||||||
|
|
||||||
if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize,
|
if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize,
|
||||||
sectorbuilder.NewSortedSectorInfo(sectorInfos), seed, params.Proof,
|
sectorbuilder.NewSortedSectorInfo(sectorInfos), params.Proof.PostRand, params.Proof.Proof, winners, proverID); !ok || lerr != nil {
|
||||||
faults); !ok || lerr != nil {
|
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
// TODO: study PoST errors
|
// TODO: study PoST errors
|
||||||
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
||||||
|
@ -836,11 +836,8 @@ func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.Proof ([]uint8) (slice)
|
// t.t.Proof (types.EPostProof) (struct)
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
|
if err := t.Proof.MarshalCBOR(w); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write(t.Proof); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,22 +863,14 @@ func (t *SubmitPoStParams) 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.Proof ([]uint8) (slice)
|
// t.t.Proof (types.EPostProof) (struct)
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
{
|
||||||
if err != nil {
|
|
||||||
return err
|
if err := t.Proof.UnmarshalCBOR(br); err != nil {
|
||||||
}
|
return err
|
||||||
if extra > 8192 {
|
}
|
||||||
return fmt.Errorf("t.Proof: array too large (%d)", extra)
|
|
||||||
}
|
|
||||||
|
|
||||||
if maj != cbg.MajByteString {
|
|
||||||
return fmt.Errorf("expected byte array")
|
|
||||||
}
|
|
||||||
t.Proof = make([]byte, extra)
|
|
||||||
if _, err := io.ReadFull(br, t.Proof); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
// t.t.DoneSet (types.BitField) (struct)
|
// t.t.DoneSet (types.BitField) (struct)
|
||||||
|
|
||||||
|
159
chain/gen/gen.go
159
chain/gen/gen.go
@ -13,6 +13,7 @@ import (
|
|||||||
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
||||||
"github.com/ipfs/go-merkledag"
|
"github.com/ipfs/go-merkledag"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
|
"go.opencensus.io/trace"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
@ -22,6 +23,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
|
|
||||||
block "github.com/ipfs/go-block-format"
|
block "github.com/ipfs/go-block-format"
|
||||||
@ -52,6 +54,7 @@ type ChainGen struct {
|
|||||||
|
|
||||||
w *wallet.Wallet
|
w *wallet.Wallet
|
||||||
|
|
||||||
|
eppProvs map[address.Address]ElectionPoStProver
|
||||||
Miners []address.Address
|
Miners []address.Address
|
||||||
mworkers []address.Address
|
mworkers []address.Address
|
||||||
receivers []address.Address
|
receivers []address.Address
|
||||||
@ -155,6 +158,11 @@ func NewGenerator() (*ChainGen, error) {
|
|||||||
return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address")
|
return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mgen := make(map[address.Address]ElectionPoStProver)
|
||||||
|
for _, m := range minercfg.MinerAddrs {
|
||||||
|
mgen[m] = &eppProvider{}
|
||||||
|
}
|
||||||
|
|
||||||
sm := stmgr.NewStateManager(cs)
|
sm := stmgr.NewStateManager(cs)
|
||||||
|
|
||||||
gen := &ChainGen{
|
gen := &ChainGen{
|
||||||
@ -166,6 +174,7 @@ func NewGenerator() (*ChainGen, error) {
|
|||||||
w: w,
|
w: w,
|
||||||
|
|
||||||
Miners: minercfg.MinerAddrs,
|
Miners: minercfg.MinerAddrs,
|
||||||
|
eppProvs: mgen,
|
||||||
mworkers: minercfg.Workers,
|
mworkers: minercfg.Workers,
|
||||||
banker: banker,
|
banker: banker,
|
||||||
receivers: receievers,
|
receivers: receievers,
|
||||||
@ -191,13 +200,13 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) {
|
|||||||
out := new(bytes.Buffer)
|
out := new(bytes.Buffer)
|
||||||
|
|
||||||
if err := car.WriteCar(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out); err != nil {
|
if err := car.WriteCar(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out); err != nil {
|
||||||
return nil, err
|
return nil, xerrors.Errorf("genesis car write car failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.Bytes(), nil
|
return out.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (types.ElectionProof, *types.Ticket, error) {
|
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) {
|
||||||
|
|
||||||
lastTicket := pts.MinTicket()
|
lastTicket := pts.MinTicket()
|
||||||
|
|
||||||
@ -208,8 +217,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
|||||||
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
vrfBase := TicketHash(lastTicket, uint64(round))
|
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, m, DSepTicket, lastTicket.VRFProof)
|
||||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, vrfBase)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||||
}
|
}
|
||||||
@ -218,7 +226,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
|||||||
VRFProof: vrfout,
|
VRFProof: vrfout,
|
||||||
}
|
}
|
||||||
|
|
||||||
win, eproof, err := IsRoundWinner(ctx, pts, round, m, &mca{w: cg.w, sm: cg.sm})
|
win, eproof, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -282,7 +290,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||||
|
|
||||||
var ts uint64
|
var ts uint64
|
||||||
if cg.Timestamper != nil {
|
if cg.Timestamper != nil {
|
||||||
@ -356,6 +364,8 @@ type MiningCheckAPI interface {
|
|||||||
|
|
||||||
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)
|
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)
|
||||||
|
|
||||||
|
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error)
|
||||||
|
|
||||||
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
|
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,11 +394,38 @@ func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *
|
|||||||
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
|
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, ts *types.TipSet) (uint64, error) {
|
||||||
|
return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr)
|
||||||
|
}
|
||||||
|
|
||||||
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
|
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
|
||||||
return mca.w.Sign(ctx, a, v)
|
return mca.w.Sign(ctx, a, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) {
|
type ElectionPoStProver interface {
|
||||||
|
GenerateCandidates(context.Context, []byte) ([]sectorbuilder.EPostCandidate, error)
|
||||||
|
ComputeProof(context.Context, []byte, []sectorbuilder.EPostCandidate) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type eppProvider struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (epp *eppProvider) GenerateCandidates(ctx context.Context, eprand []byte) ([]sectorbuilder.EPostCandidate, error) {
|
||||||
|
return []sectorbuilder.EPostCandidate{
|
||||||
|
sectorbuilder.EPostCandidate{
|
||||||
|
SectorID: 1,
|
||||||
|
PartialTicket: [32]byte{},
|
||||||
|
Ticket: [32]byte{},
|
||||||
|
SectorChallengeIndex: 1,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (epp *eppProvider) ComputeProof(ctx context.Context, eprand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) {
|
||||||
|
return []byte("this is an election post proof"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (bool, *types.EPostProof, error) {
|
||||||
r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback)
|
r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, xerrors.Errorf("chain get randomness: %w", err)
|
return false, nil, xerrors.Errorf("chain get randomness: %w", err)
|
||||||
@ -399,23 +436,111 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
|
|||||||
return false, nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
return false, nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, r)
|
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, miner, DSepElectionPost, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
return false, nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
candidates, err := epp.GenerateCandidates(ctx, vrfout)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates")
|
||||||
|
}
|
||||||
|
|
||||||
pow, err := a.StateMinerPower(ctx, miner, ts)
|
pow, err := a.StateMinerPower(ctx, miner, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, xerrors.Errorf("failed to check power: %w", err)
|
return false, nil, xerrors.Errorf("failed to check power: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil
|
ssize, err := a.StateMinerSectorSize(ctx, miner, ts)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, xerrors.Errorf("failed to look up miners sector size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var winners []sectorbuilder.EPostCandidate
|
||||||
|
for _, c := range candidates {
|
||||||
|
if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower, 1) {
|
||||||
|
winners = append(winners, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no winners, sad
|
||||||
|
if len(winners) == 0 {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
proof, err := epp.ComputeProof(ctx, vrfout, winners)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, xerrors.Errorf("failed to compute snark for election proof: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ept := types.EPostProof{
|
||||||
|
Proof: proof,
|
||||||
|
PostRand: vrfout,
|
||||||
|
}
|
||||||
|
for _, win := range winners {
|
||||||
|
ept.Winners = append(ept.Winners, types.EPostTicket{
|
||||||
|
Partial: win.PartialTicket[:],
|
||||||
|
SectorID: win.SectorID,
|
||||||
|
ChallengeIndex: win.SectorChallengeIndex,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, &ept, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
|
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||||
|
|
||||||
func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []byte) ([]byte, error) {
|
const (
|
||||||
sig, err := sign(ctx, w, input)
|
DSepTicket = 1
|
||||||
|
DSepElectionPost = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
func hashVRFBase(personalization uint64, miner address.Address, input []byte) ([]byte, error) {
|
||||||
|
if miner.Protocol() != address.ID {
|
||||||
|
return nil, xerrors.Errorf("miner address for compute VRF must be an ID address")
|
||||||
|
}
|
||||||
|
|
||||||
|
var persbuf [8]byte
|
||||||
|
binary.LittleEndian.PutUint64(persbuf[:], personalization)
|
||||||
|
|
||||||
|
h := sha256.New()
|
||||||
|
h.Write(persbuf[:])
|
||||||
|
h.Write([]byte{0})
|
||||||
|
h.Write(input)
|
||||||
|
h.Write([]byte{0})
|
||||||
|
h.Write(miner.Bytes())
|
||||||
|
|
||||||
|
return h.Sum(nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, input, vrfproof []byte) error {
|
||||||
|
ctx, span := trace.StartSpan(ctx, "VerifyVRF")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
vrfBase, err := hashVRFBase(p, miner, input)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("computing vrf base failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sig := &types.Signature{
|
||||||
|
Type: types.KTBLS,
|
||||||
|
Data: vrfproof,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sig.Verify(worker, vrfBase); err != nil {
|
||||||
|
return xerrors.Errorf("vrf was invalid: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Address, p uint64, input []byte) ([]byte, error) {
|
||||||
|
sigInput, err := hashVRFBase(p, miner, input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := sign(ctx, worker, sigInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -427,11 +552,15 @@ func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []b
|
|||||||
return sig.Data, nil
|
return sig.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TicketHash(t *types.Ticket, round uint64) []byte {
|
func TicketHash(t *types.Ticket, addr address.Address) []byte {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
|
|
||||||
h.Write(t.VRFProof)
|
h.Write(t.VRFProof)
|
||||||
var roundbuf [8]byte
|
|
||||||
binary.LittleEndian.PutUint64(roundbuf[:], round)
|
// Field Delimeter
|
||||||
h.Write(roundbuf[:])
|
h.Write([]byte{0})
|
||||||
|
|
||||||
|
h.Write(addr.Bytes())
|
||||||
|
|
||||||
return h.Sum(nil)
|
return h.Sum(nil)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, timestamp uint64) (*types.FullBlock, error) {
|
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, 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, xerrors.Errorf("failed to load tipset state: %w", err)
|
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
||||||
@ -35,7 +35,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
|||||||
Ticket: ticket,
|
Ticket: ticket,
|
||||||
Height: height,
|
Height: height,
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
ElectionProof: proof,
|
EPostProof: *proof,
|
||||||
ParentStateRoot: st,
|
ParentStateRoot: st,
|
||||||
ParentMessageReceipts: recpts,
|
ParentMessageReceipts: recpts,
|
||||||
}
|
}
|
||||||
|
@ -383,9 +383,12 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
|
|||||||
}
|
}
|
||||||
|
|
||||||
b := &types.BlockHeader{
|
b := &types.BlockHeader{
|
||||||
Miner: actors.InitAddress,
|
Miner: actors.InitAddress,
|
||||||
Ticket: genesisticket,
|
Ticket: genesisticket,
|
||||||
ElectionProof: []byte("the Genesis block"),
|
EPostProof: types.EPostProof{
|
||||||
|
Proof: []byte("not a real proof"),
|
||||||
|
PostRand: []byte("i guess this is kinda random"),
|
||||||
|
},
|
||||||
Parents: []cid.Cid{},
|
Parents: []cid.Cid{},
|
||||||
Height: 0,
|
Height: 0,
|
||||||
ParentWeight: types.NewInt(0),
|
ParentWeight: types.NewInt(0),
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"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"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
||||||
|
|
||||||
amt "github.com/filecoin-project/go-amt-ipld"
|
amt "github.com/filecoin-project/go-amt-ipld"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
@ -177,6 +178,26 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet,
|
|||||||
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors)
|
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedSectorInfo, error) {
|
||||||
|
sectors, err := GetMinerSectorSet(ctx, sm, ts, maddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to get sector set for miner: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var uselessOtherArray []sectorbuilder.SectorInfo
|
||||||
|
for _, s := range sectors {
|
||||||
|
var uselessBuffer [32]byte
|
||||||
|
copy(uselessBuffer[:], s.CommR)
|
||||||
|
uselessOtherArray = append(uselessOtherArray, sectorbuilder.SectorInfo{
|
||||||
|
SectorID: s.SectorID,
|
||||||
|
CommR: uselessBuffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ssi := sectorbuilder.NewSortedSectorInfo(uselessOtherArray)
|
||||||
|
return &ssi, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
||||||
var mas actors.StorageMinerActorState
|
var mas actors.StorageMinerActorState
|
||||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||||
|
@ -770,7 +770,7 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
|||||||
return NewFullTipSet(out), nil
|
return NewFullTipSet(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ticketHash(t *types.Ticket, round int64) []byte {
|
func drawRandomness(t *types.Ticket, round int64) []byte {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
binary.LittleEndian.PutUint64(buf[:], uint64(round))
|
binary.LittleEndian.PutUint64(buf[:], uint64(round))
|
||||||
@ -795,7 +795,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
|
|||||||
mtb := nts.MinTicketBlock()
|
mtb := nts.MinTicketBlock()
|
||||||
|
|
||||||
if int64(nts.Height()) <= round {
|
if int64(nts.Height()) <= round {
|
||||||
return ticketHash(nts.MinTicketBlock().Ticket, round), nil
|
return drawRandomness(nts.MinTicketBlock().Ticket, round), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case for lookback behind genesis block
|
// special case for lookback behind genesis block
|
||||||
@ -803,7 +803,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
|
|||||||
if mtb.Height == 0 {
|
if mtb.Height == 0 {
|
||||||
|
|
||||||
// round is negative
|
// round is negative
|
||||||
thash := ticketHash(mtb.Ticket, round*-1)
|
thash := drawRandomness(mtb.Ticket, round*-1)
|
||||||
|
|
||||||
// for negative lookbacks, just use the hash of the positive tickethash value
|
// for negative lookbacks, just use the hash of the positive tickethash value
|
||||||
h := sha256.Sum256(thash)
|
h := sha256.Sum256(thash)
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.Logger("chain")
|
var log = logging.Logger("chain")
|
||||||
@ -467,23 +468,8 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (syncer *Syncer) validateTicket(ctx context.Context, mworker address.Address, ticket *types.Ticket, base *types.TipSet, round uint64) error {
|
func (syncer *Syncer) validateTicket(ctx context.Context, maddr, mworker address.Address, ticket *types.Ticket, base *types.TipSet) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "validateTickets")
|
return gen.VerifyVRF(ctx, mworker, maddr, gen.DSepTicket, base.MinTicket().VRFProof, ticket.VRFProof)
|
||||||
defer span.End()
|
|
||||||
|
|
||||||
sig := &types.Signature{
|
|
||||||
Type: types.KTBLS,
|
|
||||||
Data: ticket.VRFProof,
|
|
||||||
}
|
|
||||||
|
|
||||||
vrfBase := gen.TicketHash(base.MinTicket(), round)
|
|
||||||
|
|
||||||
// TODO: ticket signatures should also include miner address
|
|
||||||
if err := sig.Verify(mworker, vrfBase); err != nil {
|
|
||||||
return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrTemporal = errors.New("temporal error")
|
var ErrTemporal = errors.New("temporal error")
|
||||||
@ -515,13 +501,20 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
winnerCheck := async.Err(func() error {
|
winnerCheck := async.Err(func() error {
|
||||||
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
|
_, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed getting power: %w", err)
|
return xerrors.Errorf("failed getting power: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !types.PowerCmp(h.ElectionProof, mpow, tpow) {
|
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner)
|
||||||
return xerrors.Errorf("miner created a block but was not a winner")
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to get sector size for block miner: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range h.EPostProof.Winners {
|
||||||
|
if !types.IsTicketWinner(t.Partial, ssize, tpow, 1) {
|
||||||
|
return xerrors.Errorf("miner created a block but was not a winner")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -578,20 +571,15 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
})
|
})
|
||||||
|
|
||||||
tktsCheck := async.Err(func() error {
|
tktsCheck := async.Err(func() error {
|
||||||
if err := syncer.validateTicket(ctx, waddr, h.Ticket, baseTs, h.Height); err != nil {
|
if err := syncer.validateTicket(ctx, h.Miner, waddr, h.Ticket, baseTs); err != nil {
|
||||||
return xerrors.Errorf("validating block tickets failed: %w", err)
|
return xerrors.Errorf("validating block tickets failed: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
eproofCheck := async.Err(func() error {
|
eproofCheck := async.Err(func() error {
|
||||||
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback))
|
if err := syncer.VerifyElectionPoStProof(ctx, h, baseTs, waddr); err != nil {
|
||||||
if err != nil {
|
return xerrors.Errorf("invalid election post: %w", err)
|
||||||
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := VerifyElectionProof(ctx, h.ElectionProof, rand, waddr); err != nil {
|
|
||||||
return xerrors.Errorf("checking eproof failed: %w", err)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -615,6 +603,49 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
return merr
|
return merr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, baseTs *types.TipSet, waddr address.Address) error {
|
||||||
|
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback))
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := VerifyElectionPoStVRF(ctx, h.EPostProof.PostRand, rand, waddr, h.Miner); err != nil {
|
||||||
|
return xerrors.Errorf("checking eproof failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to get sector size for miner: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var winners []sectorbuilder.EPostCandidate
|
||||||
|
for _, t := range h.EPostProof.Winners {
|
||||||
|
var partial [32]byte
|
||||||
|
copy(partial[:], t.Partial)
|
||||||
|
winners = append(winners, sectorbuilder.EPostCandidate{
|
||||||
|
PartialTicket: partial,
|
||||||
|
SectorID: t.SectorID,
|
||||||
|
SectorChallengeIndex: t.ChallengeIndex,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sectorInfo, err := stmgr.GetSectorsForElectionPost(ctx, syncer.sm, baseTs, h.Miner)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting election post sector set: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, h.EPostProof.PostRand, h.EPostProof.Proof, winners, waddr)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to verify election post: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return xerrors.Errorf("election post was invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
|
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
|
||||||
nonces := make(map[address.Address]uint64)
|
nonces := make(map[address.Address]uint64)
|
||||||
balances := make(map[address.Address]types.BigInt)
|
balances := make(map[address.Address]types.BigInt)
|
||||||
@ -1058,14 +1089,9 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyElectionProof(ctx context.Context, eproof []byte, rand []byte, worker address.Address) error {
|
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker, miner address.Address) error {
|
||||||
sig := types.Signature{
|
if err := gen.VerifyVRF(ctx, worker, miner, gen.DSepElectionPost, rand, evrf); err != nil {
|
||||||
Data: eproof,
|
return xerrors.Errorf("failed to verify post_randomness vrf: %w", err)
|
||||||
Type: types.KTBLS,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sig.Verify(worker, rand); err != nil {
|
|
||||||
return xerrors.Errorf("failed to verify election proof signature: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -20,14 +20,24 @@ type Ticket struct {
|
|||||||
VRFProof []byte
|
VRFProof []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type ElectionProof []byte
|
type EPostTicket struct {
|
||||||
|
Partial []byte
|
||||||
|
SectorID uint64
|
||||||
|
ChallengeIndex uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type EPostProof struct {
|
||||||
|
Proof []byte
|
||||||
|
PostRand []byte
|
||||||
|
Winners []EPostTicket
|
||||||
|
}
|
||||||
|
|
||||||
type BlockHeader struct {
|
type BlockHeader struct {
|
||||||
Miner address.Address
|
Miner address.Address
|
||||||
|
|
||||||
Ticket *Ticket
|
Ticket *Ticket
|
||||||
|
|
||||||
ElectionProof []byte
|
EPostProof EPostProof
|
||||||
|
|
||||||
Parents []cid.Cid
|
Parents []cid.Cid
|
||||||
|
|
||||||
@ -162,29 +172,31 @@ func CidArrsEqual(a, b []cid.Cid) bool {
|
|||||||
|
|
||||||
var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
||||||
|
|
||||||
func PowerCmp(eproof ElectionProof, mpow, totpow BigInt) bool {
|
func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt, sampleRate int64) bool {
|
||||||
|
ssize := NewInt(ssizeI)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Need to check that
|
Need to check that
|
||||||
(h(vrfout) + 1) / (max(h) + 1) <= e * minerPower / totalPower
|
(h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower
|
||||||
max(h) == 2^256-1
|
max(h) == 2^256-1
|
||||||
which in terms of integer math means:
|
which in terms of integer math means:
|
||||||
(h(vrfout) + 1) * totalPower <= e * minerPower * 2^256
|
(h(vrfout) + 1) * totalPower <= e * sectorSize * 2^256
|
||||||
in 2^256 space, it is equivalent to:
|
in 2^256 space, it is equivalent to:
|
||||||
h(vrfout) * totalPower < e * minerPower * 2^256
|
h(vrfout) * totalPower < e * sectorSize * 2^256
|
||||||
*/
|
*/
|
||||||
|
|
||||||
h := sha256.Sum256(eproof)
|
h := sha256.Sum256(partialTicket)
|
||||||
|
|
||||||
lhs := BigFromBytes(h[:]).Int
|
lhs := BigFromBytes(h[:]).Int
|
||||||
lhs = lhs.Mul(lhs, totpow.Int)
|
lhs = lhs.Mul(lhs, totpow.Int)
|
||||||
|
lhs = lhs.Mul(lhs, big.NewInt(sampleRate))
|
||||||
|
|
||||||
// rhs = minerPower * 2^256
|
// rhs = sectorSize * 2^256
|
||||||
// rhs = minerPower << 256
|
// rhs = sectorSize << 256
|
||||||
rhs := new(big.Int).Lsh(mpow.Int, 256)
|
rhs := new(big.Int).Lsh(ssize.Int, 256)
|
||||||
rhs = rhs.Mul(rhs, blocksPerEpoch.Int)
|
rhs = rhs.Mul(rhs, blocksPerEpoch.Int)
|
||||||
|
|
||||||
// h(vrfout) * totalPower < e * minerPower * 2^256?
|
// h(vrfout) * totalPower < e * sectorSize * 2^256?
|
||||||
return lhs.Cmp(rhs) == -1
|
return lhs.Cmp(rhs) == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,10 @@ func testBlockHeader(t testing.TB) *BlockHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &BlockHeader{
|
return &BlockHeader{
|
||||||
Miner: addr,
|
Miner: addr,
|
||||||
ElectionProof: []byte("cats won the election"),
|
EPostProof: EPostProof{
|
||||||
|
Proof: []byte("pruuf"),
|
||||||
|
},
|
||||||
Ticket: &Ticket{
|
Ticket: &Ticket{
|
||||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||||
},
|
},
|
||||||
|
@ -33,11 +33,8 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.ElectionProof ([]uint8) (slice)
|
// t.t.EPostProof (types.EPostProof) (struct)
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.ElectionProof)))); err != nil {
|
if err := t.EPostProof.MarshalCBOR(w); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write(t.ElectionProof); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,22 +138,14 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.t.ElectionProof ([]uint8) (slice)
|
// t.t.EPostProof (types.EPostProof) (struct)
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
{
|
||||||
if err != nil {
|
|
||||||
return err
|
if err := t.EPostProof.UnmarshalCBOR(br); err != nil {
|
||||||
}
|
return err
|
||||||
if extra > 8192 {
|
}
|
||||||
return fmt.Errorf("t.ElectionProof: array too large (%d)", extra)
|
|
||||||
}
|
|
||||||
|
|
||||||
if maj != cbg.MajByteString {
|
|
||||||
return fmt.Errorf("expected byte array")
|
|
||||||
}
|
|
||||||
t.ElectionProof = make([]byte, extra)
|
|
||||||
if _, err := io.ReadFull(br, t.ElectionProof); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
// t.t.Parents ([]cid.Cid) (slice)
|
// t.t.Parents ([]cid.Cid) (slice)
|
||||||
|
|
||||||
@ -335,6 +324,205 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *EPostProof) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{131}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Proof ([]uint8) (slice)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(t.Proof); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.PostRand ([]uint8) (slice)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(t.PostRand); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Winners ([]types.EPostTicket) (slice)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Winners)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, v := range t.Winners {
|
||||||
|
if err := v.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *EPostProof) 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 != 3 {
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Proof ([]uint8) (slice)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.Proof: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
t.Proof = make([]byte, extra)
|
||||||
|
if _, err := io.ReadFull(br, t.Proof); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.t.PostRand ([]uint8) (slice)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.PostRand: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
t.PostRand = make([]byte, extra)
|
||||||
|
if _, err := io.ReadFull(br, t.PostRand); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.t.Winners ([]types.EPostTicket) (slice)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.Winners: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("expected cbor array")
|
||||||
|
}
|
||||||
|
if extra > 0 {
|
||||||
|
t.Winners = make([]EPostTicket, extra)
|
||||||
|
}
|
||||||
|
for i := 0; i < int(extra); i++ {
|
||||||
|
|
||||||
|
var v EPostTicket
|
||||||
|
if err := v.UnmarshalCBOR(br); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Winners[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *EPostTicket) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{131}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Partial ([]uint8) (slice)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Partial)))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(t.Partial); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.SectorID (uint64) (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.ChallengeIndex (uint64) (uint64)
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ChallengeIndex))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *EPostTicket) 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 != 3 {
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.Partial ([]uint8) (slice)
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if extra > 8192 {
|
||||||
|
return fmt.Errorf("t.Partial: array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
t.Partial = make([]byte, extra)
|
||||||
|
if _, err := io.ReadFull(br, t.Partial); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.t.SectorID (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.SectorID = uint64(extra)
|
||||||
|
// t.t.ChallengeIndex (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.ChallengeIndex = uint64(extra)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Message) MarshalCBOR(w io.Writer) error {
|
func (t *Message) MarshalCBOR(w io.Writer) error {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
@ -34,8 +34,10 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &types.BlockHeader{
|
return &types.BlockHeader{
|
||||||
Miner: addr,
|
Miner: addr,
|
||||||
ElectionProof: []byte("cats won the election"),
|
EPostProof: types.EPostProof{
|
||||||
|
Proof: []byte("election post proof proof"),
|
||||||
|
},
|
||||||
Ticket: &types.Ticket{
|
Ticket: &types.Ticket{
|
||||||
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
|
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
|
||||||
},
|
},
|
||||||
|
2
extern/go-bls-sigs
vendored
2
extern/go-bls-sigs
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 98479d3c79620f18783da0c2c6a15f8b8eb4fa2e
|
Subproject commit 1c177e24fd71669a1c8cc2e0ce4ba6e247e34d77
|
2
extern/go-sectorbuilder
vendored
2
extern/go-sectorbuilder
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 40278d4a6623e4c81003e20444871c9362bedd61
|
Subproject commit 33fb89c5efe02a250508e95114836bd13dd3067e
|
@ -20,6 +20,8 @@ func main() {
|
|||||||
err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types",
|
err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types",
|
||||||
types.BlockHeader{},
|
types.BlockHeader{},
|
||||||
types.Ticket{},
|
types.Ticket{},
|
||||||
|
types.EPostProof{},
|
||||||
|
types.EPostTicket{},
|
||||||
types.Message{},
|
types.Message{},
|
||||||
types.SignedMessage{},
|
types.SignedMessage{},
|
||||||
types.MsgMeta{},
|
types.MsgMeta{},
|
||||||
|
@ -47,6 +47,8 @@ type PublicPieceInfo = sectorbuilder.PublicPieceInfo
|
|||||||
|
|
||||||
type RawSealPreCommitOutput = sectorbuilder.RawSealPreCommitOutput
|
type RawSealPreCommitOutput = sectorbuilder.RawSealPreCommitOutput
|
||||||
|
|
||||||
|
type EPostCandidate = sectorbuilder.Candidate
|
||||||
|
|
||||||
const CommLen = sectorbuilder.CommitmentBytesLen
|
const CommLen = sectorbuilder.CommitmentBytesLen
|
||||||
|
|
||||||
type SectorBuilder struct {
|
type SectorBuilder struct {
|
||||||
@ -333,16 +335,36 @@ func (sb *SectorBuilder) GetAllStagedSectors() ([]uint64, error) {
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) {
|
func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) {
|
||||||
// Wait, this is a blocking method with no way of interrupting it?
|
// Wait, this is a blocking method with no way of interrupting it?
|
||||||
// does it checkpoint itself?
|
// does it checkpoint itself?
|
||||||
return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, challengeSeed, faults)
|
return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, challengeSeed, faults)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (sb *SectorBuilder) SectorSize() uint64 {
|
func (sb *SectorBuilder) SectorSize() uint64 {
|
||||||
return sb.ssize
|
return sb.ssize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedSectorInfo, challengeSeed []byte, winners []EPostCandidate) ([]byte, error) {
|
||||||
|
if len(challengeSeed) != CommLen {
|
||||||
|
return nil, xerrors.Errorf("given challenge seed was the wrong length: %d != %d", len(challengeSeed), CommLen)
|
||||||
|
}
|
||||||
|
var cseed [CommLen]byte
|
||||||
|
copy(cseed[:], challengeSeed)
|
||||||
|
|
||||||
|
return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, winners)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) {
|
||||||
|
return sectorbuilder.GenerateCandidates(sb.handle, sectorInfo, challengeSeed, faults)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) {
|
||||||
|
panic("NYI")
|
||||||
|
}
|
||||||
|
|
||||||
var UserBytesForSectorSize = sectorbuilder.GetMaxUserBytesPerStagedSector
|
var UserBytesForSectorSize = sectorbuilder.GetMaxUserBytesPerStagedSector
|
||||||
|
|
||||||
func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address, ticket []byte, seed []byte, sectorID uint64, proof []byte) (bool, error) {
|
func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address, ticket []byte, seed []byte, sectorID uint64, proof []byte) (bool, error) {
|
||||||
@ -360,10 +382,14 @@ func NewSortedSectorInfo(sectors []SectorInfo) SortedSectorInfo {
|
|||||||
return sectorbuilder.NewSortedSectorInfo(sectors...)
|
return sectorbuilder.NewSortedSectorInfo(sectors...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, proof []byte, faults []uint64) (bool, error) {
|
func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) {
|
||||||
|
var challengeSeeda [CommLen]byte
|
||||||
|
copy(challengeSeeda[:], challengeSeed)
|
||||||
|
|
||||||
_, span := trace.StartSpan(ctx, "VerifyPoSt")
|
_, span := trace.StartSpan(ctx, "VerifyPoSt")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeed, proof, faults)
|
prover := addressToProverID(proverID)
|
||||||
|
return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, proof, winners, prover)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) {
|
func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) {
|
||||||
|
@ -47,6 +47,8 @@ func NewMiner(api api) *Miner {
|
|||||||
type Miner struct {
|
type Miner struct {
|
||||||
api api
|
api api
|
||||||
|
|
||||||
|
epp gen.ElectionPoStProver
|
||||||
|
|
||||||
lk sync.Mutex
|
lk sync.Mutex
|
||||||
addresses []address.Address
|
addresses []address.Address
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
@ -248,12 +250,12 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
|
|||||||
|
|
||||||
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
|
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()))
|
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids()))
|
||||||
ticket, err := m.scratchTicket(ctx, addr, base)
|
ticket, err := m.computeTicket(ctx, addr, base)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "scratching ticket failed")
|
return nil, errors.Wrap(err, "scratching ticket failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, &m.api)
|
win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, &m.api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to check if we win next round")
|
return nil, errors.Wrap(err, "failed to check if we win next round")
|
||||||
}
|
}
|
||||||
@ -278,7 +280,7 @@ func (m *Miner) computeVRF(ctx context.Context, addr address.Address, input []by
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return gen.ComputeVRF(ctx, m.api.WalletSign, w, input)
|
return gen.ComputeVRF(ctx, m.api.WalletSign, w, addr, gen.DSepTicket, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||||
@ -303,10 +305,9 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty
|
|||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) {
|
func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) {
|
||||||
round := base.ts.Height() + base.nullRounds + 1
|
|
||||||
|
|
||||||
vrfBase := gen.TicketHash(base.ts.MinTicket(), round)
|
vrfBase := gen.TicketHash(base.ts.MinTicket(), addr)
|
||||||
|
|
||||||
vrfOut, err := m.computeVRF(ctx, addr, vrfBase)
|
vrfOut, err := m.computeVRF(ctx, addr, vrfBase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -318,7 +319,7 @@ func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *M
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof types.ElectionProof) (*types.BlockMsg, error) {
|
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof) (*types.BlockMsg, error) {
|
||||||
|
|
||||||
pending, err := m.api.MpoolPending(context.TODO(), base.ts)
|
pending, err := m.api.MpoolPending(context.TODO(), base.ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -177,7 +177,7 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
|
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
|
||||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
||||||
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts)
|
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -193,7 +193,7 @@ func (p *post) runPost(ctx context.Context) error {
|
|||||||
var seed [32]byte
|
var seed [32]byte
|
||||||
copy(seed[:], p.r)
|
copy(seed[:], p.r)
|
||||||
|
|
||||||
proof, err := p.m.sb.GeneratePoSt(p.sortedSectorInfo(), seed, faults)
|
proof, err := p.m.sb.GenerateFallbackPoSt(p.sortedSectorInfo(), seed, faults)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("running post failed: %w", err)
|
return xerrors.Errorf("running post failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -209,8 +209,9 @@ func (p *post) commitPost(ctx context.Context) error {
|
|||||||
ctx, span := trace.StartSpan(ctx, "storage.commitPost")
|
ctx, span := trace.StartSpan(ctx, "storage.commitPost")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
|
panic("NYI")
|
||||||
params := &actors.SubmitPoStParams{
|
params := &actors.SubmitPoStParams{
|
||||||
Proof: p.proof,
|
//Proof: p.proof,
|
||||||
DoneSet: types.BitFieldFromSet(nil),
|
DoneSet: types.BitFieldFromSet(nil),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user