WIP: random beacon interface
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
7e96b15091
commit
7075eaba26
@ -73,7 +73,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, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
|
||||
|
||||
// // UX ?
|
||||
|
||||
|
@ -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, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*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, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, bvals []*types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, bvals, msgs, height, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
|
125
chain/beacon/beacon.go
Normal file
125
chain/beacon/beacon.go
Normal file
@ -0,0 +1,125 @@
|
||||
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/filecoin-project/specs-actors/actors/crypto"
|
||||
logging "github.com/ipfs/go-log"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/minio/blake2b-simd"
|
||||
)
|
||||
|
||||
var log = logging.Logger("beacon")
|
||||
|
||||
type Response struct {
|
||||
Entry *types.BeaconEntry
|
||||
Err error
|
||||
}
|
||||
|
||||
type DrandBeacon interface {
|
||||
RoundTime() time.Duration
|
||||
LastEntry() (*types.BeaconEntry, error)
|
||||
Entry(context.Context, uint64) <-chan Response
|
||||
VerifyEntry(*types.BeaconEntry) (bool, error)
|
||||
BeaconIndexesForEpoch(abi.ChainEpoch, int) []uint64
|
||||
}
|
||||
|
||||
func ValidateBlockValues(b DrandBeacon, h *types.BlockHeader, nulls int) error {
|
||||
indexes := b.BeaconIndexesForEpoch(h.Height, nulls)
|
||||
|
||||
if len(h.BeaconEntries) != len(indexes) {
|
||||
return xerrors.Errorf("incorrect number of beacon entries, exp:%d got:%d", len(indexes), len(h.BeaconEntries))
|
||||
}
|
||||
|
||||
for i, ix := range indexes {
|
||||
if h.BeaconEntries[i].Index != ix {
|
||||
return xerrors.Errorf("beacon entry at [%d] had wrong index, exp:%d got:%d", i, ix, h.BeaconEntries[i].Index)
|
||||
}
|
||||
if ok, err := b.VerifyEntry(h.BeaconEntries[i]); err != nil {
|
||||
return xerrors.Errorf("failed to verify beacon entry %d: %w", i, err)
|
||||
} else if !ok {
|
||||
return xerrors.Errorf("beacon entry %d was invalid", i)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func BeaconEntriesForBlock(ctx context.Context, beacon DrandBeacon, round abi.ChainEpoch, nulls int) ([]*types.BeaconEntry, error) {
|
||||
start := time.Now()
|
||||
|
||||
var out []*types.BeaconEntry
|
||||
for _, ei := range beacon.BeaconIndexesForEpoch(round, nulls) {
|
||||
rch := beacon.Entry(ctx, ei)
|
||||
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)
|
||||
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))
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type mockBeacon struct {
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
func NewMockBeacon(interval time.Duration) *mockBeacon {
|
||||
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{
|
||||
Index: index,
|
||||
Signature: crypto.Signature{Type: crypto.SigTypeBLS, 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(e *types.BeaconEntry) (bool, error) {
|
||||
oe := mb.entryForIndex(e.Index)
|
||||
return bytes.Equal(e.Signature.Data, oe.Signature.Data), nil
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) BeaconIndexesForEpoch(epoch abi.ChainEpoch, nulls int) []uint64 {
|
||||
var out []uint64
|
||||
for i := nulls; i > 0; i-- {
|
||||
out = append(out, uint64(epoch)-uint64(i))
|
||||
}
|
||||
out = append(out, uint64(epoch))
|
||||
return []uint64{uint64(epoch)}
|
||||
}
|
||||
|
||||
var _ DrandBeacon = (*mockBeacon)(nil)
|
@ -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"
|
||||
@ -27,6 +28,7 @@ import (
|
||||
|
||||
"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 +53,8 @@ type ChainGen struct {
|
||||
|
||||
cs *store.ChainStore
|
||||
|
||||
beacon beacon.DrandBeacon
|
||||
|
||||
sm *stmgr.StateManager
|
||||
|
||||
genesis *types.BlockHeader
|
||||
@ -211,12 +215,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,
|
||||
@ -346,7 +353,13 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
}
|
||||
|
||||
if proof != nil {
|
||||
fblk, err := cg.makeBlock(base, m, proof, t, abi.ChainEpoch(round), msgs)
|
||||
nulls := int(round) - int(base.Height()+1)
|
||||
bvals, err := beacon.BeaconEntriesForBlock(context.TODO(), cg.beacon, abi.ChainEpoch(round), nulls)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get beacon entries: %w", err)
|
||||
}
|
||||
|
||||
fblk, err := cg.makeBlock(base, m, proof, t, bvals, abi.ChainEpoch(round), msgs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
||||
}
|
||||
@ -368,7 +381,7 @@ 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, eproof *types.EPostProof, ticket *types.Ticket, bvals []*types.BeaconEntry, height abi.ChainEpoch, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
|
||||
var ts uint64
|
||||
if cg.Timestamper != nil {
|
||||
@ -377,7 +390,7 @@ 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, m, parents, ticket, eproof, bvals, msgs, height, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ 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) {
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, bvals []*types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, timestamp uint64) (*types.FullBlock, error) {
|
||||
st, recpts, err := sm.TipSetState(ctx, parents)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
||||
@ -35,6 +35,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
Miner: miner,
|
||||
Parents: parents.Cids(),
|
||||
Ticket: ticket,
|
||||
BeaconEntries: bvals,
|
||||
Height: height,
|
||||
Timestamp: timestamp,
|
||||
EPostProof: *proof,
|
||||
|
@ -36,6 +36,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"
|
||||
@ -55,6 +56,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.DrandBeacon
|
||||
|
||||
// the state manager handles making state queries
|
||||
sm *stmgr.StateManager
|
||||
|
||||
@ -78,7 +82,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.DrandBeacon) (*Syncer, error) {
|
||||
gen, err := sm.ChainStore().GetGenesis()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -90,6 +94,7 @@ func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, connmgr connm
|
||||
}
|
||||
|
||||
s := &Syncer{
|
||||
beacon: beacon,
|
||||
bad: NewBadBlockCache(),
|
||||
Genesis: gent,
|
||||
Bsync: bsync,
|
||||
@ -506,6 +511,8 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("load parent tipset failed (%s): %w", h.Parents, err)
|
||||
}
|
||||
|
||||
nulls := h.Height - (baseTs.Height() + 1)
|
||||
|
||||
// fast checks first
|
||||
if h.BlockSig == nil {
|
||||
return xerrors.Errorf("block had nil signature")
|
||||
@ -617,6 +624,13 @@ 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, int(nulls)); 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 {
|
||||
@ -645,6 +659,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
minerCheck,
|
||||
tktsCheck,
|
||||
blockSigCheck,
|
||||
beaconValuesCheck,
|
||||
eproofCheck,
|
||||
winnerCheck,
|
||||
msgsCheck,
|
||||
|
@ -34,6 +34,11 @@ type EPostProof struct {
|
||||
Candidates []EPostTicket
|
||||
}
|
||||
|
||||
type BeaconEntry struct {
|
||||
Index uint64
|
||||
Signature crypto.Signature
|
||||
}
|
||||
|
||||
type BlockHeader struct {
|
||||
Miner address.Address // 0
|
||||
|
||||
@ -41,6 +46,8 @@ type BlockHeader struct {
|
||||
|
||||
EPostProof EPostProof // 2
|
||||
|
||||
BeaconEntries []*BeaconEntry
|
||||
|
||||
Parents []cid.Cid // 3
|
||||
|
||||
ParentWeight BigInt // 4
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
@ -40,6 +40,20 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
||||
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")
|
||||
}
|
||||
|
||||
@ -167,6 +181,33 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
}
|
||||
// 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)
|
||||
@ -1455,3 +1496,66 @@ 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.Index (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Index))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Signature (crypto.Signature) (struct)
|
||||
if err := t.Signature.MarshalCBOR(w); 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.Index (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.Index = uint64(extra)
|
||||
|
||||
}
|
||||
// t.Signature (crypto.Signature) (struct)
|
||||
|
||||
{
|
||||
|
||||
if err := t.Signature.UnmarshalCBOR(br); err != nil {
|
||||
return xerrors.Errorf("unmarshaling t.Signature: %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)
|
||||
|
2
extern/filecoin-ffi
vendored
2
extern/filecoin-ffi
vendored
@ -1 +1 @@
|
||||
Subproject commit 0a1990fdd9a08b122cf97b373413b688d5b429cf
|
||||
Subproject commit e899cc1dd0720e0a4d25b0e751b84e3733cbedc5
|
@ -27,6 +27,7 @@ func main() {
|
||||
types.MessageReceipt{},
|
||||
types.BlockMsg{},
|
||||
types.ExpTipSet{},
|
||||
types.BeaconEntry{},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
@ -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.DrandBeacon) *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.DrandBeacon
|
||||
|
||||
lk sync.Mutex
|
||||
addresses []address.Address
|
||||
@ -291,6 +294,12 @@ 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()
|
||||
|
||||
round := base.ts.Height() + base.nullRounds + 1
|
||||
bvals, err := beacon.BeaconEntriesForBlock(ctx, m.beacon, round, int(base.nullRounds))
|
||||
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)
|
||||
@ -308,7 +317,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
|
||||
}
|
||||
|
||||
proofin, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, m.api)
|
||||
proofin, err := gen.IsRoundWinner(ctx, base.ts, int64(round), addr, m.epp, m.api)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
||||
}
|
||||
@ -329,7 +338,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return nil, xerrors.Errorf("computing election proof: %w", err)
|
||||
}
|
||||
|
||||
b, err := m.createBlock(base, addr, ticket, proof, pending)
|
||||
b, err := m.createBlock(base, addr, ticket, proof, bvals, pending)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create block: %w", err)
|
||||
}
|
||||
@ -369,7 +378,7 @@ 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, proof *types.EPostProof, 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 +394,7 @@ 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(), addr, base.ts.Key(), ticket, proof, bvals, msgs, nheight, uint64(uts))
|
||||
}
|
||||
|
||||
type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)
|
||||
|
@ -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.DrandBeacon), modules.RandomBeacon),
|
||||
|
||||
Override(new(*paychmgr.Store), paychmgr.NewStore),
|
||||
Override(new(*paychmgr.Manager), paychmgr.NewManager),
|
||||
|
@ -269,13 +269,12 @@ 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) {
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.EPostProof, bvals []*types.BeaconEntry, 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)
|
||||
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, bvals, msgs, height, ts)
|
||||
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.DrandBeacon) (*chain.Syncer, error) {
|
||||
syncer, err := chain.NewSyncer(sm, bsync, h.ConnManager(), h.ID(), beacon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
eventbus "github.com/libp2p/go-eventbus"
|
||||
event "github.com/libp2p/go-libp2p-core/event"
|
||||
@ -16,6 +18,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 +117,8 @@ func NewLocalDiscovery(ds dtypes.MetadataDS) *discovery.Local {
|
||||
func RetrievalResolver(l *discovery.Local) retrievalmarket.PeerResolver {
|
||||
return discovery.Multi(l)
|
||||
}
|
||||
|
||||
func RandomBeacon() beacon.DrandBeacon {
|
||||
fmt.Println("RANDOM BEACON!")
|
||||
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.DrandBeacon) (*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