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
|
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 {
|
func (mb *mockBeacon) BeaconIndexesForEpoch(epoch abi.ChainEpoch, nulls int) []uint64 {
|
||||||
var out []uint64
|
var out []uint64
|
||||||
out = append(out, uint64(epoch))
|
for i := nulls; i > 0; i-- {
|
||||||
for i := 0; i < nulls; i++ {
|
|
||||||
out = append(out, uint64(epoch)-uint64(i))
|
out = append(out, uint64(epoch)-uint64(i))
|
||||||
}
|
}
|
||||||
|
out = append(out, uint64(epoch))
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
format "github.com/ipfs/go-ipld-format"
|
format "github.com/ipfs/go-ipld-format"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
"github.com/ipfs/go-merkledag"
|
"github.com/ipfs/go-merkledag"
|
||||||
"github.com/minio/blake2b-simd"
|
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
@ -307,7 +306,8 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
|||||||
VRFProof: vrfout,
|
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 {
|
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)
|
||||||
}
|
}
|
||||||
@ -521,11 +521,17 @@ type ProofInput struct {
|
|||||||
vrfout []byte
|
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 := 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 {
|
if err := miner.MarshalCBOR(buf); err != nil {
|
||||||
return nil, xerrors.Errorf("failed to cbor marshal address: %w")
|
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())
|
epostRand, err := a.ChainGetRandomness(ctx, ts.Key(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, abi.ChainEpoch(round-build.EcRandomnessLookback), buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("chain get randomness: %w", err)
|
return nil, xerrors.Errorf("chain get randomness: %w", err)
|
||||||
@ -541,6 +547,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
|
|||||||
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if len(mbi.Sectors) == 0 {
|
if len(mbi.Sectors) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -574,13 +581,23 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
|
|||||||
if len(winners) == 0 {
|
if len(winners) == 0 {
|
||||||
return nil, nil
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
return &ProofInput{
|
return &ProofInput{
|
||||||
sectors: sinfos,
|
sectors: sinfos,
|
||||||
hvrf: hvrf[:],
|
hvrf: hvrf[:],
|
||||||
winners: winners,
|
winners: winners,
|
||||||
vrfout: vrfout,
|
vrfout: vrfout,
|
||||||
}, nil
|
}, nil
|
||||||
|
*/
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (*types.EPostProof, error) {
|
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
|
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()
|
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)
|
||||||
@ -902,7 +902,6 @@ func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int6
|
|||||||
if err := binary.Write(h, binary.BigEndian, round); err != nil {
|
if err := binary.Write(h, binary.BigEndian, round); err != nil {
|
||||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||||
}
|
}
|
||||||
h.Write(drandRng)
|
|
||||||
h.Write(entropy)
|
h.Write(entropy)
|
||||||
|
|
||||||
return h.Sum(nil), nil
|
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)
|
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 {
|
for {
|
||||||
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
||||||
if err != nil {
|
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
|
// if at (or just past -- for null epochs) appropriate epoch
|
||||||
// or at genesis (works for negative epochs)
|
// or at genesis (works for negative epochs)
|
||||||
if int64(nts.Height()) <= round || mtb.Height == 0 {
|
if int64(nts.Height()) <= round || mtb.Height == 0 {
|
||||||
if len(drandRng) == 0 {
|
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, entropy)
|
||||||
drandRng = nts.Blocks()[0].BeaconEntries[0].Data
|
|
||||||
}
|
|
||||||
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, drandRng, entropy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blks = mtb.Parents
|
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 {
|
if err := beacon.ValidateBlockValues(syncer.beacon, h, int(nulls)); 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
|
||||||
return nil
|
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
|
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
|
cur := targetBE[0].Index
|
||||||
|
|
||||||
for _, e := range targetBE[1:] {
|
for _, e := range targetBE[1:] {
|
||||||
if cur <= e.Index {
|
if cur >= e.Index {
|
||||||
markBad("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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -985,12 +990,12 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
|
|||||||
}
|
}
|
||||||
for _, bh := range from.Blocks()[1:] {
|
for _, bh := range from.Blocks()[1:] {
|
||||||
if len(targetBE) != len(bh.BeaconEntries) {
|
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")
|
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].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")
|
return nil, xerrors.Errorf("tipset contained different number for beacon entires")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,39 +173,26 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
|||||||
|
|
||||||
const sha256bits = 256
|
const sha256bits = 256
|
||||||
|
|
||||||
func IsTicketWinner(partialTicket []byte, ssizeI abi.SectorSize, snum uint64, totpow BigInt) bool {
|
func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
|
||||||
ssize := NewInt(uint64(ssizeI))
|
|
||||||
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
|
|
||||||
/*
|
/*
|
||||||
Need to check that
|
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
|
max(h) == 2^256-1
|
||||||
which in terms of integer math means:
|
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:
|
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)
|
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, new(big.Int).SetUint64(ssampled))
|
|
||||||
|
|
||||||
// rhs = sectorSize * 2^256
|
// rhs = sectorSize * 2^256
|
||||||
// rhs = sectorSize << 256
|
// rhs = sectorSize << 256
|
||||||
rhs := new(big.Int).Lsh(ssize.Int, sha256bits)
|
rhs := new(big.Int).Lsh(mypow.Int, sha256bits)
|
||||||
rhs = rhs.Mul(rhs, new(big.Int).SetUint64(snum))
|
|
||||||
rhs = rhs.Mul(rhs, blocksPerEpoch.Int)
|
rhs = rhs.Mul(rhs, blocksPerEpoch.Int)
|
||||||
|
|
||||||
// h(vrfout) * totalPower < e * sectorSize * 2^256?
|
// 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)
|
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 {
|
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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user