Tests pass
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
8e0ca306d2
commit
f1c890ca54
@ -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 {
|
func (mb *mockBeacon) BeaconRoundsForEpoch(epoch abi.ChainEpoch, prevEntry types.BeaconEntry) []uint64 {
|
||||||
var out []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)
|
out = append(out, i)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
@ -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) {
|
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}
|
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)
|
buf := new(bytes.Buffer)
|
||||||
if err := m.MarshalCBOR(buf); err != nil {
|
if err := m.MarshalCBOR(buf); err != nil {
|
||||||
return nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -306,21 +324,6 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
|||||||
VRFProof: vrfout,
|
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?
|
// TODO winning post return?
|
||||||
_, err = IsRoundWinner(ctx, pts, round, m, rbase, mc)
|
_, err = IsRoundWinner(ctx, pts, round, m, rbase, mc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -359,6 +362,9 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("next block proof: %w", err)
|
return nil, xerrors.Errorf("next block proof: %w", err)
|
||||||
}
|
}
|
||||||
|
if len(bvals) == 0 {
|
||||||
|
panic("no drand")
|
||||||
|
}
|
||||||
|
|
||||||
if t != nil {
|
if t != nil {
|
||||||
// TODO: winning post proof
|
// TODO: winning post proof
|
||||||
|
@ -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) {
|
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()
|
h := blake2b.New256()
|
||||||
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
|
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
|
||||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||||
|
@ -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)
|
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 {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to get latest beacon entry: %w", err)
|
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
|
// fast checks first
|
||||||
if h.BlockSig == nil {
|
if h.BlockSig == nil {
|
||||||
@ -614,7 +614,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
})
|
})
|
||||||
|
|
||||||
beaconValuesCheck := async.Err(func() error {
|
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)
|
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
|
// 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 {
|
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
|
baseBeacon := prevBeacon
|
||||||
if len(h.BeaconEntries) > 0 {
|
if len(h.BeaconEntries) > 0 {
|
||||||
baseBeacon = h.BeaconEntries[len(h.BeaconEntries)-1]
|
baseBeacon = &h.BeaconEntries[len(h.BeaconEntries)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
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
|
// 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 {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
|
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
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
eproofCheck := async.Err(func() error {
|
//eproofCheck := async.Err(func() error {
|
||||||
if err := syncer.VerifyElectionPoStProof(ctx, h, waddr); err != nil {
|
//if err := syncer.VerifyElectionPoStProof(ctx, h, waddr); err != nil {
|
||||||
return xerrors.Errorf("invalid election post: %w", err)
|
//return xerrors.Errorf("invalid election post: %w", err)
|
||||||
}
|
//}
|
||||||
return nil
|
//return nil
|
||||||
})
|
//})
|
||||||
|
|
||||||
await := []async.ErrorFuture{
|
await := []async.ErrorFuture{
|
||||||
minerCheck,
|
minerCheck,
|
||||||
tktsCheck,
|
tktsCheck,
|
||||||
blockSigCheck,
|
blockSigCheck,
|
||||||
beaconValuesCheck,
|
beaconValuesCheck,
|
||||||
eproofCheck,
|
//eproofCheck,
|
||||||
winnerCheck,
|
winnerCheck,
|
||||||
msgsCheck,
|
msgsCheck,
|
||||||
}
|
}
|
||||||
@ -704,7 +699,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
|
|||||||
if err := h.Miner.MarshalCBOR(buf); err != nil {
|
if err := h.Miner.MarshalCBOR(buf); err != nil {
|
||||||
return xerrors.Errorf("failed to marshal miner to cbor: %w", err)
|
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 {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
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")
|
syncer.bad.Add(from.Cids()[0], "no beacon entires")
|
||||||
return nil, xerrors.Errorf("block (%s) contained no drand entires", from.Cids()[0])
|
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:] {
|
for _, e := range targetBE[1:] {
|
||||||
if cur >= e.Index {
|
if cur >= e.Round {
|
||||||
syncer.bad.Add(from.Cids()[0], "wrong order of beacon entires")
|
syncer.bad.Add(from.Cids()[0], "wrong order of beacon entires")
|
||||||
return nil, xerrors.Errorf("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")
|
return nil, xerrors.Errorf("tipset contained different number for beacon entires")
|
||||||
}
|
}
|
||||||
for i, be := range bh.BeaconEntries {
|
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
|
// cannot mark bad, I think @Kubuxu
|
||||||
return nil, xerrors.Errorf("tipset contained different number for beacon entires")
|
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) {
|
func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) {
|
||||||
return syncer.bad.Has(blk)
|
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")
|
||||||
|
}
|
||||||
|
@ -52,7 +52,7 @@ func (crt *incrt) Read(buf []byte) (int, error) {
|
|||||||
|
|
||||||
err := crt.rd.SetReadDeadline(start.Add(crt.wait))
|
err := crt.rd.SetReadDeadline(start.Add(crt.wait))
|
||||||
if err != nil {
|
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)
|
n, err := crt.rd.Read(buf)
|
||||||
|
@ -9,13 +9,13 @@ import (
|
|||||||
|
|
||||||
address "github.com/filecoin-project/go-address"
|
address "github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/beacon"
|
"github.com/filecoin-project/lotus/chain/beacon"
|
||||||
"github.com/filecoin-project/lotus/chain/gen"
|
"github.com/filecoin-project/lotus/chain/gen"
|
||||||
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
|
||||||
logging "github.com/ipfs/go-log/v2"
|
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)
|
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
|
rbase := *beaconPrev
|
||||||
if len(bvals) > 0 {
|
if len(bvals) > 0 {
|
||||||
rbase = bvals[len(bvals)-1]
|
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)
|
winner, err := gen.IsRoundWinner(ctx, base.ts, round, addr, rbase, m.api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
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
|
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)
|
w, err := m.api.StateMinerWorker(ctx, addr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err := addr.MarshalCBOR(buf); err != nil {
|
||||||
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
|
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)-1, buf.Bytes())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ func (a *ChainAPI) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey,
|
|||||||
return nil, xerrors.Errorf("loading tipset key: %w", err)
|
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) {
|
func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user