Reintroduce correct ticket randomness alongside ElectionProof

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
Jakub Sztandera 2020-04-08 21:06:41 +02:00
parent 9a17beba9e
commit ce4978d8c3
15 changed files with 151 additions and 331 deletions

View File

@ -73,7 +73,7 @@ type FullNode interface {
// miner
MinerGetBaseInfo(context.Context, address.Address, types.TipSetKey) (*MiningBaseInfo, error)
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.ElectionProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
// // UX ?

View File

@ -88,8 +88,8 @@ type FullNodeStruct struct {
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.ElectionProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
@ -330,7 +330,7 @@ func (c *FullNodeStruct) MinerGetBaseInfo(ctx context.Context, maddr address.Add
return c.Internal.MinerGetBaseInfo(ctx, maddr, tsk)
}
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.ElectionProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, bvals, msgs, height, ts)
}

View File

@ -69,7 +69,7 @@ const MaxSealLookback = SealRandomnessLookbackLimit + 2000 // TODO: Get from spe
// Mining
// Epochs
const EcRandomnessLookback = Finality
const TicketRandomnessLookback = 1
// /////
// Devnet settings

View File

@ -277,17 +277,16 @@ func CarWalkFunc(nd format.Node) (out []*format.Link, err error) {
return out, nil
}
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *types.Ticket, error) {
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *types.ElectionProof, *types.Ticket, error) {
mc := &mca{w: cg.w, sm: cg.sm}
prev, err := cg.cs.GetLatestBeaconEntry(pts)
if err != nil {
return nil, nil, xerrors.Errorf("getLatestBeaconEntry: %w", err)
return nil, nil, nil, xerrors.Errorf("getLatestBeaconEntry: %w", err)
}
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, abi.ChainEpoch(round), *prev)
if err != nil {
return nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
return nil, nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
}
if len(entries) == 0 {
panic("no drand")
@ -298,39 +297,37 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
rbase = entries[len(entries)-1]
}
buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil {
return nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
eproof, err := IsRoundWinner(ctx, pts, round, m, rbase, mc)
if err != nil {
return nil, nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
}
ticketRand, err := store.DrawRandomness(rbase.Data, 17, round, buf.Bytes())
buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil {
return nil, nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
}
ticketRand, err := cg.cs.GetRandomness(ctx, pts.Cids(), crypto.DomainSeparationTag_TicketProduction,
round-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
st := pts.ParentState()
worker, err := stmgr.GetMinerWorkerRaw(ctx, cg.sm, st, m)
if err != nil {
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
}
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
if err != nil {
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
}
tick := &types.Ticket{
VRFProof: vrfout,
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
}
// TODO winning post return?
_, err = IsRoundWinner(ctx, pts, round, m, rbase, mc)
if err != nil {
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
}
return entries, tick, nil
return entries, eproof, &types.Ticket{VRFProof: vrfout}, nil
}
type MinedTipSet struct {
@ -358,7 +355,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
for round := base.Height() + 1; len(blks) == 0; round++ {
for _, m := range miners {
bvals, t, err := cg.nextBlockProof(context.TODO(), base, m, round)
bvals, et, ticket, err := cg.nextBlockProof(context.TODO(), base, m, round)
if err != nil {
return nil, xerrors.Errorf("next block proof: %w", err)
}
@ -366,9 +363,10 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
panic("no drand")
}
if t != nil {
if et != nil {
// TODO: winning post proof
fblk, err := cg.makeBlock(base, m, nil, t, bvals, abi.ChainEpoch(round), msgs)
_ = ticket
fblk, err := cg.makeBlock(base, m, ticket, et, bvals, abi.ChainEpoch(round), msgs)
if err != nil {
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
}
@ -390,7 +388,9 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
}, nil
}
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, bvals []types.BeaconEntry, height abi.ChainEpoch, msgs []*types.SignedMessage) (*types.FullBlock, error) {
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticket *types.Ticket,
eticket *types.ElectionProof, bvals []types.BeaconEntry, height abi.ChainEpoch,
msgs []*types.SignedMessage) (*types.FullBlock, error) {
var ts uint64
if cg.Timestamper != nil {
@ -399,7 +399,7 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *
ts = parents.MinTimestamp() + uint64((height-parents.Height())*build.BlockDelay)
}
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, bvals, msgs, height, ts)
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, vrfticket, eticket, bvals, msgs, height, ts)
if err != nil {
return nil, err
}
@ -531,37 +531,37 @@ type ProofInput struct {
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
miner address.Address, brand types.BeaconEntry, a MiningCheckAPI) (bool, error) {
miner address.Address, brand types.BeaconEntry, a MiningCheckAPI) (*types.ElectionProof, error) {
buf := new(bytes.Buffer)
if err := miner.MarshalCBOR(buf); err != nil {
return false, xerrors.Errorf("failed to cbor marshal address: %w")
return nil, xerrors.Errorf("failed to cbor marshal address: %w")
}
electionRand, err := store.DrawRandomness(brand.Data, 17, round, buf.Bytes())
if err != nil {
return false, xerrors.Errorf("failed to draw randomness: %w", err)
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
}
mbi, err := a.MinerGetBaseInfo(ctx, miner, ts.Key())
if err != nil {
return false, xerrors.Errorf("failed to get mining base info: %w", err)
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
}
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.Worker, electionRand)
if err != nil {
return false, xerrors.Errorf("failed to compute VRF: %w", err)
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
}
// TODO: wire in real power
myPower := types.BigMul(types.NewInt(uint64(len(mbi.Sectors))), types.NewInt(uint64(mbi.SectorSize)))
if !types.IsTicketWinner(vrfout, myPower, mbi.NetworkPower) {
return false, nil
if !types.IsTicketWinner(vrfout, mbi.MinerPower, mbi.NetworkPower) {
return nil, nil
}
return true, nil
return &types.ElectionProof{VRFProof: vrfout}, nil
}
/*
func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (*types.EPostProof, error) {
proof, err := epp.ComputeProof(ctx, pi.sectors, pi.hvrf, pi.winners)
if err != nil {
@ -584,6 +584,7 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
return &ept, nil
}
*/
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)

