diff --git a/chain/beacon/beacon.go b/chain/beacon/beacon.go index 8647773d7..37ad66d79 100644 --- a/chain/beacon/beacon.go +++ b/chain/beacon/beacon.go @@ -124,7 +124,7 @@ func (mb *mockBeacon) IsEntryForEpoch(e types.BeaconEntry, epoch abi.ChainEpoch, func (mb *mockBeacon) BeaconRoundsForEpoch(epoch abi.ChainEpoch, prevEntry types.BeaconEntry) []uint64 { var out []uint64 - for i := prevEntry.Round + 1; i < uint64(epoch); i++ { + for i := prevEntry.Round + 1; i <= uint64(epoch); i++ { out = append(out, i) } return out diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 12157df30..613dfa3cf 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -280,12 +280,30 @@ func CarWalkFunc(nd format.Node) (out []*format.Link, err error) { func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *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) + } + + 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) + } + if len(entries) == 0 { + panic("no drand") + } + + rbase := *prev + if len(entries) > 0 { + 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) } - ticketRand, err := mc.ChainGetRandomness(ctx, pts.Key(), crypto.DomainSeparationTag_TicketProduction, abi.ChainEpoch(round-build.EcRandomnessLookback), buf.Bytes()) + ticketRand, err := store.DrawRandomness(rbase.Data, 17, round, buf.Bytes()) if err != nil { return nil, nil, err } @@ -306,21 +324,6 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add VRFProof: vrfout, } - prev, err := cg.cs.GetLatestBeaconEntry(pts) - if err != nil { - return 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) - } - - rbase := *prev - if len(entries) > 0 { - rbase = entries[len(entries)-1] - } - // TODO winning post return? _, err = IsRoundWinner(ctx, pts, round, m, rbase, mc) if err != nil { @@ -359,6 +362,9 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad if err != nil { return nil, xerrors.Errorf("next block proof: %w", err) } + if len(bvals) == 0 { + panic("no drand") + } if t != nil { // TODO: winning post proof diff --git a/chain/store/store.go b/chain/store/store.go index c5c548cb4..1645a62ee 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -893,6 +893,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) h := blake2b.New256() if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil { return nil, xerrors.Errorf("deriving randomness: %w", err) diff --git a/chain/sync.go b/chain/sync.go index 088da7b00..258572d8f 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -511,12 +511,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return xerrors.Errorf("load parent tipset failed (%s): %w", h.Parents, err) } - prevBeacon, err := syncer.getLatestBeaconEntry(baseTs) + prevBeacon, err := syncer.store.GetLatestBeaconEntry(baseTs) if err != nil { return xerrors.Errorf("failed to get latest beacon entry: %w", err) } - nulls := h.Height - (baseTs.Height() + 1) + //nulls := h.Height - (baseTs.Height() + 1) // fast checks first if h.BlockSig == nil { @@ -614,7 +614,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err }) beaconValuesCheck := async.Err(func() error { - if err := beacon.ValidateBlockValues(syncer.beacon, h, int(nulls)); err != nil { + if err := beacon.ValidateBlockValues(syncer.beacon, h, *prevBeacon); err != nil { return xerrors.Errorf("failed to validate blocks random beacon values: %w", err) } // TODO: check if first value links to value from previous block/previous block containing a value @@ -622,14 +622,9 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err }) tktsCheck := async.Err(func() error { - buf := new(bytes.Buffer) - if err := h.Miner.MarshalCBOR(buf); err != nil { - return xerrors.Errorf("failed to marshal miner address to cbor: %w", err) - } - baseBeacon := prevBeacon if len(h.BeaconEntries) > 0 { - baseBeacon = h.BeaconEntries[len(h.BeaconEntries)-1] + baseBeacon = &h.BeaconEntries[len(h.BeaconEntries)-1] } buf := new(bytes.Buffer) @@ -638,7 +633,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } // TODO: use real DST from specs actors when it lands - vrfBase, err := store.DrawRandomness(baseBeacon.Data, 17, int64(h.Height), buf.Bytes()) + vrfBase, err := store.DrawRandomness(baseBeacon.Data, 17, h.Height, buf.Bytes()) if err != nil { return xerrors.Errorf("failed to compute vrf base for ticket: %w", err) } @@ -650,19 +645,19 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return nil }) - eproofCheck := async.Err(func() error { - if err := syncer.VerifyElectionPoStProof(ctx, h, waddr); err != nil { - return xerrors.Errorf("invalid election post: %w", err) - } - return nil - }) + //eproofCheck := async.Err(func() error { + //if err := syncer.VerifyElectionPoStProof(ctx, h, waddr); err != nil { + //return xerrors.Errorf("invalid election post: %w", err) + //} + //return nil + //}) await := []async.ErrorFuture{ minerCheck, tktsCheck, blockSigCheck, beaconValuesCheck, - eproofCheck, + //eproofCheck, winnerCheck, msgsCheck, } @@ -704,7 +699,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc if err := h.Miner.MarshalCBOR(buf); err != nil { return xerrors.Errorf("failed to marshal miner to cbor: %w", err) } - rand, err := syncer.sm.ChainStore().GetRandomness(ctx, curTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, int64(h.Height-build.EcRandomnessLookback), buf.Bytes()) + rand, err := syncer.sm.ChainStore().GetRandomness(ctx, curTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, h.Height-build.EcRandomnessLookback, buf.Bytes()) if err != nil { return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err) } @@ -979,10 +974,10 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to syncer.bad.Add(from.Cids()[0], "no beacon entires") return nil, xerrors.Errorf("block (%s) contained no drand entires", from.Cids()[0]) } - cur := targetBE[0].Index + cur := targetBE[0].Round for _, e := range targetBE[1:] { - if cur >= e.Index { + if cur >= e.Round { syncer.bad.Add(from.Cids()[0], "wrong order of beacon entires") return nil, xerrors.Errorf("wrong order of beacon entires") } @@ -994,7 +989,7 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to return nil, xerrors.Errorf("tipset contained different number for beacon entires") } for i, be := range bh.BeaconEntries { - if targetBE[i].Index != be.Index || !bytes.Equal(targetBE[i].Data, be.Data) { + if targetBE[i].Round != be.Round || !bytes.Equal(targetBE[i].Data, be.Data) { // cannot mark bad, I think @Kubuxu return nil, xerrors.Errorf("tipset contained different number for beacon entires") } @@ -1331,3 +1326,24 @@ func (syncer *Syncer) MarkBad(blk cid.Cid) { func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) { return syncer.bad.Has(blk) } +func (syncer *Syncer) getLatestBeaconEntry(ctx context.Context, ts *types.TipSet) (*types.BeaconEntry, error) { + cur := ts + for i := 0; i < 20; i++ { + cbe := cur.Blocks()[0].BeaconEntries + if len(cbe) > 0 { + return &cbe[len(cbe)-1], nil + } + + if cur.Height() == 0 { + return nil, xerrors.Errorf("made it back to genesis block without finding beacon entry") + } + + next, err := syncer.store.LoadTipSet(cur.Parents()) + if err != nil { + return nil, xerrors.Errorf("failed to load parents when searching back for latest beacon entry: %w", err) + } + cur = next + } + + return nil, xerrors.Errorf("found NO beacon entries in the 20 blocks prior to given tipset") +} diff --git a/lib/increadtimeout/incrt.go b/lib/increadtimeout/incrt.go index ca44e0a6d..95e6c0e42 100644 --- a/lib/increadtimeout/incrt.go +++ b/lib/increadtimeout/incrt.go @@ -52,7 +52,7 @@ func (crt *incrt) Read(buf []byte) (int, error) { err := crt.rd.SetReadDeadline(start.Add(crt.wait)) if err != nil { - log.Warnf("unable to set deadline: %+v", err) + log.Debugf("unable to set deadline: %+v", err) } n, err := crt.rd.Read(buf) diff --git a/miner/miner.go b/miner/miner.go index a288f6626..b2562347e 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -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" @@ -340,16 +340,16 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB log.Infof("Time delta between now and our mining base: %ds (nulls: %d)", uint64(time.Now().Unix())-base.ts.MinTimestamp(), base.nullRounds) - ticket, err := m.computeTicket(ctx, addr, base) - if err != nil { - return nil, xerrors.Errorf("scratching ticket failed: %w", err) - } - rbase := *beaconPrev if len(bvals) > 0 { rbase = bvals[len(bvals)-1] } + ticket, err := m.computeTicket(ctx, addr, &rbase, base) + if err != nil { + return nil, xerrors.Errorf("scratching ticket failed: %w", err) + } + winner, err := gen.IsRoundWinner(ctx, base.ts, round, addr, rbase, m.api) if err != nil { return nil, xerrors.Errorf("failed to check if we win next round: %w", err) @@ -381,7 +381,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return b, nil } -func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { +func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *types.BeaconEntry, base *MiningBase) (*types.Ticket, error) { w, err := m.api.StateMinerWorker(ctx, addr, types.EmptyTSK) if err != nil { return nil, err @@ -391,8 +391,7 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *M if err := addr.MarshalCBOR(buf); err != nil { return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err) } - - input, err := m.api.ChainGetRandomness(ctx, base.ts.Key(), crypto.DomainSeparationTag_TicketProduction, (base.ts.Height()+base.nullRounds+1)-1, buf.Bytes()) + input, err := store.DrawRandomness(brand.Data, 17, (base.ts.Height() + base.nullRounds + 1), buf.Bytes()) if err != nil { return nil, err } diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index 1937191a6..3ddc516c0 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -59,7 +59,7 @@ func (a *ChainAPI) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, return nil, xerrors.Errorf("loading tipset key: %w", err) } - return a.Chain.GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy) + return a.Chain.GetRandomness(ctx, pts.Cids(), personalization, randEpoch, entropy) } func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) {