Merge pull request #1527 from filecoin-project/feat/drand
Initial randomness beacon implementation
This commit is contained in:
commit
70d654e4a6
@ -332,7 +332,7 @@ workflows:
|
||||
ci:
|
||||
jobs:
|
||||
- lint-changes:
|
||||
args: "--new-from-rev origin/master"
|
||||
args: "--new-from-rev origin/testnet/3"
|
||||
- test:
|
||||
codecov-upload: true
|
||||
- mod-tidy-check
|
||||
|
@ -72,7 +72,7 @@ type FullNode interface {
|
||||
// miner
|
||||
|
||||
MinerGetBaseInfo(context.Context, address.Address, types.TipSetKey) (*MiningBaseInfo, error)
|
||||
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
|
||||
MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error)
|
||||
|
||||
// // UX ?
|
||||
|
||||
@ -380,9 +380,21 @@ type ComputeStateOutput struct {
|
||||
}
|
||||
|
||||
type MiningBaseInfo struct {
|
||||
MinerPower types.BigInt
|
||||
NetworkPower types.BigInt
|
||||
Sectors []*ChainSectorInfo
|
||||
Worker address.Address
|
||||
SectorSize abi.SectorSize
|
||||
MinerPower types.BigInt
|
||||
NetworkPower types.BigInt
|
||||
Sectors []*ChainSectorInfo
|
||||
Worker address.Address
|
||||
SectorSize abi.SectorSize
|
||||
PrevBeaconEntry types.BeaconEntry
|
||||
}
|
||||
|
||||
type BlockTemplate struct {
|
||||
Miner address.Address
|
||||
Parents types.TipSetKey
|
||||
Ticket *types.Ticket
|
||||
Eproof *types.ElectionProof
|
||||
BeaconValues []types.BeaconEntry
|
||||
Messages []*types.SignedMessage
|
||||
Epoch abi.ChainEpoch
|
||||
Timestamp uint64
|
||||
}
|
||||
|
@ -88,8 +88,8 @@ type FullNodeStruct struct {
|
||||
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
|
||||
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
|
||||
|
||||
MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
||||
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
||||
MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"`
|
||||
|
||||
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
|
||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||
@ -330,8 +330,8 @@ func (c *FullNodeStruct) MinerGetBaseInfo(ctx context.Context, maddr address.Add
|
||||
return c.Internal.MinerGetBaseInfo(ctx, maddr, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, bt *api.BlockTemplate) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, bt)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
|
@ -69,7 +69,7 @@ const MaxSealLookback = SealRandomnessLookbackLimit + 2000 // TODO: Get from spe
|
||||
// Mining
|
||||
|
||||
// Epochs
|
||||
const EcRandomnessLookback = 1
|
||||
const TicketRandomnessLookback = 1
|
||||
|
||||
// /////
|
||||
// Devnet settings
|
||||
|
84
chain/beacon/beacon.go
Normal file
84
chain/beacon/beacon.go
Normal file
@ -0,0 +1,84 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
logging "github.com/ipfs/go-log"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var log = logging.Logger("beacon")
|
||||
|
||||
type Response struct {
|
||||
Entry types.BeaconEntry
|
||||
Err error
|
||||
}
|
||||
|
||||
type RandomBeacon interface {
|
||||
Entry(context.Context, uint64) <-chan Response
|
||||
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error
|
||||
MaxBeaconRoundForEpoch(abi.ChainEpoch, types.BeaconEntry) uint64
|
||||
}
|
||||
|
||||
func ValidateBlockValues(b RandomBeacon, h *types.BlockHeader, prevEntry types.BeaconEntry) error {
|
||||
maxRound := b.MaxBeaconRoundForEpoch(h.Height, prevEntry)
|
||||
if maxRound == prevEntry.Round {
|
||||
if len(h.BeaconEntries) != 0 {
|
||||
return xerrors.Errorf("expected not to have any beacon entries in this block, got %d", len(h.BeaconEntries))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
last := h.BeaconEntries[len(h.BeaconEntries)-1]
|
||||
if last.Round != maxRound {
|
||||
return xerrors.Errorf("expected final beacon entry in block to be at round %d, got %d", maxRound, last.Round)
|
||||
}
|
||||
|
||||
for i, e := range h.BeaconEntries {
|
||||
if err := b.VerifyEntry(e, prevEntry); err != nil {
|
||||
return xerrors.Errorf("beacon entry %d was invalid: %w", i, err)
|
||||
}
|
||||
prevEntry = e
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func BeaconEntriesForBlock(ctx context.Context, beacon RandomBeacon, round abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||
start := time.Now()
|
||||
|
||||
maxRound := beacon.MaxBeaconRoundForEpoch(round, prev)
|
||||
if maxRound == prev.Round {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
cur := maxRound
|
||||
var out []types.BeaconEntry
|
||||
for cur > prev.Round {
|
||||
rch := beacon.Entry(ctx, cur)
|
||||
select {
|
||||
case resp := <-rch:
|
||||
if resp.Err != nil {
|
||||
return nil, xerrors.Errorf("beacon entry request returned error: %w", resp.Err)
|
||||
}
|
||||
|
||||
out = append(out, resp.Entry)
|
||||
cur = resp.Entry.Round - 1
|
||||
case <-ctx.Done():
|
||||
return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for round %d: %w", round, ctx.Err())
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugw("fetching beacon entries", "took", time.Since(start), "numEntries", len(out))
|
||||
reverse(out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func reverse(arr []types.BeaconEntry) {
|
||||
for i := 0; i < len(arr)/2; i++ {
|
||||
arr[i], arr[len(arr)-(1+i)] = arr[len(arr)-(1+i)], arr[i]
|
||||
}
|
||||
}
|
59
chain/beacon/drand/drand.go
Normal file
59
chain/beacon/drand/drand.go
Normal file
@ -0,0 +1,59 @@
|
||||
package drand
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
dnet "github.com/drand/drand/net"
|
||||
dproto "github.com/drand/drand/protobuf/drand"
|
||||
)
|
||||
|
||||
type DrandBeacon struct {
|
||||
client dnet.Client
|
||||
|
||||
cacheLk sync.Mutex
|
||||
localCache map[int64]types.BeaconEntry
|
||||
}
|
||||
|
||||
func NewDrandBeacon() *DrandBeacon {
|
||||
return &DrandBeacon{
|
||||
client: dnet.NewGrpcClient(),
|
||||
localCache: make(map[int64]types.BeaconEntry),
|
||||
}
|
||||
}
|
||||
|
||||
//func (db *DrandBeacon)
|
||||
|
||||
func (db *DrandBeacon) Entry(ctx context.Context, round uint64) <-chan beacon.Response {
|
||||
// check cache, it it if there, otherwise query the endpoint
|
||||
resp, err := db.client.PublicRand(nil, &dproto.PublicRandRequest{Round: round})
|
||||
|
||||
var br beacon.Response
|
||||
if err != nil {
|
||||
br.Err = err
|
||||
} else {
|
||||
br.Entry.Round = resp.GetRound()
|
||||
br.Entry.Data = resp.GetSignature()
|
||||
}
|
||||
|
||||
out := make(chan beacon.Response, 1)
|
||||
out <- br
|
||||
close(out)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (db *DrandBeacon) VerifyEntry(types.BeaconEntry, types.BeaconEntry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DrandBeacon) MaxBeaconRoundForEpoch(abi.ChainEpoch, types.BeaconEntry) uint64 {
|
||||
// this is just some local math
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ beacon.RandomBeacon = (*DrandBeacon)(nil)
|
68
chain/beacon/mock.go
Normal file
68
chain/beacon/mock.go
Normal file
@ -0,0 +1,68 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/minio/blake2b-simd"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// Mock beacon assumes that filecoin rounds are 1:1 mapped with the beacon rounds
|
||||
type mockBeacon struct {
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
func NewMockBeacon(interval time.Duration) RandomBeacon {
|
||||
mb := &mockBeacon{interval: interval}
|
||||
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) RoundTime() time.Duration {
|
||||
return mb.interval
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) LastEntry() (types.BeaconEntry, error) {
|
||||
panic("NYI")
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) entryForIndex(index uint64) types.BeaconEntry {
|
||||
buf := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(buf, index)
|
||||
rval := blake2b.Sum256(buf)
|
||||
return types.BeaconEntry{
|
||||
Round: index,
|
||||
Data: rval[:],
|
||||
}
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) Entry(ctx context.Context, index uint64) <-chan Response {
|
||||
e := mb.entryForIndex(index)
|
||||
out := make(chan Response, 1)
|
||||
out <- Response{Entry: e}
|
||||
return out
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry) error {
|
||||
// TODO: cache this, especially for bls
|
||||
oe := mb.entryForIndex(from.Round)
|
||||
if !bytes.Equal(from.Data, oe.Data) {
|
||||
return xerrors.Errorf("mock beacon entry was invalid!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) IsEntryForEpoch(e types.BeaconEntry, epoch abi.ChainEpoch, nulls int) (bool, error) {
|
||||
return int64(e.Round) <= int64(epoch) && int64(epoch)-int64(nulls) >= int64(e.Round), nil
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) MaxBeaconRoundForEpoch(epoch abi.ChainEpoch, prevEntry types.BeaconEntry) uint64 {
|
||||
return uint64(epoch)
|
||||
}
|
||||
|
||||
var _ RandomBeacon = (*mockBeacon)(nil)
|
146
chain/gen/gen.go
146
chain/gen/gen.go
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||
@ -21,12 +22,12 @@ 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"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
@ -51,6 +52,8 @@ type ChainGen struct {
|
||||
|
||||
cs *store.ChainStore
|
||||
|
||||
beacon beacon.RandomBeacon
|
||||
|
||||
sm *stmgr.StateManager
|
||||
|
||||
genesis *types.BlockHeader
|
||||
@ -211,12 +214,15 @@ func NewGenerator() (*ChainGen, error) {
|
||||
|
||||
miners := []address.Address{maddr1, maddr2}
|
||||
|
||||
beac := beacon.NewMockBeacon(time.Second)
|
||||
|
||||
gen := &ChainGen{
|
||||
bs: bs,
|
||||
cs: cs,
|
||||
sm: sm,
|
||||
msgsPerBlock: msgsPerBlock,
|
||||
genesis: genb.Genesis,
|
||||
beacon: beac,
|
||||
w: w,
|
||||
|
||||
GetMessages: getRandomMessages,
|
||||
@ -271,48 +277,57 @@ func CarWalkFunc(nd format.Node) (out []*format.Link, err error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) {
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *types.ElectionProof, *types.Ticket, error) {
|
||||
mc := &mca{w: cg.w, sm: cg.sm}
|
||||
|
||||
mbi, err := mc.MinerGetBaseInfo(ctx, m, pts.Key())
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("get miner base info: %w", err)
|
||||
}
|
||||
|
||||
prev := mbi.PrevBeaconEntry
|
||||
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, round, prev)
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
|
||||
}
|
||||
|
||||
rbase := prev
|
||||
if len(entries) > 0 {
|
||||
rbase = entries[len(entries)-1]
|
||||
}
|
||||
|
||||
eproof, err := IsRoundWinner(ctx, pts, round, m, rbase, mbi, mc)
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.MarshalCBOR(buf); err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
||||
return nil, 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 := cg.cs.GetRandomness(ctx, pts.Cids(), crypto.DomainSeparationTag_TicketProduction,
|
||||
round-build.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
st := pts.ParentState()
|
||||
|
||||
worker, err := stmgr.GetMinerWorkerRaw(ctx, cg.sm, st, m)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
}
|
||||
|
||||
tick := &types.Ticket{
|
||||
VRFProof: vrfout,
|
||||
}
|
||||
// TODO winning post return?
|
||||
|
||||
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], mc)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
if eproofin == nil {
|
||||
return nil, tick, nil
|
||||
}
|
||||
eproof, err := ComputeProof(ctx, cg.eppProvs[m], eproofin)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("computing proof: %w", err)
|
||||
}
|
||||
|
||||
return eproof, tick, nil
|
||||
return entries, eproof, &types.Ticket{VRFProof: vrfout}, nil
|
||||
}
|
||||
|
||||
type MinedTipSet struct {
|
||||
@ -338,15 +353,17 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
return nil, xerrors.Errorf("get random messages: %w", err)
|
||||
}
|
||||
|
||||
for round := int64(base.Height() + 1); len(blks) == 0; round++ {
|
||||
for round := base.Height() + 1; len(blks) == 0; round++ {
|
||||
for _, m := range miners {
|
||||
proof, t, err := cg.nextBlockProof(context.TODO(), base, m, round)
|
||||
bvals, et, ticket, err := cg.nextBlockProof(context.TODO(), base, m, round)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("next block proof: %w", err)
|
||||
}
|
||||
|
||||
if proof != nil {
|
||||
fblk, err := cg.makeBlock(base, m, proof, t, abi.ChainEpoch(round), msgs)
|
||||
if et != nil {
|
||||
// TODO: winning post proof
|
||||
_ = ticket
|
||||
fblk, err := cg.makeBlock(base, m, ticket, et, bvals, round, msgs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
||||
}
|
||||
@ -368,7 +385,9 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height abi.ChainEpoch, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticket *types.Ticket,
|
||||
eticket *types.ElectionProof, bvals []types.BeaconEntry, height abi.ChainEpoch,
|
||||
msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
|
||||
var ts uint64
|
||||
if cg.Timestamper != nil {
|
||||
@ -377,7 +396,16 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *
|
||||
ts = parents.MinTimestamp() + uint64((height-parents.Height())*build.BlockDelay)
|
||||
}
|
||||
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, msgs, height, ts)
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, &api.BlockTemplate{
|
||||
Miner: m,
|
||||
Parents: parents.Key(),
|
||||
Ticket: vrfticket,
|
||||
Eproof: eticket,
|
||||
BeaconValues: bvals,
|
||||
Messages: msgs,
|
||||
Epoch: height,
|
||||
Timestamp: ts,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -462,7 +490,7 @@ func (mca mca) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, pers
|
||||
return nil, xerrors.Errorf("loading tipset key: %w", err)
|
||||
}
|
||||
|
||||
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy)
|
||||
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, randEpoch, entropy)
|
||||
}
|
||||
|
||||
func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*api.MiningBaseInfo, error) {
|
||||
@ -508,68 +536,33 @@ 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 abi.ChainEpoch,
|
||||
miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) {
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
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())
|
||||
|
||||
electionRand, err := store.DrawRandomness(brand.Data, 17, round, buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("chain get randomness: %w", err)
|
||||
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
||||
}
|
||||
|
||||
mbi, err := a.MinerGetBaseInfo(ctx, miner, ts.Key())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.Worker, epostRand)
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.Worker, electionRand)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
}
|
||||
|
||||
if len(mbi.Sectors) == 0 {
|
||||
// TODO: wire in real power
|
||||
if !types.IsTicketWinner(vrfout, mbi.MinerPower, mbi.NetworkPower) {
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
return &ProofInput{
|
||||
sectors: sinfos,
|
||||
hvrf: hvrf[:],
|
||||
winners: winners,
|
||||
vrfout: vrfout,
|
||||
}, nil
|
||||
return &types.ElectionProof{VRFProof: vrfout}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (*types.EPostProof, error) {
|
||||
proof, err := epp.ComputeProof(ctx, pi.sectors, pi.hvrf, pi.winners)
|
||||
if err != nil {
|
||||
@ -592,6 +585,7 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
|
||||
|
||||
return &ept, nil
|
||||
}
|
||||
*/
|
||||
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
|
||||
|
@ -252,11 +252,8 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys
|
||||
}
|
||||
|
||||
b := &types.BlockHeader{
|
||||
Miner: builtin.SystemActorAddr,
|
||||
Ticket: genesisticket,
|
||||
EPostProof: types.EPostProof{
|
||||
PostRand: []byte("i guess this is kinda random"),
|
||||
},
|
||||
Miner: builtin.SystemActorAddr,
|
||||
Ticket: genesisticket,
|
||||
Parents: []cid.Cid{},
|
||||
Height: 0,
|
||||
ParentWeight: types.NewInt(0),
|
||||
@ -266,6 +263,12 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys
|
||||
BLSAggregate: nil,
|
||||
BlockSig: nil,
|
||||
Timestamp: template.Timestamp,
|
||||
BeaconEntries: []types.BeaconEntry{
|
||||
{
|
||||
Round: 0,
|
||||
Data: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
sb, err := b.ToStorageBlock()
|
||||
|
@ -264,8 +264,8 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
|
||||
// TODO: copied from actors test harness, deduplicate or remove from here
|
||||
type fakeRand struct{}
|
||||
|
||||
func (fr *fakeRand) GetRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch int64, entropy []byte) ([]byte, error) {
|
||||
func (fr *fakeRand) GetRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
out := make([]byte, 32)
|
||||
rand.New(rand.NewSource(randEpoch)).Read(out)
|
||||
_, _ = rand.New(rand.NewSource(int64(randEpoch))).Read(out)
|
||||
return out, nil
|
||||
}
|
||||
|
@ -5,14 +5,13 @@ import (
|
||||
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -20,24 +19,33 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
)
|
||||
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, timestamp uint64) (*types.FullBlock, error) {
|
||||
st, recpts, err := sm.TipSetState(ctx, parents)
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) {
|
||||
|
||||
pts, err := sm.ChainStore().LoadTipSet(bt.Parents)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load parent tipset: %w", err)
|
||||
}
|
||||
|
||||
st, recpts, err := sm.TipSetState(ctx, pts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
||||
}
|
||||
|
||||
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, miner)
|
||||
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, bt.Miner)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
||||
}
|
||||
|
||||
next := &types.BlockHeader{
|
||||
Miner: miner,
|
||||
Parents: parents.Cids(),
|
||||
Ticket: ticket,
|
||||
Height: height,
|
||||
Timestamp: timestamp,
|
||||
EPostProof: *proof,
|
||||
Miner: bt.Miner,
|
||||
Parents: bt.Parents.Cids(),
|
||||
Ticket: bt.Ticket,
|
||||
ElectionProof: bt.Eproof,
|
||||
|
||||
BeaconEntries: bt.BeaconValues,
|
||||
Height: bt.Epoch,
|
||||
Timestamp: bt.Timestamp,
|
||||
//EPostProof: *proof,
|
||||
ParentStateRoot: st,
|
||||
ParentMessageReceipts: recpts,
|
||||
}
|
||||
@ -47,7 +55,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
|
||||
var blsMsgCids, secpkMsgCids []cid.Cid
|
||||
var blsSigs []crypto.Signature
|
||||
for _, msg := range msgs {
|
||||
for _, msg := range bt.Messages {
|
||||
if msg.Signature.Type == crypto.SigTypeBLS {
|
||||
blsSigs = append(blsSigs, msg.Signature)
|
||||
blsMessages = append(blsMessages, &msg.Message)
|
||||
@ -95,7 +103,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
}
|
||||
|
||||
next.BLSAggregate = aggSig
|
||||
pweight, err := sm.ChainStore().Weight(ctx, parents)
|
||||
pweight, err := sm.ChainStore().Weight(ctx, pts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
}
|
||||
|
||||
return []*types.SignedMessage{
|
||||
&types.SignedMessage{
|
||||
{
|
||||
Signature: *sig,
|
||||
Message: *m,
|
||||
},
|
||||
|
@ -189,7 +189,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
|
||||
Miner: b.Miner,
|
||||
Penalty: penalty,
|
||||
GasReward: gasReward,
|
||||
TicketCount: b.TicketCount,
|
||||
TicketCount: 1, // TODO: no longer need ticket count here.
|
||||
})
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to serialize award params: %w", err)
|
||||
@ -314,7 +314,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
Miner: b.Miner,
|
||||
BlsMessages: make([]types.ChainMsg, 0, len(bms)),
|
||||
SecpkMessages: make([]types.ChainMsg, 0, len(sms)),
|
||||
TicketCount: int64(len(b.EPostProof.Proofs)),
|
||||
TicketCount: 1, //int64(len(b.EPostProof.Proofs)), // TODO fix this
|
||||
}
|
||||
|
||||
for _, m := range bms {
|
||||
|
@ -2,6 +2,7 @@ package stmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
@ -418,11 +419,17 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, tsk types.TipSetKey
|
||||
return nil, xerrors.Errorf("failed to get miner sector size: %w", err)
|
||||
}
|
||||
|
||||
prev, err := sm.ChainStore().GetLatestBeaconEntry(ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get latest beacon entry: %w", err)
|
||||
}
|
||||
|
||||
return &api.MiningBaseInfo{
|
||||
MinerPower: mpow,
|
||||
NetworkPower: tpow,
|
||||
Sectors: provset,
|
||||
Worker: worker,
|
||||
SectorSize: ssize,
|
||||
MinerPower: mpow,
|
||||
NetworkPower: tpow,
|
||||
Sectors: provset,
|
||||
Worker: worker,
|
||||
SectorSize: ssize,
|
||||
PrevBeaconEntry: *prev,
|
||||
}, nil
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/trace"
|
||||
"go.uber.org/multierr"
|
||||
"go.uber.org/zap"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
|
||||
@ -892,12 +893,13 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
||||
return NewFullTipSet(out), nil
|
||||
}
|
||||
|
||||
func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int64, 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()
|
||||
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
}
|
||||
VRFDigest := blake2b.Sum256(t.VRFProof)
|
||||
VRFDigest := blake2b.Sum256(rbase)
|
||||
h.Write(VRFDigest[:])
|
||||
if err := binary.Write(h, binary.BigEndian, round); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
@ -907,17 +909,14 @@ func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int6
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round int64, entropy []byte) (out []byte, err error) {
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (out []byte, err error) {
|
||||
_, span := trace.StartSpan(ctx, "store.GetRandomness")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("round", round))
|
||||
|
||||
/*
|
||||
defer func() {
|
||||
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
|
||||
}()
|
||||
*/
|
||||
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
|
||||
|
||||
//defer func() {
|
||||
//log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
|
||||
//}()
|
||||
for {
|
||||
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
||||
if err != nil {
|
||||
@ -928,8 +927,8 @@ 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 {
|
||||
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, entropy)
|
||||
if nts.Height() <= round || mtb.Height == 0 {
|
||||
return DrawRandomness(nts.MinTicketBlock().Ticket.VRFProof, pers, round, entropy)
|
||||
}
|
||||
|
||||
blks = mtb.Parents
|
||||
@ -1091,6 +1090,28 @@ func (cs *ChainStore) Import(r io.Reader) (*types.TipSet, error) {
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetLatestBeaconEntry(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 := cs.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")
|
||||
}
|
||||
|
||||
type chainRand struct {
|
||||
cs *ChainStore
|
||||
blks []cid.Cid
|
||||
@ -1105,7 +1126,7 @@ func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight abi.ChainEpoch) vm.Ran
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, pers, round, entropy)
|
||||
}
|
||||
|
||||
|
195
chain/sync.go
195
chain/sync.go
@ -18,7 +18,6 @@ import (
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/libp2p/go-libp2p-core/connmgr"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/minio/blake2b-simd"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"github.com/whyrusleeping/pubsub"
|
||||
"go.opencensus.io/stats"
|
||||
@ -28,7 +27,6 @@ import (
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
"github.com/filecoin-project/go-address"
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
@ -36,6 +34,7 @@ import (
|
||||
|
||||
"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/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
@ -44,7 +43,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
||||
)
|
||||
|
||||
var log = logging.Logger("chain")
|
||||
@ -55,6 +53,9 @@ type Syncer struct {
|
||||
// The interface for accessing and putting tipsets into local storage
|
||||
store *store.ChainStore
|
||||
|
||||
// handle to the random beacon for verification
|
||||
beacon beacon.RandomBeacon
|
||||
|
||||
// the state manager handles making state queries
|
||||
sm *stmgr.StateManager
|
||||
|
||||
@ -78,7 +79,7 @@ type Syncer struct {
|
||||
receiptTracker *blockReceiptTracker
|
||||
}
|
||||
|
||||
func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, connmgr connmgr.ConnManager, self peer.ID) (*Syncer, error) {
|
||||
func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, connmgr connmgr.ConnManager, self peer.ID, beacon beacon.RandomBeacon) (*Syncer, error) {
|
||||
gen, err := sm.ChainStore().GetGenesis()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -90,6 +91,7 @@ func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, connmgr connm
|
||||
}
|
||||
|
||||
s := &Syncer{
|
||||
beacon: beacon,
|
||||
bad: NewBadBlockCache(),
|
||||
Genesis: gent,
|
||||
Bsync: bsync,
|
||||
@ -506,6 +508,13 @@ 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.store.GetLatestBeaconEntry(baseTs)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get latest beacon entry: %w", err)
|
||||
}
|
||||
|
||||
//nulls := h.Height - (baseTs.Height() + 1)
|
||||
|
||||
// fast checks first
|
||||
if h.BlockSig == nil {
|
||||
return xerrors.Errorf("block had nil signature")
|
||||
@ -526,46 +535,6 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height(), diff)
|
||||
}
|
||||
|
||||
winnerCheck := async.Err(func() error {
|
||||
slashed, err := stmgr.GetMinerSlashed(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to check if block miner was slashed: %w", err)
|
||||
}
|
||||
|
||||
if slashed {
|
||||
return xerrors.Errorf("received block was from slashed or invalid miner")
|
||||
}
|
||||
|
||||
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed getting power: %w", err)
|
||||
}
|
||||
|
||||
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get sector size for block miner: %w", err)
|
||||
}
|
||||
|
||||
snum := types.BigDiv(mpow, types.NewInt(uint64(ssize)))
|
||||
|
||||
if len(h.EPostProof.Candidates) == 0 {
|
||||
return xerrors.Errorf("no candidates")
|
||||
}
|
||||
|
||||
wins := make(map[uint64]bool)
|
||||
for _, t := range h.EPostProof.Candidates {
|
||||
if wins[t.ChallengeIndex] {
|
||||
return xerrors.Errorf("block had duplicate epost candidates")
|
||||
}
|
||||
wins[t.ChallengeIndex] = true
|
||||
|
||||
if !types.IsTicketWinner(t.Partial, ssize, snum.Uint64(), tpow) {
|
||||
return xerrors.Errorf("miner created a block but was not a winner")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
msgsCheck := async.Err(func() error {
|
||||
if err := syncer.checkBlockMessages(ctx, b, baseTs); err != nil {
|
||||
return xerrors.Errorf("block had invalid messages: %w", err)
|
||||
@ -610,6 +579,50 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("GetMinerWorkerRaw failed: %w", err)
|
||||
}
|
||||
|
||||
winnerCheck := async.Err(func() error {
|
||||
rBeacon := *prevBeacon
|
||||
if len(h.BeaconEntries) != 0 {
|
||||
rBeacon = h.BeaconEntries[len(h.BeaconEntries)-1]
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if err := h.Miner.MarshalCBOR(buf); err != nil {
|
||||
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, 17, h.Height, buf.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not draw randomness: %w", err)
|
||||
}
|
||||
|
||||
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.ElectionProof.VRFProof)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("validating block election proof failed: %w", err)
|
||||
}
|
||||
|
||||
slashed, err := stmgr.GetMinerSlashed(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to check if block miner was slashed: %w", err)
|
||||
}
|
||||
|
||||
if slashed {
|
||||
return xerrors.Errorf("received block was from slashed or invalid miner")
|
||||
}
|
||||
|
||||
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed getting power: %w", err)
|
||||
}
|
||||
|
||||
if !types.IsTicketWinner(h.ElectionProof.VRFProof, mpow, tpow) {
|
||||
return xerrors.Errorf("miner created a block but was not a winner")
|
||||
}
|
||||
|
||||
log.Warn("TODO: validate winning post proof") // TODO: validate winning post proof
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
blockSigCheck := async.Err(func() error {
|
||||
if err := sigs.CheckBlockSignature(h, ctx, waddr); err != nil {
|
||||
return xerrors.Errorf("check block signature failed: %w", err)
|
||||
@ -617,14 +630,23 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return nil
|
||||
})
|
||||
|
||||
beaconValuesCheck := async.Err(func() error {
|
||||
if err := beacon.ValidateBlockValues(syncer.beacon, h, *prevBeacon); err != nil {
|
||||
return xerrors.Errorf("failed to validate blocks random beacon values: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_TicketProduction, int64(h.Height)-1, buf.Bytes())
|
||||
|
||||
vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(),
|
||||
crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
||||
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
|
||||
}
|
||||
|
||||
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.Ticket.VRFProof)
|
||||
@ -634,18 +656,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,
|
||||
eproofCheck,
|
||||
beaconValuesCheck,
|
||||
//eproofCheck,
|
||||
winnerCheck,
|
||||
msgsCheck,
|
||||
}
|
||||
@ -677,6 +700,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return merr
|
||||
}
|
||||
|
||||
/*
|
||||
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, waddr address.Address) error {
|
||||
curTs, err := types.NewTipSet([]*types.BlockHeader{h})
|
||||
if err != nil {
|
||||
@ -687,7 +711,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)
|
||||
}
|
||||
@ -778,6 +802,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
|
||||
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
|
||||
{
|
||||
@ -942,15 +967,50 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
|
||||
trace.Int64Attribute("toHeight", int64(to.Height())),
|
||||
)
|
||||
|
||||
markBad := func(fmts string, args ...interface{}) {
|
||||
for _, b := range from.Cids() {
|
||||
syncer.bad.Add(b, fmt.Sprintf(fmts, args...))
|
||||
}
|
||||
}
|
||||
|
||||
for _, pcid := range from.Parents().Cids() {
|
||||
if reason, ok := syncer.bad.Has(pcid); ok {
|
||||
for _, b := range from.Cids() {
|
||||
syncer.bad.Add(b, fmt.Sprintf("linked to %s", pcid))
|
||||
}
|
||||
markBad("linked to %s", pcid)
|
||||
return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), pcid, reason)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// ensure consistency of beacon entires
|
||||
targetBE := from.Blocks()[0].BeaconEntries
|
||||
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].Round
|
||||
|
||||
for _, e := range targetBE[1:] {
|
||||
if cur >= e.Round {
|
||||
syncer.bad.Add(from.Cids()[0], "wrong order of beacon entires")
|
||||
return nil, xerrors.Errorf("wrong order of beacon entires")
|
||||
}
|
||||
|
||||
}
|
||||
for _, bh := range from.Blocks()[1:] {
|
||||
if len(targetBE) != len(bh.BeaconEntries) {
|
||||
// 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].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")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
blockSet := []*types.TipSet{from}
|
||||
|
||||
at := from.Parents()
|
||||
@ -1279,3 +1339,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")
|
||||
}
|
||||
|
@ -22,16 +22,13 @@ type Ticket struct {
|
||||
VRFProof []byte
|
||||
}
|
||||
|
||||
type EPostTicket struct {
|
||||
Partial []byte
|
||||
SectorID abi.SectorNumber
|
||||
ChallengeIndex uint64
|
||||
type ElectionProof struct {
|
||||
VRFProof []byte
|
||||
}
|
||||
|
||||
type EPostProof struct {
|
||||
Proofs []abi.PoStProof
|
||||
PostRand []byte
|
||||
Candidates []EPostTicket
|
||||
type BeaconEntry struct {
|
||||
Round uint64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type BlockHeader struct {
|
||||
@ -39,7 +36,9 @@ type BlockHeader struct {
|
||||
|
||||
Ticket *Ticket // 1
|
||||
|
||||
EPostProof EPostProof // 2
|
||||
ElectionProof *ElectionProof
|
||||
|
||||
BeaconEntries []BeaconEntry
|
||||
|
||||
Parents []cid.Cid // 3
|
||||
|
||||
@ -166,53 +165,32 @@ 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(vrfTicket []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)
|
||||
h := sha256.Sum256(vrfTicket)
|
||||
|
||||
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?
|
||||
return lhs.Cmp(rhs) < 0
|
||||
}
|
||||
|
||||
func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 {
|
||||
if sectors-faults == 0 {
|
||||
return 0
|
||||
}
|
||||
// ceil(sectors / SectorChallengeRatioDiv)
|
||||
return (sectors-faults-1)/build.SectorChallengeRatioDiv + 1
|
||||
}
|
||||
|
||||
func (t *Ticket) Equals(ot *Ticket) bool {
|
||||
return bytes.Equal(t.VRFProof, ot.VRFProof)
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
)
|
||||
@ -27,13 +26,12 @@ func testBlockHeader(t testing.TB) *BlockHeader {
|
||||
|
||||
return &BlockHeader{
|
||||
Miner: addr,
|
||||
EPostProof: EPostProof{
|
||||
Proofs: []abi.PoStProof{{ProofBytes: []byte("pruuf")}},
|
||||
PostRand: []byte("random"),
|
||||
},
|
||||
Ticket: &Ticket{
|
||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||
},
|
||||
ElectionProof: &ElectionProof{
|
||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||
},
|
||||
Parents: []cid.Cid{c, c},
|
||||
ParentMessageReceipts: c,
|
||||
BLSAggregate: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
|
||||
|
@ -21,7 +21,7 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write([]byte{141}); err != nil {
|
||||
if _, err := w.Write([]byte{142}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -35,11 +35,25 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.EPostProof (types.EPostProof) (struct)
|
||||
if err := t.EPostProof.MarshalCBOR(w); err != nil {
|
||||
// t.ElectionProof (types.ElectionProof) (struct)
|
||||
if err := t.ElectionProof.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.BeaconEntries ([]types.BeaconEntry) (slice)
|
||||
if len(t.BeaconEntries) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.BeaconEntries was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.BeaconEntries)))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.BeaconEntries {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.Parents ([]cid.Cid) (slice)
|
||||
if len(t.Parents) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Parents was too long")
|
||||
@ -124,7 +138,7 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 13 {
|
||||
if extra != 14 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
@ -158,15 +172,54 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
}
|
||||
// t.EPostProof (types.EPostProof) (struct)
|
||||
// t.ElectionProof (types.ElectionProof) (struct)
|
||||
|
||||
{
|
||||
|
||||
if err := t.EPostProof.UnmarshalCBOR(br); err != nil {
|
||||
return xerrors.Errorf("unmarshaling t.EPostProof: %w", err)
|
||||
pb, err := br.PeekByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pb == cbg.CborNull[0] {
|
||||
var nbuf [1]byte
|
||||
if _, err := br.Read(nbuf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
t.ElectionProof = new(ElectionProof)
|
||||
if err := t.ElectionProof.UnmarshalCBOR(br); err != nil {
|
||||
return xerrors.Errorf("unmarshaling t.ElectionProof pointer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// t.BeaconEntries ([]types.BeaconEntry) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.BeaconEntries: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.BeaconEntries = make([]BeaconEntry, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v BeaconEntry
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.BeaconEntries[i] = v
|
||||
}
|
||||
|
||||
// t.Parents ([]cid.Cid) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
@ -394,58 +447,30 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostProof) MarshalCBOR(w io.Writer) error {
|
||||
func (t *ElectionProof) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write([]byte{131}); err != nil {
|
||||
if _, err := w.Write([]byte{129}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Proofs ([]abi.PoStProof) (slice)
|
||||
if len(t.Proofs) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Proofs was too long")
|
||||
// t.VRFProof ([]uint8) (slice)
|
||||
if len(t.VRFProof) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.VRFProof was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Proofs)))); err != nil {
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.VRFProof)))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Proofs {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.PostRand ([]uint8) (slice)
|
||||
if len(t.PostRand) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.PostRand was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil {
|
||||
if _, err := w.Write(t.VRFProof); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(t.PostRand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Candidates ([]types.EPostTicket) (slice)
|
||||
if len(t.Candidates) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Candidates was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Candidates {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
|
||||
func (t *ElectionProof) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
@ -456,38 +481,11 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 3 {
|
||||
if extra != 1 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Proofs ([]abi.PoStProof) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Proofs: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.Proofs = make([]abi.PoStProof, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v abi.PoStProof
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Proofs[i] = v
|
||||
}
|
||||
|
||||
// t.PostRand ([]uint8) (slice)
|
||||
// t.VRFProof ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
@ -495,141 +493,15 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.PostRand: byte array too large (%d)", extra)
|
||||
return fmt.Errorf("t.VRFProof: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
t.PostRand = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.PostRand); err != nil {
|
||||
t.VRFProof = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.VRFProof); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.Candidates ([]types.EPostTicket) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Candidates: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.Candidates = make([]EPostTicket, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v EPostTicket
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Candidates[i] = v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostTicket) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write([]byte{131}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Partial ([]uint8) (slice)
|
||||
if len(t.Partial) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Partial was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Partial)))); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(t.Partial); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.SectorID (abi.SectorNumber) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.ChallengeIndex (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ChallengeIndex))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostTicket) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 3 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Partial ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Partial: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
t.Partial = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.Partial); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.SectorID (abi.SectorNumber) (uint64)
|
||||
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.SectorID = abi.SectorNumber(extra)
|
||||
|
||||
}
|
||||
// t.ChallengeIndex (uint64) (uint64)
|
||||
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.ChallengeIndex = uint64(extra)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1455,3 +1327,81 @@ func (t *ExpTipSet) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *BeaconEntry) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write([]byte{130}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Round (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Round))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Data ([]uint8) (slice)
|
||||
if len(t.Data) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Data was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Data)))); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(t.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *BeaconEntry) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 2 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Round (uint64) (uint64)
|
||||
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Round = uint64(extra)
|
||||
|
||||
}
|
||||
// t.Data ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Data: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
t.Data = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -60,8 +60,8 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
||||
|
||||
return &types.BlockHeader{
|
||||
Miner: addr,
|
||||
EPostProof: types.EPostProof{
|
||||
Proofs: []abi.PoStProof{{ProofBytes: []byte("election post proof proof")}},
|
||||
ElectionProof: &types.ElectionProof{
|
||||
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
|
||||
},
|
||||
Ticket: &types.Ticket{
|
||||
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
|
||||
|
@ -2,6 +2,7 @@ package validation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
@ -101,15 +102,15 @@ type randWrapper struct {
|
||||
rnd vstate.RandomnessSource
|
||||
}
|
||||
|
||||
func (w *randWrapper) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
|
||||
return w.rnd.Randomness(ctx, pers, abi.ChainEpoch(round), entropy)
|
||||
func (w *randWrapper) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
return w.rnd.Randomness(ctx, pers, round, entropy)
|
||||
}
|
||||
|
||||
type vmRand struct {
|
||||
eCtx *vtypes.ExecutionContext
|
||||
}
|
||||
|
||||
func (*vmRand) GetRandomness(ctx context.Context, dst crypto.DomainSeparationTag, h int64, input []byte) ([]byte, error) {
|
||||
func (*vmRand) GetRandomness(ctx context.Context, dst crypto.DomainSeparationTag, h abi.ChainEpoch, input []byte) ([]byte, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ func LoadVector(t *testing.T, f string, out interface{}) {
|
||||
}
|
||||
|
||||
func TestBlockHeaderVectors(t *testing.T) {
|
||||
t.Skip("we need to regenerate for beacon")
|
||||
var headers []HeaderVector
|
||||
LoadVector(t, "block_headers.json", &headers)
|
||||
|
||||
|
@ -151,7 +151,7 @@ func (rs *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool)
|
||||
}
|
||||
|
||||
func (rt *Runtime) GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
|
||||
res, err := rt.vm.rand.GetRandomness(rt.ctx, personalization, int64(randEpoch), entropy)
|
||||
res, err := rt.vm.rand.GetRandomness(rt.ctx, personalization, randEpoch, entropy)
|
||||
if err != nil {
|
||||
panic(aerrors.Fatalf("could not get randomness: %s", err))
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, maddr address.Address, c
|
||||
}
|
||||
|
||||
type Rand interface {
|
||||
GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error)
|
||||
GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
type ApplyRet struct {
|
||||
|
@ -70,12 +70,7 @@ create table if not exists blocks
|
||||
miner text not null,
|
||||
timestamp bigint not null,
|
||||
vrfproof bytea,
|
||||
tickets bigint not null,
|
||||
eprof bytea,
|
||||
prand bytea,
|
||||
ep0partial bytea,
|
||||
ep0sector numeric not null,
|
||||
ep0challangei numeric not null
|
||||
);
|
||||
|
||||
create unique index if not exists block_cid_uindex
|
||||
@ -564,16 +559,12 @@ create temp table c (like blocks_challenges excluding constraints) on commit dro
|
||||
}
|
||||
}
|
||||
|
||||
stmt2, err := tx.Prepare(`copy b (cid, parentWeight, parentStateRoot, height, miner, "timestamp", vrfproof, tickets, prand, ep0partial, ep0sector, ep0challangei) from stdin`)
|
||||
stmt2, err := tx.Prepare(`copy b (cid, parentWeight, parentStateRoot, height, miner, "timestamp", vrfproof) from stdin`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, bh := range bhs {
|
||||
l := len(bh.EPostProof.Candidates)
|
||||
if len(bh.EPostProof.Candidates) == 0 {
|
||||
bh.EPostProof.Candidates = append(bh.EPostProof.Candidates, types.EPostTicket{})
|
||||
}
|
||||
|
||||
if _, err := stmt2.Exec(
|
||||
bh.Cid().String(),
|
||||
@ -582,13 +573,7 @@ create temp table c (like blocks_challenges excluding constraints) on commit dro
|
||||
bh.Height,
|
||||
bh.Miner.String(),
|
||||
bh.Timestamp,
|
||||
bh.Ticket.VRFProof,
|
||||
l,
|
||||
//bh.EPostProof.Proof,
|
||||
bh.EPostProof.PostRand,
|
||||
bh.EPostProof.Candidates[0].Partial,
|
||||
bh.EPostProof.Candidates[0].SectorID,
|
||||
bh.EPostProof.Candidates[0].ChallengeIndex); err != nil {
|
||||
bh.Ticket.VRFProof); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
@ -601,36 +586,6 @@ create temp table c (like blocks_challenges excluding constraints) on commit dro
|
||||
return xerrors.Errorf("blk put: %w", err)
|
||||
}
|
||||
|
||||
stmt3, err := tx.Prepare(`copy c (block, index, sector_id, partial, candidate) from stdin`)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("s3 create: %w", err)
|
||||
}
|
||||
for _, bh := range bhs {
|
||||
for index, c := range bh.EPostProof.Candidates {
|
||||
if _, err := stmt3.Exec(
|
||||
bh.Cid().String(),
|
||||
index,
|
||||
c.SectorID,
|
||||
c.Partial,
|
||||
c.ChallengeIndex); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := stmt3.Close(); err != nil {
|
||||
return xerrors.Errorf("s2 close: %w", err)
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(`insert into blocks_challenges select * from c on conflict do nothing `); err != nil {
|
||||
return xerrors.Errorf("blk put: %w", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("commit: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/google/uuid"
|
||||
@ -37,6 +38,7 @@ import (
|
||||
lapi "github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
@ -435,7 +437,9 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
|
||||
}
|
||||
epp := storage.NewElectionPoStProver(smgr, dtypes.MinerID(mid))
|
||||
|
||||
m := miner.NewMiner(api, epp)
|
||||
beacon := beacon.NewMockBeacon(build.BlockDelay * time.Second)
|
||||
|
||||
m := miner.NewMiner(api, epp, beacon)
|
||||
{
|
||||
if err := m.Register(a); err != nil {
|
||||
return xerrors.Errorf("failed to start up genesis miner: %w", err)
|
||||
|
@ -4,12 +4,12 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
lapi "github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -67,37 +67,13 @@ func init() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
epostp := &types.EPostProof{
|
||||
Proofs: []abi.PoStProof{{ProofBytes: []byte("valid proof")}},
|
||||
Candidates: []types.EPostTicket{
|
||||
{
|
||||
ChallengeIndex: 0,
|
||||
SectorID: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
{
|
||||
r, err := api.ChainGetRandomness(ctx, head.Key(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, (head.Height()+1)-build.EcRandomnessLookback, addr.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("chain get randomness: %w", err)
|
||||
}
|
||||
mworker, err := api.StateMinerWorker(ctx, addr, head.Key())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := gen.ComputeVRF(ctx, api.WalletSign, mworker, r)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
}
|
||||
epostp.PostRand = vrfout
|
||||
}
|
||||
// TODO: beacon
|
||||
|
||||
uts := head.MinTimestamp() + uint64(build.BlockDelay)
|
||||
nheight := head.Height() + 1
|
||||
blk, err := api.MinerCreateBlock(ctx, addr, head.Key(), ticket, epostp, msgs, nheight, uts)
|
||||
blk, err := api.MinerCreateBlock(ctx, &lapi.BlockTemplate{
|
||||
addr, head.Key(), ticket, nil, nil, msgs, nheight, uts,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("creating block: %w", err)
|
||||
}
|
||||
|
2
extern/filecoin-ffi
vendored
2
extern/filecoin-ffi
vendored
@ -1 +1 @@
|
||||
Subproject commit 0a1990fdd9a08b122cf97b373413b688d5b429cf
|
||||
Subproject commit e899cc1dd0720e0a4d25b0e751b84e3733cbedc5
|
14
gen/main.go
14
gen/main.go
@ -11,15 +11,13 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/hello"
|
||||
"github.com/filecoin-project/lotus/paychmgr"
|
||||
sealing "github.com/filecoin-project/storage-fsm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types",
|
||||
types.BlockHeader{},
|
||||
types.Ticket{},
|
||||
types.EPostProof{},
|
||||
types.EPostTicket{},
|
||||
types.ElectionProof{},
|
||||
types.Message{},
|
||||
types.SignedMessage{},
|
||||
types.MsgMeta{},
|
||||
@ -27,6 +25,7 @@ func main() {
|
||||
types.MessageReceipt{},
|
||||
types.BlockMsg{},
|
||||
types.ExpTipSet{},
|
||||
types.BeaconEntry{},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
@ -73,13 +72,4 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = gen.WriteMapEncodersToFile("./storage/sealing/cbor_gen.go", "sealing",
|
||||
sealing.Piece{},
|
||||
sealing.SectorInfo{},
|
||||
sealing.Log{},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -11,6 +11,7 @@ require (
|
||||
github.com/coreos/go-systemd/v22 v22.0.0
|
||||
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f // indirect
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/drand/drand v0.5.4
|
||||
github.com/filecoin-project/chain-validation v0.0.6-0.20200331143132-15970e639ac2
|
||||
github.com/filecoin-project/filecoin-ffi v0.0.0-20200326153646-e899cc1dd072
|
||||
github.com/filecoin-project/go-address v0.0.2-0.20200218010043-eb9bb40ed5be
|
||||
|
65
go.sum
65
go.sum
@ -32,9 +32,12 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5Vpd
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
||||
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/benbjohnson/clock v1.0.0 h1:78Jk/r6m4wCi6sndMpty7A//t4dw/RW5fV4ZgDVfX1w=
|
||||
github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||
@ -52,11 +55,14 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa
|
||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@ -83,6 +89,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f h1:BOaYiTvg8p9vBUXpklC22XSK/mifLF7lG9jtmYYi3Tc=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||
github.com/dchest/blake2b v1.0.0 h1:KK9LimVmE0MjRl9095XJmKqZ+iLxWATvlcpVFRtaw6s=
|
||||
github.com/dchest/blake2b v1.0.0/go.mod h1:U034kXgbJpCle2wSk5ybGIVhOSHCVLMDqOzcPEA0F7s=
|
||||
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
|
||||
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgraph-io/badger v1.6.0 h1:DshxFxZWXUcO0xX476VJC07Xsr6ZCBVRHKZ93Oh7Evo=
|
||||
@ -96,6 +104,13 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczC
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/drand/bls12-381 v0.0.0-20200110233355-faca855b3a67 h1:+zwFBPeS6Tx0ShngG44wyJ8wBh8ENK9upPxN2fE58Uc=
|
||||
github.com/drand/bls12-381 v0.0.0-20200110233355-faca855b3a67/go.mod h1:HRtP9ULniFcAfoXvSrD5Kebk1e3/g4cvtBfjlT80PuQ=
|
||||
github.com/drand/drand v0.5.4 h1:DyCkE4YHy1klVtu0YgYiYtsryyzyc0x6Y78HM2C9Mws=
|
||||
github.com/drand/drand v0.5.4/go.mod h1:n9JV/s1TIL/kx/4002pct7qjilbdzScQKVu05IfHf8c=
|
||||
github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw=
|
||||
github.com/drand/kyber v1.0.1-0.20200128205555-52819dbafde7 h1:ItV7+85W8JU5bQd/DxjT9y5Khsetlrp9CErHvDtYlE4=
|
||||
github.com/drand/kyber v1.0.1-0.20200128205555-52819dbafde7/go.mod h1:Rzu9PGFt3q8d7WWdrHmR8dktHucO0dSTWlMYrgqjSpA=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
@ -105,6 +120,8 @@ github.com/elastic/go-sysinfo v1.3.0 h1:eb2XFGTMlSwG/yyU9Y8jVAYLIzU2sFzWXwo2gmet
|
||||
github.com/elastic/go-sysinfo v1.3.0/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0=
|
||||
github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY=
|
||||
github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY=
|
||||
github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8=
|
||||
@ -165,9 +182,14 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 h1:EzDjxMg43q1tA2c0MV3tNbaontnHLplHyFF6M5KiVP0=
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1/go.mod h1:0eHX/BVySxPc6SE2mZRoppGq7qcEagxdmQnA3dzork8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
@ -179,6 +201,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -214,6 +237,8 @@ github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.12.1 h1:zCy2xE9ablevUOrUZc3Dl72Dt+ya2FNAvC2yLYMHzi4=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
|
||||
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
|
||||
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
|
||||
github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE=
|
||||
@ -407,7 +432,10 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3 h1:Iy7Ifq2ysilWU4QlCx/97OoI4xT1IV7i8byT/EyIT/M=
|
||||
github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU=
|
||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
|
||||
github.com/kilic/bls12-381 v0.0.0-20191103193557-038659eaa189/go.mod h1:INznczsRc7ASFbWFUI9GnIvpi9s2FhenKE+24rdTmBQ=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
@ -707,6 +735,10 @@ github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS
|
||||
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
|
||||
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c h1:5bFTChQxSKNwy8ALwOebjekYExl9HTT9urdawqC95tA=
|
||||
github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c/go.mod h1:7qN3Y0BvzRUf4LofcoJplQL10lsFDb4PYlePTVwrP28=
|
||||
github.com/nikkolasg/slog v0.0.0-20170921200349-3c8d441d7a1e h1:07zdEcJ4Fble5uWsqKpjW19699kQWRLXP+RZh1a6ZRg=
|
||||
github.com/nikkolasg/slog v0.0.0-20170921200349-3c8d441d7a1e/go.mod h1:79GLCU4P87rYvYYACbNwVyc1WmRvkwQbYnybpCmRXzg=
|
||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=
|
||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@ -751,6 +783,8 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
@ -761,6 +795,7 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R
|
||||
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0 h1:c8R11WC8m7KNMkTv/0+Be8vvwo4I3/Ut9AC2FW8fX3U=
|
||||
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
@ -782,6 +817,8 @@ github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:s
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY=
|
||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
|
||||
@ -807,6 +844,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg=
|
||||
github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
@ -855,6 +894,14 @@ github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJ
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
|
||||
go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ=
|
||||
go.dedis.ch/kyber/v3 v3.0.9/go.mod h1:rhNjUUg6ahf8HEg5HUvVBYoWY4boAafX8tYxX+PS+qg=
|
||||
go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo=
|
||||
go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4=
|
||||
go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo=
|
||||
go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
@ -893,6 +940,7 @@ go4.org v0.0.0-20190313082347-94abd6928b1d/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@ -906,6 +954,7 @@ golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 h1:TjszyFsQsyZNHwdVdZ5m7bjmreu0znc2kRYsEml9/Ww=
|
||||
golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@ -940,6 +989,8 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
|
||||
golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@ -959,6 +1010,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -976,9 +1028,11 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d h1:62ap6LNOjDU6uGmKXHJbSfciMoV+FeI1sRXx/pLDL44=
|
||||
@ -998,6 +1052,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@ -1025,9 +1080,17 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24 h1:wDju+RU97qa0FZT0QnZDg9Uc2dH0Ql513kFvHocz+WM=
|
||||
google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
||||
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -1048,12 +1111,14 @@ gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0Y
|
||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
|
@ -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)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
"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/types"
|
||||
|
||||
@ -26,15 +27,16 @@ var log = logging.Logger("miner")
|
||||
|
||||
type waitFunc func(ctx context.Context, baseTime uint64) error
|
||||
|
||||
func NewMiner(api api.FullNode, epp gen.ElectionPoStProver) *Miner {
|
||||
func NewMiner(api api.FullNode, epp gen.ElectionPoStProver, beacon beacon.RandomBeacon) *Miner {
|
||||
arc, err := lru.NewARC(10000)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Miner{
|
||||
api: api,
|
||||
epp: epp,
|
||||
api: api,
|
||||
epp: epp,
|
||||
beacon: beacon,
|
||||
waitFunc: func(ctx context.Context, baseTime uint64) error {
|
||||
// Wait around for half the block time in case other parents come in
|
||||
deadline := baseTime + build.PropagationDelay
|
||||
@ -49,7 +51,8 @@ func NewMiner(api api.FullNode, epp gen.ElectionPoStProver) *Miner {
|
||||
type Miner struct {
|
||||
api api.FullNode
|
||||
|
||||
epp gen.ElectionPoStProver
|
||||
epp gen.ElectionPoStProver
|
||||
beacon beacon.RandomBeacon
|
||||
|
||||
lk sync.Mutex
|
||||
addresses []address.Address
|
||||
@ -291,6 +294,19 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids()))
|
||||
start := time.Now()
|
||||
|
||||
mbi, err := m.api.MinerGetBaseInfo(ctx, addr, base.ts.Key())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
|
||||
}
|
||||
|
||||
beaconPrev := mbi.PrevBeaconEntry
|
||||
|
||||
round := base.ts.Height() + base.nullRounds + 1
|
||||
bvals, err := beacon.BeaconEntriesForBlock(ctx, m.beacon, round, beaconPrev)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get beacon entries failed: %w", err)
|
||||
}
|
||||
|
||||
hasPower, err := m.hasPower(ctx, addr, base.ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("checking if miner is slashed: %w", err)
|
||||
@ -303,17 +319,22 @@ 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)
|
||||
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)
|
||||
}
|
||||
|
||||
proofin, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, m.api)
|
||||
winner, err := gen.IsRoundWinner(ctx, base.ts, round, addr, rbase, mbi, m.api)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
||||
}
|
||||
|
||||
if proofin == nil {
|
||||
if winner == nil {
|
||||
base.nullRounds++
|
||||
return nil, nil
|
||||
}
|
||||
@ -324,12 +345,8 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return nil, xerrors.Errorf("failed to get pending messages: %w", err)
|
||||
}
|
||||
|
||||
proof, err := gen.ComputeProof(ctx, m.epp, proofin)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("computing election proof: %w", err)
|
||||
}
|
||||
|
||||
b, err := m.createBlock(base, addr, ticket, proof, pending)
|
||||
// TODO: winning post proof
|
||||
b, err := m.createBlock(base, addr, ticket, winner, bvals, pending)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create block: %w", err)
|
||||
}
|
||||
@ -343,7 +360,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
|
||||
@ -353,8 +370,8 @@ 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 := m.api.ChainGetRandomness(ctx, base.ts.Key(), crypto.DomainSeparationTag_TicketProduction,
|
||||
base.ts.Height()+base.nullRounds+1-build.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -369,7 +386,8 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *M
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof, pending []*types.SignedMessage) (*types.BlockMsg, error) {
|
||||
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket,
|
||||
eproof *types.ElectionProof, bvals []types.BeaconEntry, pending []*types.SignedMessage) (*types.BlockMsg, error) {
|
||||
msgs, err := SelectMessages(context.TODO(), m.api.StateGetActor, base.ts, pending)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
||||
@ -385,7 +403,16 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
|
||||
nheight := base.ts.Height() + base.nullRounds + 1
|
||||
|
||||
// why even return this? that api call could just submit it for us
|
||||
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts.Key(), ticket, proof, msgs, nheight, uint64(uts))
|
||||
return m.api.MinerCreateBlock(context.TODO(), &api.BlockTemplate{
|
||||
Miner: addr,
|
||||
Parents: base.ts.Key(),
|
||||
Ticket: ticket,
|
||||
Eproof: eproof,
|
||||
BeaconValues: bvals,
|
||||
Messages: msgs,
|
||||
Epoch: nheight,
|
||||
Timestamp: uts,
|
||||
})
|
||||
}
|
||||
|
||||
type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)
|
||||
|
@ -23,11 +23,11 @@ func TestMessageFiltering(t *testing.T) {
|
||||
a2 := mustIDAddr(2)
|
||||
|
||||
actors := map[address.Address]*types.Actor{
|
||||
a1: &types.Actor{
|
||||
a1: {
|
||||
Nonce: 3,
|
||||
Balance: types.NewInt(1200),
|
||||
},
|
||||
a2: &types.Actor{
|
||||
a2: {
|
||||
Nonce: 1,
|
||||
Balance: types.NewInt(1000),
|
||||
},
|
||||
@ -38,7 +38,7 @@ func TestMessageFiltering(t *testing.T) {
|
||||
}
|
||||
|
||||
msgs := []types.Message{
|
||||
types.Message{
|
||||
{
|
||||
From: a1,
|
||||
To: a1,
|
||||
Nonce: 3,
|
||||
@ -46,7 +46,7 @@ func TestMessageFiltering(t *testing.T) {
|
||||
GasLimit: 50,
|
||||
GasPrice: types.NewInt(1),
|
||||
},
|
||||
types.Message{
|
||||
{
|
||||
From: a1,
|
||||
To: a1,
|
||||
Nonce: 4,
|
||||
@ -54,7 +54,7 @@ func TestMessageFiltering(t *testing.T) {
|
||||
GasLimit: 50,
|
||||
GasPrice: types.NewInt(1),
|
||||
},
|
||||
types.Message{
|
||||
{
|
||||
From: a2,
|
||||
To: a1,
|
||||
Nonce: 1,
|
||||
@ -62,7 +62,7 @@ func TestMessageFiltering(t *testing.T) {
|
||||
GasLimit: 100,
|
||||
GasPrice: types.NewInt(1),
|
||||
},
|
||||
types.Message{
|
||||
{
|
||||
From: a2,
|
||||
To: a1,
|
||||
Nonce: 0,
|
||||
@ -70,7 +70,7 @@ func TestMessageFiltering(t *testing.T) {
|
||||
GasLimit: 100,
|
||||
GasPrice: types.NewInt(1),
|
||||
},
|
||||
types.Message{
|
||||
{
|
||||
From: a2,
|
||||
To: a1,
|
||||
Nonce: 2,
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
@ -16,7 +17,9 @@ func NewTestMiner(nextCh <-chan struct{}, addr address.Address) func(api.FullNod
|
||||
panic(err)
|
||||
}
|
||||
|
||||
beacon := beacon.NewMockBeacon(0)
|
||||
m := &Miner{
|
||||
beacon: beacon,
|
||||
api: api,
|
||||
waitFunc: chanWaiter(nextCh),
|
||||
epp: epp,
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/market"
|
||||
@ -255,6 +256,7 @@ func Online() Option {
|
||||
Override(new(storagemarket.StorageClientNode), storageadapter.NewClientNodeAdapter),
|
||||
Override(RegisterClientValidatorKey, modules.RegisterClientValidator),
|
||||
Override(RunDealClientKey, modules.RunDealClient),
|
||||
Override(new(beacon.RandomBeacon), modules.RandomBeacon),
|
||||
|
||||
Override(new(*paychmgr.Store), paychmgr.NewStore),
|
||||
Override(new(*paychmgr.Manager), paychmgr.NewManager),
|
||||
|
@ -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) {
|
||||
|
@ -269,13 +269,8 @@ func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address,
|
||||
return stmgr.MinerGetBaseInfo(ctx, a.StateManager, tsk, maddr)
|
||||
}
|
||||
|
||||
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
parents, err := a.Chain.GetTipSetFromKey(parentsTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset %s: %w", parentsTSK, err)
|
||||
}
|
||||
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts)
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, bt *api.BlockTemplate) (*types.BlockMsg, error) {
|
||||
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, bt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
@ -141,8 +142,8 @@ func NetworkName(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore,
|
||||
return netName, err
|
||||
}
|
||||
|
||||
func NewSyncer(lc fx.Lifecycle, sm *stmgr.StateManager, bsync *blocksync.BlockSync, h host.Host) (*chain.Syncer, error) {
|
||||
syncer, err := chain.NewSyncer(sm, bsync, h.ConnManager(), h.ID())
|
||||
func NewSyncer(lc fx.Lifecycle, sm *stmgr.StateManager, bsync *blocksync.BlockSync, h host.Host, beacon beacon.RandomBeacon) (*chain.Syncer, error) {
|
||||
syncer, err := chain.NewSyncer(sm, bsync, h.ConnManager(), h.ID(), beacon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
eventbus "github.com/libp2p/go-eventbus"
|
||||
event "github.com/libp2p/go-libp2p-core/event"
|
||||
@ -16,6 +17,7 @@ import (
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/sub"
|
||||
@ -114,3 +116,7 @@ func NewLocalDiscovery(ds dtypes.MetadataDS) *discovery.Local {
|
||||
func RetrievalResolver(l *discovery.Local) retrievalmarket.PeerResolver {
|
||||
return discovery.Multi(l)
|
||||
}
|
||||
|
||||
func RandomBeacon() beacon.RandomBeacon {
|
||||
return beacon.NewMockBeacon(build.BlockDelay * time.Second)
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ import (
|
||||
|
||||
lapi "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/types"
|
||||
"github.com/filecoin-project/lotus/markets/retrievaladapter"
|
||||
@ -257,13 +258,13 @@ func StagingGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.Stagi
|
||||
return gs
|
||||
}
|
||||
|
||||
func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.ElectionPoStProver) (*miner.Miner, error) {
|
||||
func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.ElectionPoStProver, beacon beacon.RandomBeacon) (*miner.Miner, error) {
|
||||
minerAddr, err := minerAddrFromDS(ds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := miner.NewMiner(api, epp)
|
||||
m := miner.NewMiner(api, epp, beacon)
|
||||
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
|
Loading…
Reference in New Issue
Block a user