View File

@ -252,11 +252,8 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys
}
b := &types.BlockHeader{
Miner: builtin.SystemActorAddr,
Ticket: genesisticket,
EPostProof: types.EPostProof{
PostRand: []byte("i guess this is kinda random"),
},
Miner: builtin.SystemActorAddr,
Ticket: genesisticket,
Parents: []cid.Cid{},
Height: 0,
ParentWeight: types.NewInt(0),

View File

@ -21,8 +21,10 @@ import (
)
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address,
parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, bvals []types.BeaconEntry,
msgs []*types.SignedMessage, height abi.ChainEpoch, timestamp uint64) (*types.FullBlock, error) {
parents *types.TipSet, vrfticket *types.Ticket, eproof *types.ElectionProof,
bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch,
timestamp uint64) (*types.FullBlock, error) {
st, recpts, err := sm.TipSetState(ctx, parents)
if err != nil {
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
@ -36,7 +38,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
next := &types.BlockHeader{
Miner: miner,
Parents: parents.Cids(),
Ticket: ticket,
Ticket: vrfticket,
ElectionProof: eproof,
BeaconEntries: bvals,
Height: height,
Timestamp: timestamp,

View File

@ -314,7 +314,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
Miner: b.Miner,
BlsMessages: make([]types.ChainMsg, 0, len(bms)),
SecpkMessages: make([]types.ChainMsg, 0, len(sms)),
TicketCount: int64(len(b.EPostProof.Proofs)),
TicketCount: 1, //int64(len(b.EPostProof.Proofs)), // TODO fix this
}
for _, m := range bms {

View File

@ -23,6 +23,7 @@ import (
"go.opencensus.io/stats"
"go.opencensus.io/trace"
"go.uber.org/multierr"
"go.uber.org/zap"
amt "github.com/filecoin-project/go-amt-ipld/v2"
@ -893,7 +894,7 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
}
func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
// log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar().Warnw("DrawRandomness", "base", rbase, "dsep", pers, "round", round, "entropy", entropy)
log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar().Warnw("DrawRandomness", "base", rbase, "dsep", pers, "round", round, "entropy", entropy)
h := blake2b.New256()
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
@ -913,11 +914,9 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers cr
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
/*
defer func() {
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
}()
*/
//defer func() {
//log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
//}()
for {
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {

View File

@ -18,7 +18,6 @@ import (
logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p-core/connmgr"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/minio/blake2b-simd"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/whyrusleeping/pubsub"
"go.opencensus.io/stats"
@ -28,7 +27,6 @@ import (
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/crypto"
@ -45,7 +43,6 @@ import (
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/sector-storage/ffiwrapper"
)
var log = logging.Logger("chain")
@ -538,30 +535,6 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height(), diff)
}
winnerCheck := async.Err(func() error {
slashed, err := stmgr.GetMinerSlashed(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed to check if block miner was slashed: %w", err)
}
if slashed {
return xerrors.Errorf("received block was from slashed or invalid miner")
}
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed getting power: %w", err)
}
if !types.IsTicketWinner(h.Ticket.VRFProof, mpow, tpow) {
return xerrors.Errorf("miner created a block but was not a winner")
}
// TODO: validate winning post proof
return nil
})
msgsCheck := async.Err(func() error {
if err := syncer.checkBlockMessages(ctx, b, baseTs); err != nil {
return xerrors.Errorf("block had invalid messages: %w", err)
@ -606,6 +579,50 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("GetMinerWorkerRaw failed: %w", err)
}
winnerCheck := async.Err(func() error {
rBeacon := *prevBeacon
if len(h.BeaconEntries) != 0 {
rBeacon = h.BeaconEntries[len(h.BeaconEntries)-1]
}
buf := new(bytes.Buffer)
if err := h.Miner.MarshalCBOR(buf); err != nil {
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
}
//TODO: DST from spec actors when it is there
vrfBase, err := store.DrawRandomness(rBeacon.Data, 17, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("could not draw randomness: %w", err)
}
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.ElectionProof.VRFProof)
if err != nil {
return xerrors.Errorf("validating block election proof failed: %w", err)
}
slashed, err := stmgr.GetMinerSlashed(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed to check if block miner was slashed: %w", err)
}
if slashed {
return xerrors.Errorf("received block was from slashed or invalid miner")
}
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed getting power: %w", err)
}
if !types.IsTicketWinner(h.ElectionProof.VRFProof, mpow, tpow) {
return xerrors.Errorf("miner created a block but was not a winner")
}
// TODO: validate winning post proof
return nil
})
blockSigCheck := async.Err(func() error {
if err := sigs.CheckBlockSignature(h, ctx, waddr); err != nil {
return xerrors.Errorf("check block signature failed: %w", err)
@ -622,18 +639,13 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
})
tktsCheck := async.Err(func() error {
baseBeacon := prevBeacon
if len(h.BeaconEntries) > 0 {
baseBeacon = &h.BeaconEntries[len(h.BeaconEntries)-1]
}
buf := new(bytes.Buffer)
if err := h.Miner.MarshalCBOR(buf); err != nil {
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
}
// TODO: use real DST from specs actors when it lands
vrfBase, err := store.DrawRandomness(baseBeacon.Data, 17, h.Height, buf.Bytes())
vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(),
crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
}
@ -689,6 +701,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return merr
}
/*
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, waddr address.Address) error {
curTs, err := types.NewTipSet([]*types.BlockHeader{h})
if err != nil {
@ -790,6 +803,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
return nil
}
*/
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
{

View File

@ -22,16 +22,8 @@ type Ticket struct {
VRFProof []byte
}
type EPostTicket struct {
Partial []byte
SectorID abi.SectorNumber
ChallengeIndex uint64
}
type EPostProof struct {
Proofs []abi.PoStProof
PostRand []byte
Candidates []EPostTicket
type ElectionProof struct {
VRFProof []byte
}
type BeaconEntry struct {
@ -44,7 +36,7 @@ type BlockHeader struct {
Ticket *Ticket // 1
EPostProof EPostProof // 2
ElectionProof *ElectionProof
BeaconEntries []BeaconEntry
@ -173,7 +165,7 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
const sha256bits = 256
func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
func IsTicketWinner(vrfTicket []byte, mypow BigInt, totpow BigInt) bool {
/*
Need to check that
(h(vrfout) + 1) / (max(h) + 1) <= e * myPower / totalPower
@ -185,7 +177,7 @@ func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
*/
h := sha256.Sum256(partialTicket)
h := sha256.Sum256(vrfTicket)
lhs := BigFromBytes(h[:]).Int
lhs = lhs.Mul(lhs, totpow.Int)
@ -199,14 +191,6 @@ func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
return lhs.Cmp(rhs) < 0
}
func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 {
if sectors-faults == 0 {
return 0
}
// ceil(sectors / SectorChallengeRatioDiv)
return (sectors-faults-1)/build.SectorChallengeRatioDiv + 1
}
func (t *Ticket) Equals(ot *Ticket) bool {
return bytes.Equal(t.VRFProof, ot.VRFProof)
}

View File

@ -35,8 +35,8 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
return err
}
// t.EPostProof (types.EPostProof) (struct)
if err := t.EPostProof.MarshalCBOR(w); err != nil {
// t.ElectionProof (types.ElectionProof) (struct)
if err := t.ElectionProof.MarshalCBOR(w); err != nil {
return err
}
@ -172,12 +172,24 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
}
}
// t.EPostProof (types.EPostProof) (struct)
// t.ElectionProof (types.ElectionProof) (struct)
{
if err := t.EPostProof.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.EPostProof: %w", err)
pb, err := br.PeekByte()
if err != nil {
return err
}
if pb == cbg.CborNull[0] {
var nbuf [1]byte
if _, err := br.Read(nbuf[:]); err != nil {
return err
}
} else {
t.ElectionProof = new(ElectionProof)
if err := t.ElectionProof.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.ElectionProof pointer: %w", err)
}
}
}
@ -435,58 +447,30 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *EPostProof) MarshalCBOR(w io.Writer) error {
func (t *ElectionProof) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{131}); err != nil {
if _, err := w.Write([]byte{129}); err != nil {
return err
}
// t.Proofs ([]abi.PoStProof) (slice)
if len(t.Proofs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Proofs was too long")
// t.VRFProof ([]uint8) (slice)
if len(t.VRFProof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.VRFProof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Proofs)))); err != nil {
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.VRFProof)))); err != nil {
return err
}
for _, v := range t.Proofs {
if err := v.MarshalCBOR(w); err != nil {
return err
}
}
// t.PostRand ([]uint8) (slice)
if len(t.PostRand) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.PostRand was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil {
if _, err := w.Write(t.VRFProof); err != nil {
return err
}
if _, err := w.Write(t.PostRand); err != nil {
return err
}
// t.Candidates ([]types.EPostTicket) (slice)
if len(t.Candidates) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Candidates was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
return err
}
for _, v := range t.Candidates {
if err := v.MarshalCBOR(w); err != nil {
return err
}
}
return nil
}
func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
func (t *ElectionProof) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
@ -497,38 +481,11 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 3 {
if extra != 1 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Proofs ([]abi.PoStProof) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > cbg.MaxLength {
return fmt.Errorf("t.Proofs: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Proofs = make([]abi.PoStProof, extra)
}
for i := 0; i < int(extra); i++ {
var v abi.PoStProof
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
t.Proofs[i] = v
}
// t.PostRand ([]uint8) (slice)
// t.VRFProof ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
@ -536,141 +493,15 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
}
if extra > cbg.ByteArrayMaxLen {
return fmt.Errorf("t.PostRand: byte array too large (%d)", extra)
return fmt.Errorf("t.VRFProof: byte 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 {
t.VRFProof = make([]byte, extra)
if _, err := io.ReadFull(br, t.VRFProof); err != nil {
return err
}
// t.Candidates ([]types.EPostTicket) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > cbg.MaxLength {
return fmt.Errorf("t.Candidates: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Candidates = make([]EPostTicket, extra)
}
for i := 0; i < int(extra); i++ {
var v EPostTicket
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
t.Candidates[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.Partial ([]uint8) (slice)
if len(t.Partial) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Partial was too long")
}
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.SectorID (abi.SectorNumber) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
return err
}
// 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.Partial ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > cbg.ByteArrayMaxLen {
return fmt.Errorf("t.Partial: byte 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.SectorID (abi.SectorNumber) (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 = abi.SectorNumber(extra)
}
// 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
}
@ -1506,7 +1337,7 @@ func (t *BeaconEntry) MarshalCBOR(w io.Writer) error {
return err
}
// t.Index (uint64) (uint64)
// t.Round (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Round))); err != nil {
return err
@ -1541,7 +1372,7 @@ func (t *BeaconEntry) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Index (uint64) (uint64)
// t.Round (uint64) (uint64)
{

View File

@ -60,8 +60,8 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
return &types.BlockHeader{
Miner: addr,
EPostProof: types.EPostProof{
Proofs: []abi.PoStProof{{ProofBytes: []byte("election post proof proof")}},
ElectionProof: &types.ElectionProof{
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
},
Ticket: &types.Ticket{
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),

View File

@ -11,15 +11,13 @@ import (
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/hello"
"github.com/filecoin-project/lotus/paychmgr"
sealing "github.com/filecoin-project/storage-fsm"
)
func main() {
err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types",
types.BlockHeader{},
types.Ticket{},
types.EPostProof{},
types.EPostTicket{},
types.ElectionProof{},
types.Message{},
types.SignedMessage{},
types.MsgMeta{},
@ -74,13 +72,4 @@ func main() {
os.Exit(1)
}
err = gen.WriteMapEncodersToFile("./storage/sealing/cbor_gen.go", "sealing",
sealing.Piece{},
sealing.SectorInfo{},
sealing.Log{},
)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

View File

@ -9,13 +9,13 @@ import (
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
lru "github.com/hashicorp/golang-lru"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
logging "github.com/ipfs/go-log/v2"
@ -355,7 +355,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
}
if !winner {
if winner == nil {
base.nullRounds++
return nil, nil
}
@ -367,7 +367,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
}
// TODO: winning post proof
b, err := m.createBlock(base, addr, ticket, nil, bvals, pending)
b, err := m.createBlock(base, addr, ticket, winner, bvals, pending)
if err != nil {
return nil, xerrors.Errorf("failed to create block: %w", err)
}
@ -391,7 +391,8 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *
if err := addr.MarshalCBOR(buf); err != nil {
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
}
input, err := store.DrawRandomness(brand.Data, 17, (base.ts.Height() + base.nullRounds + 1), buf.Bytes())
input, err := m.api.ChainGetRandomness(ctx, base.ts.Key(), crypto.DomainSeparationTag_TicketProduction,
base.ts.Height()+base.nullRounds+1-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return nil, err
}
@ -407,7 +408,7 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *
}
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket,
proof *types.EPostProof, bvals []types.BeaconEntry, pending []*types.SignedMessage) (*types.BlockMsg, error) {
eproof *types.ElectionProof, bvals []types.BeaconEntry, pending []*types.SignedMessage) (*types.BlockMsg, error) {
msgs, err := SelectMessages(context.TODO(), m.api.StateGetActor, base.ts, pending)
if err != nil {
return nil, xerrors.Errorf("message filtering failed: %w", err)
@ -423,7 +424,7 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
nheight := base.ts.Height() + base.nullRounds + 1
// why even return this? that api call could just submit it for us
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts.Key(), ticket, proof, bvals, msgs, nheight, uint64(uts))
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts.Key(), ticket, eproof, bvals, msgs, nheight, uint64(uts))
}
type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)

View File

@ -269,7 +269,7 @@ func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address,
return stmgr.MinerGetBaseInfo(ctx, a.StateManager, tsk, maddr)
}
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.EPostProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.ElectionProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
parents, err := a.Chain.GetTipSetFromKey(parentsTSK)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", parentsTSK, err)