Nex wip
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
afdb1db529
commit
9c250f24fa
@ -45,6 +45,12 @@ func ValidateBlockValues(b DrandBeacon, h *types.BlockHeader, nulls int) error {
|
||||
}
|
||||
}
|
||||
|
||||
// validate that block contains entry for its own epoch
|
||||
should := b.BeaconIndexesForEpoch(h.Height, 0)
|
||||
if should[len(should)-1] != h.BeaconEntries[len(h.BeaconEntries)-1].Index {
|
||||
return xerrors.Errorf("missing beacon entry for this block")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -117,10 +123,10 @@ func (mb *mockBeacon) IsEntryForEpoch(e types.BeaconEntry, epoch abi.ChainEpoch,
|
||||
|
||||
func (mb *mockBeacon) BeaconIndexesForEpoch(epoch abi.ChainEpoch, nulls int) []uint64 {
|
||||
var out []uint64
|
||||
out = append(out, uint64(epoch))
|
||||
for i := 0; i < nulls; i++ {
|
||||
for i := nulls; i > 0; i-- {
|
||||
out = append(out, uint64(epoch)-uint64(i))
|
||||
}
|
||||
out = append(out, uint64(epoch))
|
||||
return out
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
format "github.com/ipfs/go-ipld-format"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/ipfs/go-merkledag"
|
||||
"github.com/minio/blake2b-simd"
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -307,7 +306,8 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
VRFProof: vrfout,
|
||||
}
|
||||
|
||||
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], mc)
|
||||
// TODO beacon
|
||||
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], types.BeaconEntry{}, mc)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
@ -521,11 +521,17 @@ type ProofInput struct {
|
||||
vrfout []byte
|
||||
}
|
||||
|
||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (*ProofInput, error) {
|
||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64,
|
||||
miner address.Address, epp ElectionPoStProver, brand types.BeaconEntry, a MiningCheckAPI) (*ProofInput, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
_, _ = buf.Write(brand.Data) // a bit hacky, would be better if it was insidce ChainGetRanomness,
|
||||
// but chain has no idea about the block we are in progress of producing
|
||||
|
||||
if err := miner.MarshalCBOR(buf); err != nil {
|
||||
return nil, xerrors.Errorf("failed to cbor marshal address: %w")
|
||||
}
|
||||
|
||||
epostRand, err := a.ChainGetRandomness(ctx, ts.Key(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, abi.ChainEpoch(round-build.EcRandomnessLookback), buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("chain get randomness: %w", err)
|
||||
@ -541,46 +547,57 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
|
||||
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
}
|
||||
|
||||
if len(mbi.Sectors) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var sinfos []abi.SectorInfo
|
||||
for _, s := range mbi.Sectors {
|
||||
if s.Info.Info.RegisteredProof == 0 {
|
||||
return nil, xerrors.Errorf("sector %d in proving set had registered type of zero", s.ID)
|
||||
/*
|
||||
if len(mbi.Sectors) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
sinfos = append(sinfos, abi.SectorInfo{
|
||||
SectorNumber: s.ID,
|
||||
SealedCID: s.Info.Info.SealedCID,
|
||||
RegisteredProof: s.Info.Info.RegisteredProof,
|
||||
})
|
||||
}
|
||||
|
||||
hvrf := blake2b.Sum256(vrfout)
|
||||
candidates, err := epp.GenerateCandidates(ctx, sinfos, hvrf[:])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err)
|
||||
}
|
||||
|
||||
var winners []storage.PoStCandidateWithTicket
|
||||
for _, c := range candidates {
|
||||
if types.IsTicketWinner(c.Candidate.PartialTicket, mbi.SectorSize, uint64(len(sinfos)), mbi.NetworkPower) {
|
||||
winners = append(winners, c)
|
||||
var sinfos []abi.SectorInfo
|
||||
for _, s := range mbi.Sectors {
|
||||
if s.Info.Info.RegisteredProof == 0 {
|
||||
return nil, xerrors.Errorf("sector %d in proving set had registered type of zero", s.ID)
|
||||
}
|
||||
sinfos = append(sinfos, abi.SectorInfo{
|
||||
SectorNumber: s.ID,
|
||||
SealedCID: s.Info.Info.SealedCID,
|
||||
RegisteredProof: s.Info.Info.RegisteredProof,
|
||||
})
|
||||
}
|
||||
|
||||
hvrf := blake2b.Sum256(vrfout)
|
||||
candidates, err := epp.GenerateCandidates(ctx, sinfos, hvrf[:])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err)
|
||||
}
|
||||
|
||||
var winners []storage.PoStCandidateWithTicket
|
||||
for _, c := range candidates {
|
||||
if types.IsTicketWinner(c.Candidate.PartialTicket, mbi.SectorSize, uint64(len(sinfos)), mbi.NetworkPower) {
|
||||
winners = append(winners, c)
|
||||
}
|
||||
}
|
||||
|
||||
// no winners, sad
|
||||
if len(winners) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
*/
|
||||
// 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) {
|
||||
panic("TODO what to do when we win")
|
||||
// yey winner
|
||||
}
|
||||
|
||||
// no winners, sad
|
||||
if len(winners) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &ProofInput{
|
||||
sectors: sinfos,
|
||||
hvrf: hvrf[:],
|
||||
winners: winners,
|
||||
vrfout: vrfout,
|
||||
}, nil
|
||||
/*
|
||||
return &ProofInput{
|
||||
sectors: sinfos,
|
||||
hvrf: hvrf[:],
|
||||
winners: winners,
|
||||
vrfout: vrfout,
|
||||
}, nil
|
||||
*/
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (*types.EPostProof, error) {
|
||||
|
@ -892,7 +892,7 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
||||
return NewFullTipSet(out), nil
|
||||
}
|
||||
|
||||
func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int64, drandRng []byte, entropy []byte) ([]byte, error) {
|
||||
func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
|
||||
h := blake2b.New256()
|
||||
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
@ -902,7 +902,6 @@ func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int6
|
||||
if err := binary.Write(h, binary.BigEndian, round); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
}
|
||||
h.Write(drandRng)
|
||||
h.Write(entropy)
|
||||
|
||||
return h.Sum(nil), nil
|
||||
@ -918,17 +917,6 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers cr
|
||||
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
|
||||
}()
|
||||
*/
|
||||
var drandRng []byte
|
||||
if pers == crypto.DomainSeparationTag_ElectionPoStChallengeSeed {
|
||||
// special case, use lates beacon
|
||||
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
drandRng = nts.Blocks()[0].BeaconEntries[0].Data
|
||||
}
|
||||
|
||||
for {
|
||||
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
||||
if err != nil {
|
||||
@ -940,10 +928,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers cr
|
||||
// if at (or just past -- for null epochs) appropriate epoch
|
||||
// or at genesis (works for negative epochs)
|
||||
if int64(nts.Height()) <= round || mtb.Height == 0 {
|
||||
if len(drandRng) == 0 {
|
||||
drandRng = nts.Blocks()[0].BeaconEntries[0].Data
|
||||
}
|
||||
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, drandRng, entropy)
|
||||
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, entropy)
|
||||
}
|
||||
|
||||
blks = mtb.Parents
|
||||
|
@ -628,6 +628,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
if err := beacon.ValidateBlockValues(syncer.beacon, h, int(nulls)); 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
|
||||
return nil
|
||||
})
|
||||
|
||||
@ -971,13 +972,17 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
|
||||
}
|
||||
|
||||
{
|
||||
// ensure consistency of beacon entires
|
||||
targetBE := from.Blocks()[0].BeaconEntries
|
||||
if len(targetBE) != 0 {
|
||||
if len(targetBE) == 0 {
|
||||
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
|
||||
|
||||
for _, e := range targetBE[1:] {
|
||||
if cur <= e.Index {
|
||||
markBad("wrong order of beacon entires")
|
||||
if cur >= e.Index {
|
||||
syncer.bad.Add(from.Cids()[0], "wrong order of beacon entires")
|
||||
return nil, xerrors.Errorf("wrong order of beacon entires")
|
||||
}
|
||||
}
|
||||
@ -985,12 +990,12 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
|
||||
}
|
||||
for _, bh := range from.Blocks()[1:] {
|
||||
if len(targetBE) != len(bh.BeaconEntries) {
|
||||
markBad("different number of beacon entires")
|
||||
// cannot mark bad, I think @Kubuxu
|
||||
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) {
|
||||
markBad("different beacon eintires in epoch")
|
||||
// cannot mark bad, I think @Kubuxu
|
||||
return nil, xerrors.Errorf("tipset contained different number for beacon entires")
|
||||
}
|
||||
}
|
||||
|
@ -173,39 +173,26 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
||||
|
||||
const sha256bits = 256
|
||||
|
||||
func IsTicketWinner(partialTicket []byte, ssizeI abi.SectorSize, snum uint64, totpow BigInt) bool {
|
||||
ssize := NewInt(uint64(ssizeI))
|
||||
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
|
||||
func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
|
||||
/*
|
||||
Need to check that
|
||||
(h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower
|
||||
(h(vrfout) + 1) / (max(h) + 1) <= e * myPower / totalPower
|
||||
max(h) == 2^256-1
|
||||
which in terms of integer math means:
|
||||
(h(vrfout) + 1) * totalPower <= e * sectorSize * 2^256
|
||||
(h(vrfout) + 1) * totalPower <= e * myPower * 2^256
|
||||
in 2^256 space, it is equivalent to:
|
||||
h(vrfout) * totalPower < e * sectorSize * 2^256
|
||||
h(vrfout) * totalPower < e * myPower * 2^256
|
||||
|
||||
Because of SectorChallengeRatioDiv sampling for proofs
|
||||
we need to scale this appropriately.
|
||||
|
||||
Let c = ceil(numSectors/SectorChallengeRatioDiv)
|
||||
(c is the number of tickets a miner requests)
|
||||
Accordingly we check
|
||||
(h(vrfout) + 1) / 2^256 <= e * sectorSize / totalPower * snum / c
|
||||
or
|
||||
h(vrfout) * totalPower * c < e * sectorSize * 2^256 * snum
|
||||
*/
|
||||
|
||||
h := sha256.Sum256(partialTicket)
|
||||
|
||||
lhs := BigFromBytes(h[:]).Int
|
||||
lhs = lhs.Mul(lhs, totpow.Int)
|
||||
lhs = lhs.Mul(lhs, new(big.Int).SetUint64(ssampled))
|
||||
|
||||
// rhs = sectorSize * 2^256
|
||||
// rhs = sectorSize << 256
|
||||
rhs := new(big.Int).Lsh(ssize.Int, sha256bits)
|
||||
rhs = rhs.Mul(rhs, new(big.Int).SetUint64(snum))
|
||||
rhs := new(big.Int).Lsh(mypow.Int, sha256bits)
|
||||
rhs = rhs.Mul(rhs, blocksPerEpoch.Int)
|
||||
|
||||
// h(vrfout) * totalPower < e * sectorSize * 2^256?
|
||||
|
@ -317,7 +317,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
|
||||
}
|
||||
|
||||
proofin, err := gen.IsRoundWinner(ctx, base.ts, int64(round), addr, m.epp, m.api)
|
||||
proofin, err := gen.IsRoundWinner(ctx, base.ts, int64(round), addr, m.epp, bvals[len(bvals)-1] m.api)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user