From 156a14eeeb2ae4ede1c16e6655601d0af6a84060 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 23 Jun 2020 16:59:44 +0200 Subject: [PATCH] Integrate Poisson Sortition into chain sync Signed-off-by: Jakub Sztandera --- chain/gen/gen.go | 8 ++++++-- chain/store/weight.go | 20 ++++++++++++++------ chain/sub/incoming.go | 6 ++++++ chain/sync.go | 10 +++++++--- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 89d4f32bf..14581ded9 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -559,11 +559,15 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch, } // TODO: wire in real power - if !types.IsTicketWinner(vrfout, mbi.MinerPower, mbi.NetworkPower) { + // TODO: is above TODO still applicable? + ep := &types.ElectionProof{VRFProof: vrfout} + j := ep.ComputeWinCount(mbi.MinerPower, mbi.NetworkPower) + ep.WinCount = j + if j < 1 { return nil, nil } - return &types.ElectionProof{VRFProof: vrfout}, nil + return ep, nil } type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error) diff --git a/chain/store/weight.go b/chain/store/weight.go index c92f1a74d..ac51aeb45 100644 --- a/chain/store/weight.go +++ b/chain/store/weight.go @@ -21,11 +21,11 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn if ts == nil { return types.NewInt(0), nil } - // >>> w[r] <<< + wFunction(totalPowerAtTipset(ts)) * 2^8 + (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den) + // >>> w[r] <<< + wFunction(totalPowerAtTipset(ts)) * 2^8 + (wFunction(totalPowerAtTipset(ts)) * sum(ts.blocks.ElectionProof.WinCount) * wRatio_num * 2^8) / (e * wRatio_den) var out = new(big.Int).Set(ts.Blocks()[0].ParentWeight.Int) - // >>> wFunction(totalPowerAtTipset(ts)) * 2^8 <<< + (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den) + // >>> wFunction(totalPowerAtTipset(ts)) * 2^8 <<< + (wFunction(totalPowerAtTipset(ts)) * sum(ts.blocks.ElectionProof.WinCount) * wRatio_num * 2^8) / (e * wRatio_den) tpow := big2.Zero() { @@ -57,11 +57,19 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn out.Add(out, big.NewInt(log2P<<8)) - // (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den) + // (wFunction(totalPowerAtTipset(ts)) * sum(ts.blocks.ElectionProof.WinCount) * wRatio_num * 2^8) / (e * wRatio_den) - eWeight := big.NewInt((log2P * int64(len(ts.Blocks())) * build.WRatioNum) << 8) - eWeight.Div(eWeight, big.NewInt(int64(build.BlocksPerEpoch*build.WRatioDen))) - out.Add(out, eWeight) + totalJ := uint64(0) + for _, b := range ts.Blocks() { + totalJ += b.ElectionProof.WinCount + } + + eWeight := big.NewInt((log2P * build.WRatioNum)) + eWeight = eWeight.Lsh(eWeight, 8) + eWeight = eWeight.Mul(eWeight, new(big.Int).SetUint64(totalJ)) + eWeight = eWeight.Div(eWeight, big.NewInt(int64(build.BlocksPerEpoch*build.WRatioDen))) + + out = out.Add(out, eWeight) return types.BigInt{Int: out}, nil } diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index ba61dc5c5..0c4350d03 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -210,6 +210,12 @@ func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub return pubsub.ValidationReject } + if blk.Header.ElectionProof.WinCount < 1 { + log.Errorf("block is not claiming to be winning") + recordFailure("not_winning") + return pubsub.ValidationReject + } + // it's a good block! make sure we've only seen it once if bv.recvBlocks.add(blk.Header.Cid()) > 0 { // TODO: once these changes propagate to the network, we can consider diff --git a/chain/sync.go b/chain/sync.go index 26f30d95b..b190dc449 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -651,6 +651,10 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er } winnerCheck := async.Err(func() error { + if h.ElectionProof.WinCount < 1 { + return xerrors.Errorf("block is not claiming to be a winner") + } + rBeacon := *prevBeacon if len(h.BeaconEntries) != 0 { rBeacon = h.BeaconEntries[len(h.BeaconEntries)-1] @@ -660,7 +664,6 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er 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, crypto.DomainSeparationTag_ElectionProofProduction, h.Height, buf.Bytes()) if err != nil { return xerrors.Errorf("could not draw randomness: %w", err) @@ -684,8 +687,9 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er return xerrors.Errorf("failed getting power: %w", err) } - if !types.IsTicketWinner(h.ElectionProof.VRFProof, mpow.QualityAdjPower, tpow.QualityAdjPower) { - return xerrors.Errorf("miner created a block but was not a winner") + j := h.ElectionProof.ComputeWinCount(mpow.QualityAdjPower, tpow.QualityAdjPower) + if h.ElectionProof.WinCount != j { + return xerrors.Errorf("miner claims wrong number of wins: miner: %d, computed: %d", h.ElectionProof.WinCount, j) } return nil