Merge pull request #3670 from filecoin-project/feat/drand-upgrade
Drand upgrade
This commit is contained in:
commit
38d854af83
@ -1,15 +1,26 @@
|
||||
package build
|
||||
|
||||
import "github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
import (
|
||||
"sort"
|
||||
|
||||
var DrandNetwork = DrandIncentinet
|
||||
|
||||
func DrandConfig() dtypes.DrandConfig {
|
||||
return DrandConfigs[DrandNetwork]
|
||||
}
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
type DrandEnum int
|
||||
|
||||
func DrandConfigSchedule() dtypes.DrandSchedule {
|
||||
out := dtypes.DrandSchedule{}
|
||||
for start, config := range DrandSchedule {
|
||||
out = append(out, dtypes.DrandPoint{Start: start, Config: DrandConfigs[config]})
|
||||
}
|
||||
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
return out[i].Start < out[j].Start
|
||||
})
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
const (
|
||||
DrandMainnet DrandEnum = iota + 1
|
||||
DrandTestnet
|
||||
|
@ -13,6 +13,12 @@ import (
|
||||
const UpgradeBreezeHeight = -1
|
||||
const BreezeGasTampingDuration = 0
|
||||
|
||||
const UpgradeSmokeHeight = -1
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
func init() {
|
||||
power.ConsensusMinerMinPower = big.NewInt(2048)
|
||||
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
|
||||
@ -23,7 +29,7 @@ func init() {
|
||||
BuildType |= Build2k
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(4)
|
||||
const BlockDelaySecs = uint64(30)
|
||||
|
||||
const PropagationDelaySecs = uint64(1)
|
||||
|
||||
|
@ -70,6 +70,12 @@ var (
|
||||
PackingEfficiencyNum int64 = 4
|
||||
PackingEfficiencyDenom int64 = 5
|
||||
|
||||
UpgradeBreezeHeight abi.ChainEpoch = 0
|
||||
UpgradeBreezeHeight abi.ChainEpoch = -1
|
||||
BreezeGasTampingDuration abi.ChainEpoch = 0
|
||||
|
||||
UpgradeSmokeHeight = -1
|
||||
|
||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
)
|
||||
|
@ -12,9 +12,16 @@ import (
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandIncentinet,
|
||||
UpgradeSmokeHeight: DrandMainnet,
|
||||
}
|
||||
|
||||
const UpgradeBreezeHeight = 41280
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
const UpgradeSmokeHeight = 51000
|
||||
|
||||
func init() {
|
||||
power.ConsensusMinerMinPower = big.NewInt(10 << 40)
|
||||
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
|
||||
|
@ -18,6 +18,23 @@ type Response struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type Schedule []BeaconPoint
|
||||
|
||||
func (bs Schedule) BeaconForEpoch(e abi.ChainEpoch) RandomBeacon {
|
||||
for i := len(bs) - 1; i >= 0; i-- {
|
||||
bp := bs[i]
|
||||
if e >= bp.Start {
|
||||
return bp.Beacon
|
||||
}
|
||||
}
|
||||
return bs[0].Beacon
|
||||
}
|
||||
|
||||
type BeaconPoint struct {
|
||||
Start abi.ChainEpoch
|
||||
Beacon RandomBeacon
|
||||
}
|
||||
|
||||
// RandomBeacon represents a system that provides randomness to Lotus.
|
||||
// Other components interrogate the RandomBeacon to acquire randomness that's
|
||||
// valid for a specific chain epoch. Also to verify beacon entries that have
|
||||
@ -25,11 +42,30 @@ type Response struct {
|
||||
type RandomBeacon interface {
|
||||
Entry(context.Context, uint64) <-chan Response
|
||||
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error
|
||||
MaxBeaconRoundForEpoch(abi.ChainEpoch, types.BeaconEntry) uint64
|
||||
MaxBeaconRoundForEpoch(abi.ChainEpoch) uint64
|
||||
}
|
||||
|
||||
func ValidateBlockValues(b RandomBeacon, h *types.BlockHeader, prevEntry types.BeaconEntry) error {
|
||||
maxRound := b.MaxBeaconRoundForEpoch(h.Height, prevEntry)
|
||||
func ValidateBlockValues(bSchedule Schedule, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
|
||||
prevEntry types.BeaconEntry) error {
|
||||
{
|
||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||
currBeacon := bSchedule.BeaconForEpoch(h.Height)
|
||||
if parentBeacon != currBeacon {
|
||||
if len(h.BeaconEntries) != 2 {
|
||||
return xerrors.Errorf("expected two beacon entries at beacon fork, got %d", len(h.BeaconEntries))
|
||||
}
|
||||
err := currBeacon.VerifyEntry(h.BeaconEntries[1], h.BeaconEntries[0])
|
||||
if err != nil {
|
||||
return xerrors.Errorf("beacon at fork point invalid: (%v, %v): %w",
|
||||
h.BeaconEntries[1], h.BeaconEntries[0], err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: fork logic
|
||||
b := bSchedule.BeaconForEpoch(h.Height)
|
||||
maxRound := b.MaxBeaconRoundForEpoch(h.Height)
|
||||
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))
|
||||
@ -56,10 +92,35 @@ func ValidateBlockValues(b RandomBeacon, h *types.BlockHeader, prevEntry types.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func BeaconEntriesForBlock(ctx context.Context, beacon RandomBeacon, round abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, epoch abi.ChainEpoch, parentEpoch abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||
{
|
||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||
currBeacon := bSchedule.BeaconForEpoch(epoch)
|
||||
if parentBeacon != currBeacon {
|
||||
// Fork logic
|
||||
round := currBeacon.MaxBeaconRoundForEpoch(epoch)
|
||||
out := make([]types.BeaconEntry, 2)
|
||||
rch := currBeacon.Entry(ctx, round-1)
|
||||
res := <-rch
|
||||
if res.Err != nil {
|
||||
return nil, xerrors.Errorf("getting entry %d returned error: %w", round-1, res.Err)
|
||||
}
|
||||
out[0] = res.Entry
|
||||
rch = currBeacon.Entry(ctx, round)
|
||||
res = <-rch
|
||||
if res.Err != nil {
|
||||
return nil, xerrors.Errorf("getting entry %d returned error: %w", round, res.Err)
|
||||
}
|
||||
out[1] = res.Entry
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
|
||||
beacon := bSchedule.BeaconForEpoch(epoch)
|
||||
|
||||
start := build.Clock.Now()
|
||||
|
||||
maxRound := beacon.MaxBeaconRoundForEpoch(round, prev)
|
||||
maxRound := beacon.MaxBeaconRoundForEpoch(epoch)
|
||||
if maxRound == prev.Round {
|
||||
return nil, nil
|
||||
}
|
||||
@ -82,7 +143,7 @@ func BeaconEntriesForBlock(ctx context.Context, beacon RandomBeacon, round abi.C
|
||||
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())
|
||||
return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for epoch %d: %w", epoch, ctx.Err())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DrandBeacon) MaxBeaconRoundForEpoch(filEpoch abi.ChainEpoch, prevEntry types.BeaconEntry) uint64 {
|
||||
func (db *DrandBeacon) MaxBeaconRoundForEpoch(filEpoch abi.ChainEpoch) uint64 {
|
||||
// TODO: sometimes the genesis time for filecoin is zero and this goes negative
|
||||
latestTs := ((uint64(filEpoch) * db.filRoundTime) + db.filGenTime) - db.filRoundTime
|
||||
dround := (latestTs - db.drandGenTime) / uint64(db.interval.Seconds())
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestPrintGroupInfo(t *testing.T) {
|
||||
server := build.DrandConfig().Servers[0]
|
||||
server := build.DrandConfigs[build.DrandIncentinet].Servers[0]
|
||||
c, err := hclient.New(server, nil, nil)
|
||||
assert.NoError(t, err)
|
||||
cg := c.(interface {
|
||||
|
@ -53,11 +53,7 @@ func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry)
|
||||
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 {
|
||||
func (mb *mockBeacon) MaxBeaconRoundForEpoch(epoch abi.ChainEpoch) uint64 {
|
||||
return uint64(epoch)
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ type ChainGen struct {
|
||||
|
||||
cs *store.ChainStore
|
||||
|
||||
beacon beacon.RandomBeacon
|
||||
beacon beacon.Schedule
|
||||
|
||||
sm *stmgr.StateManager
|
||||
|
||||
@ -252,7 +252,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
||||
|
||||
miners := []address.Address{maddr1, maddr2}
|
||||
|
||||
beac := beacon.NewMockBeacon(time.Second)
|
||||
beac := beacon.Schedule{{Start: 0, Beacon: beacon.NewMockBeacon(time.Second)}}
|
||||
//beac, err := drand.NewDrandBeacon(tpl.Timestamp, build.BlockDelaySecs)
|
||||
//if err != nil {
|
||||
//return nil, xerrors.Errorf("creating drand beacon: %w", err)
|
||||
@ -338,7 +338,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
|
||||
prev := mbi.PrevBeaconEntry
|
||||
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, round, prev)
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, round, pts.Height(), prev)
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
|
||||
}
|
||||
@ -559,7 +559,7 @@ type mca struct {
|
||||
w *wallet.Wallet
|
||||
sm *stmgr.StateManager
|
||||
pv ffiwrapper.Verifier
|
||||
bcn beacon.RandomBeacon
|
||||
bcn beacon.Schedule
|
||||
}
|
||||
|
||||
func (mca mca) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
|
||||
|
@ -502,7 +502,7 @@ func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.
|
||||
return lbts, nil
|
||||
}
|
||||
|
||||
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBeacon, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) {
|
||||
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) {
|
||||
ts, err := sm.ChainStore().LoadTipSet(tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load tipset for mining base: %w", err)
|
||||
@ -517,7 +517,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBe
|
||||
prev = &types.BeaconEntry{}
|
||||
}
|
||||
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, bcn, round, *prev)
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, bcs, round, ts.Height(), *prev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ type Syncer struct {
|
||||
store *store.ChainStore
|
||||
|
||||
// handle to the random beacon for verification
|
||||
beacon beacon.RandomBeacon
|
||||
beacon beacon.Schedule
|
||||
|
||||
// the state manager handles making state queries
|
||||
sm *stmgr.StateManager
|
||||
@ -141,7 +141,7 @@ type Syncer struct {
|
||||
}
|
||||
|
||||
// NewSyncer creates a new Syncer object.
|
||||
func NewSyncer(ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.Client, connmgr connmgr.ConnManager, self peer.ID, beacon beacon.RandomBeacon, verifier ffiwrapper.Verifier) (*Syncer, error) {
|
||||
func NewSyncer(ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.Client, connmgr connmgr.ConnManager, self peer.ID, beacon beacon.Schedule, verifier ffiwrapper.Verifier) (*Syncer, error) {
|
||||
gen, err := sm.ChainStore().GetGenesis()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting genesis block: %w", err)
|
||||
@ -879,7 +879,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := beacon.ValidateBlockValues(syncer.beacon, h, *prevBeacon); err != nil {
|
||||
if err := beacon.ValidateBlockValues(syncer.beacon, h, baseTs.Height(), *prevBeacon); err != nil {
|
||||
return xerrors.Errorf("failed to validate blocks random beacon values: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
4
go.mod
4
go.mod
@ -17,8 +17,8 @@ require (
|
||||
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
|
||||
github.com/dgraph-io/badger/v2 v2.0.3
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4
|
||||
github.com/drand/kyber v1.1.1
|
||||
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32
|
||||
github.com/drand/kyber v1.1.2
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/elastic/go-sysinfo v1.3.0
|
||||
github.com/fatih/color v1.8.0
|
||||
|
10
go.sum
10
go.sum
@ -91,6 +91,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/briandowns/spinner v1.11.1 h1:OixPqDEcX3juo5AjQZAnFPbeUA0jvkp2qzB5gOZJ/L0=
|
||||
github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
|
||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
@ -179,12 +180,12 @@ 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.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE=
|
||||
github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y=
|
||||
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4 h1:+Rov3bfUriGWFR/lUVXnpimx+HMr9BXRC4by0BxuQ8k=
|
||||
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4/go.mod h1:SnqWL9jksIMK63UKkfmWI6f9PDN8ROoCgg+Z4zWk7hg=
|
||||
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32 h1:sU+51aQRaDxg0KnjQg19KuYRIxDBEUHffBAICSnBys8=
|
||||
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32/go.mod h1:0sQEVg+ngs1jaDPVIiEgY0lbENWJPaUlWxGHEaSmKVM=
|
||||
github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw=
|
||||
github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
|
||||
github.com/drand/kyber v1.1.1 h1:mwCY2XGRB+Qc1MPfrnRuVuXELkPhcq/r9yMoJIcDhHI=
|
||||
github.com/drand/kyber v1.1.1/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
|
||||
github.com/drand/kyber v1.1.2 h1:faemqlaFyLrbBSjZGRzzu5SG/do+uTYpHlnrJIHbAhQ=
|
||||
github.com/drand/kyber v1.1.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
|
||||
github.com/drand/kyber-bls12381 v0.1.0 h1:/P4C65VnyEwxzR5ZYYVMNzY1If+aYBrdUU5ukwh7LQw=
|
||||
github.com/drand/kyber-bls12381 v0.1.0/go.mod h1:N1emiHpm+jj7kMlxEbu3MUyOiooTgNySln564cgD9mk=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@ -1747,7 +1748,6 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200617041141-9a465503579e/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -226,7 +226,7 @@ func Online() Option {
|
||||
|
||||
Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap),
|
||||
Override(new(dtypes.DrandBootstrap), modules.DrandBootstrap),
|
||||
Override(new(dtypes.DrandConfig), modules.BuiltinDrandConfig),
|
||||
Override(new(dtypes.DrandSchedule), modules.BuiltinDrandConfig),
|
||||
|
||||
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
|
||||
|
||||
@ -272,7 +272,7 @@ func Online() Option {
|
||||
Override(new(modules.ClientDealFunds), modules.NewClientDealFunds),
|
||||
Override(new(storagemarket.StorageClient), modules.StorageClient),
|
||||
Override(new(storagemarket.StorageClientNode), storageadapter.NewClientNodeAdapter),
|
||||
Override(new(beacon.RandomBeacon), modules.RandomBeacon),
|
||||
Override(new(beacon.Schedule), modules.RandomSchedule),
|
||||
|
||||
Override(new(*paychmgr.Store), paychmgr.NewStore),
|
||||
Override(new(*paychmgr.Manager), paychmgr.NewManager),
|
||||
@ -535,6 +535,6 @@ func Test() Option {
|
||||
return Options(
|
||||
Unset(RunPeerMgrKey),
|
||||
Unset(new(*peermgr.PeerMgr)),
|
||||
Override(new(beacon.RandomBeacon), testing.RandomBeacon),
|
||||
Override(new(beacon.Schedule), testing.RandomBeacon),
|
||||
)
|
||||
}
|
||||
|
@ -13,12 +13,13 @@ import (
|
||||
type BeaconAPI struct {
|
||||
fx.In
|
||||
|
||||
Beacon beacon.RandomBeacon
|
||||
Beacon beacon.Schedule
|
||||
}
|
||||
|
||||
func (a *BeaconAPI) BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
rr := a.Beacon.MaxBeaconRoundForEpoch(epoch, types.BeaconEntry{})
|
||||
e := a.Beacon.Entry(ctx, rr)
|
||||
b := a.Beacon.BeaconForEpoch(epoch)
|
||||
rr := b.MaxBeaconRoundForEpoch(epoch)
|
||||
e := b.Entry(ctx, rr)
|
||||
|
||||
select {
|
||||
case be, ok := <-e:
|
||||
|
@ -53,7 +53,7 @@ type StateAPI struct {
|
||||
ProofVerifier ffiwrapper.Verifier
|
||||
StateManager *stmgr.StateManager
|
||||
Chain *store.ChainStore
|
||||
Beacon beacon.RandomBeacon
|
||||
Beacon beacon.Schedule
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateNetworkName(ctx context.Context) (dtypes.NetworkName, error) {
|
||||
|
@ -163,7 +163,7 @@ func NetworkName(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore,
|
||||
return netName, err
|
||||
}
|
||||
|
||||
func NewSyncer(lc fx.Lifecycle, ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.Client, h host.Host, beacon beacon.RandomBeacon, verifier ffiwrapper.Verifier) (*chain.Syncer, error) {
|
||||
func NewSyncer(lc fx.Lifecycle, ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.Client, h host.Host, beacon beacon.Schedule, verifier ffiwrapper.Verifier) (*chain.Syncer, error) {
|
||||
syncer, err := chain.NewSyncer(ds, sm, exchange, h.ConnManager(), h.ID(), beacon, verifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/gbrlsnchs/jwt/v3"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/libp2p/go-libp2p-core/peerstore"
|
||||
record "github.com/libp2p/go-libp2p-record"
|
||||
"golang.org/x/xerrors"
|
||||
@ -93,14 +94,18 @@ func BuiltinBootstrap() (dtypes.BootstrapPeers, error) {
|
||||
return build.BuiltinBootstrap()
|
||||
}
|
||||
|
||||
func DrandBootstrap(d dtypes.DrandConfig) (dtypes.DrandBootstrap, error) {
|
||||
func DrandBootstrap(ds dtypes.DrandSchedule) (dtypes.DrandBootstrap, error) {
|
||||
// TODO: retry resolving, don't fail if at least one resolve succeeds
|
||||
addrs, err := addrutil.ParseAddresses(context.TODO(), d.Relays)
|
||||
if err != nil {
|
||||
log.Errorf("reoslving drand relays addresses: %+v", err)
|
||||
return nil, nil
|
||||
res := []peer.AddrInfo{}
|
||||
for _, d := range ds {
|
||||
addrs, err := addrutil.ParseAddresses(context.TODO(), d.Config.Relays)
|
||||
if err != nil {
|
||||
log.Errorf("reoslving drand relays addresses: %+v", err)
|
||||
return res, nil
|
||||
}
|
||||
res = append(res, addrs...)
|
||||
}
|
||||
return addrs, nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func SetupJournal(lr repo.LockedRepo) error {
|
||||
|
@ -1,5 +1,14 @@
|
||||
package dtypes
|
||||
|
||||
import "github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
type DrandSchedule []DrandPoint
|
||||
|
||||
type DrandPoint struct {
|
||||
Start abi.ChainEpoch
|
||||
Config DrandConfig
|
||||
}
|
||||
|
||||
type DrandConfig struct {
|
||||
Servers []string
|
||||
Relays []string
|
||||
|
@ -49,7 +49,7 @@ type GossipIn struct {
|
||||
Db dtypes.DrandBootstrap
|
||||
Cfg *config.Pubsub
|
||||
Sk *dtypes.ScoreKeeper
|
||||
Dr dtypes.DrandConfig
|
||||
Dr dtypes.DrandSchedule
|
||||
}
|
||||
|
||||
func getDrandTopic(chainInfoJSON string) (string, error) {
|
||||
@ -74,9 +74,126 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
||||
}
|
||||
|
||||
isBootstrapNode := in.Cfg.Bootstrapper
|
||||
drandTopic, err := getDrandTopic(in.Dr.ChainInfoJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
drandTopicParams := &pubsub.TopicScoreParams{
|
||||
// expected 2 beaconsn/min
|
||||
TopicWeight: 0.5, // 5x block topic; max cap is 62.5
|
||||
|
||||
// 1 tick per second, maxes at 1 after 1 hour
|
||||
TimeInMeshWeight: 0.00027, // ~1/3600
|
||||
TimeInMeshQuantum: time.Second,
|
||||
TimeInMeshCap: 1,
|
||||
|
||||
// deliveries decay after 1 hour, cap at 25 beacons
|
||||
FirstMessageDeliveriesWeight: 5, // max value is 125
|
||||
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
FirstMessageDeliveriesCap: 25, // the maximum expected in an hour is ~26, including the decay
|
||||
|
||||
// Mesh Delivery Failure is currently turned off for beacons
|
||||
// This is on purpose as
|
||||
// - the traffic is very low for meaningful distribution of incoming edges.
|
||||
// - the reaction time needs to be very slow -- in the order of 10 min at least
|
||||
// so we might as well let opportunistic grafting repair the mesh on its own
|
||||
// pace.
|
||||
// - the network is too small, so large asymmetries can be expected between mesh
|
||||
// edges.
|
||||
// We should revisit this once the network grows.
|
||||
|
||||
// invalid messages decay after 1 hour
|
||||
InvalidMessageDeliveriesWeight: -1000,
|
||||
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
}
|
||||
|
||||
topicParams := map[string]*pubsub.TopicScoreParams{
|
||||
build.BlocksTopic(in.Nn): {
|
||||
// expected 10 blocks/min
|
||||
TopicWeight: 0.1, // max cap is 50, max mesh penalty is -10, single invalid message is -100
|
||||
|
||||
// 1 tick per second, maxes at 1 after 1 hour
|
||||
TimeInMeshWeight: 0.00027, // ~1/3600
|
||||
TimeInMeshQuantum: time.Second,
|
||||
TimeInMeshCap: 1,
|
||||
|
||||
// deliveries decay after 1 hour, cap at 100 blocks
|
||||
FirstMessageDeliveriesWeight: 5, // max value is 500
|
||||
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
FirstMessageDeliveriesCap: 100, // 100 blocks in an hour
|
||||
|
||||
// Mesh Delivery Failure is currently turned off for blocks
|
||||
// This is on purpose as
|
||||
// - the traffic is very low for meaningful distribution of incoming edges.
|
||||
// - the reaction time needs to be very slow -- in the order of 10 min at least
|
||||
// so we might as well let opportunistic grafting repair the mesh on its own
|
||||
// pace.
|
||||
// - the network is too small, so large asymmetries can be expected between mesh
|
||||
// edges.
|
||||
// We should revisit this once the network grows.
|
||||
//
|
||||
// // tracks deliveries in the last minute
|
||||
// // penalty activates at 1 minute and expects ~0.4 blocks
|
||||
// MeshMessageDeliveriesWeight: -576, // max penalty is -100
|
||||
// MeshMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Minute),
|
||||
// MeshMessageDeliveriesCap: 10, // 10 blocks in a minute
|
||||
// MeshMessageDeliveriesThreshold: 0.41666, // 10/12/2 blocks/min
|
||||
// MeshMessageDeliveriesWindow: 10 * time.Millisecond,
|
||||
// MeshMessageDeliveriesActivation: time.Minute,
|
||||
//
|
||||
// // decays after 15 min
|
||||
// MeshFailurePenaltyWeight: -576,
|
||||
// MeshFailurePenaltyDecay: pubsub.ScoreParameterDecay(15 * time.Minute),
|
||||
|
||||
// invalid messages decay after 1 hour
|
||||
InvalidMessageDeliveriesWeight: -1000,
|
||||
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
},
|
||||
build.MessagesTopic(in.Nn): {
|
||||
// expected > 1 tx/second
|
||||
TopicWeight: 0.1, // max cap is 5, single invalid message is -100
|
||||
|
||||
// 1 tick per second, maxes at 1 hour
|
||||
TimeInMeshWeight: 0.0002778, // ~1/3600
|
||||
TimeInMeshQuantum: time.Second,
|
||||
TimeInMeshCap: 1,
|
||||
|
||||
// deliveries decay after 10min, cap at 100 tx
|
||||
FirstMessageDeliveriesWeight: 0.5, // max value is 50
|
||||
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(10 * time.Minute),
|
||||
FirstMessageDeliveriesCap: 100, // 100 messages in 10 minutes
|
||||
|
||||
// Mesh Delivery Failure is currently turned off for messages
|
||||
// This is on purpose as the network is still too small, which results in
|
||||
// asymmetries and potential unmeshing from negative scores.
|
||||
// // tracks deliveries in the last minute
|
||||
// // penalty activates at 1 min and expects 2.5 txs
|
||||
// MeshMessageDeliveriesWeight: -16, // max penalty is -100
|
||||
// MeshMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Minute),
|
||||
// MeshMessageDeliveriesCap: 100, // 100 txs in a minute
|
||||
// MeshMessageDeliveriesThreshold: 2.5, // 60/12/2 txs/minute
|
||||
// MeshMessageDeliveriesWindow: 10 * time.Millisecond,
|
||||
// MeshMessageDeliveriesActivation: time.Minute,
|
||||
|
||||
// // decays after 5min
|
||||
// MeshFailurePenaltyWeight: -16,
|
||||
// MeshFailurePenaltyDecay: pubsub.ScoreParameterDecay(5 * time.Minute),
|
||||
|
||||
// invalid messages decay after 1 hour
|
||||
InvalidMessageDeliveriesWeight: -1000,
|
||||
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
},
|
||||
}
|
||||
|
||||
pgTopicWeights := map[string]float64{
|
||||
build.BlocksTopic(in.Nn): 10,
|
||||
build.MessagesTopic(in.Nn): 1,
|
||||
}
|
||||
|
||||
for _, d := range in.Dr {
|
||||
topic, err := getDrandTopic(d.Config.ChainInfoJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
topicParams[topic] = drandTopicParams
|
||||
pgTopicWeights[topic] = 5
|
||||
}
|
||||
|
||||
options := []pubsub.Option{
|
||||
@ -124,111 +241,7 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
||||
RetainScore: 6 * time.Hour,
|
||||
|
||||
// topic parameters
|
||||
Topics: map[string]*pubsub.TopicScoreParams{
|
||||
drandTopic: {
|
||||
// expected 2 beaconsn/min
|
||||
TopicWeight: 0.5, // 5x block topic; max cap is 62.5
|
||||
|
||||
// 1 tick per second, maxes at 1 after 1 hour
|
||||
TimeInMeshWeight: 0.00027, // ~1/3600
|
||||
TimeInMeshQuantum: time.Second,
|
||||
TimeInMeshCap: 1,
|
||||
|
||||
// deliveries decay after 1 hour, cap at 25 beacons
|
||||
FirstMessageDeliveriesWeight: 5, // max value is 125
|
||||
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
FirstMessageDeliveriesCap: 25, // the maximum expected in an hour is ~26, including the decay
|
||||
|
||||
// Mesh Delivery Failure is currently turned off for beacons
|
||||
// This is on purpose as
|
||||
// - the traffic is very low for meaningful distribution of incoming edges.
|
||||
// - the reaction time needs to be very slow -- in the order of 10 min at least
|
||||
// so we might as well let opportunistic grafting repair the mesh on its own
|
||||
// pace.
|
||||
// - the network is too small, so large asymmetries can be expected between mesh
|
||||
// edges.
|
||||
// We should revisit this once the network grows.
|
||||
|
||||
// invalid messages decay after 1 hour
|
||||
InvalidMessageDeliveriesWeight: -1000,
|
||||
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
},
|
||||
build.BlocksTopic(in.Nn): {
|
||||
// expected 10 blocks/min
|
||||
TopicWeight: 0.1, // max cap is 50, max mesh penalty is -10, single invalid message is -100
|
||||
|
||||
// 1 tick per second, maxes at 1 after 1 hour
|
||||
TimeInMeshWeight: 0.00027, // ~1/3600
|
||||
TimeInMeshQuantum: time.Second,
|
||||
TimeInMeshCap: 1,
|
||||
|
||||
// deliveries decay after 1 hour, cap at 100 blocks
|
||||
FirstMessageDeliveriesWeight: 5, // max value is 500
|
||||
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
FirstMessageDeliveriesCap: 100, // 100 blocks in an hour
|
||||
|
||||
// Mesh Delivery Failure is currently turned off for blocks
|
||||
// This is on purpose as
|
||||
// - the traffic is very low for meaningful distribution of incoming edges.
|
||||
// - the reaction time needs to be very slow -- in the order of 10 min at least
|
||||
// so we might as well let opportunistic grafting repair the mesh on its own
|
||||
// pace.
|
||||
// - the network is too small, so large asymmetries can be expected between mesh
|
||||
// edges.
|
||||
// We should revisit this once the network grows.
|
||||
//
|
||||
// // tracks deliveries in the last minute
|
||||
// // penalty activates at 1 minute and expects ~0.4 blocks
|
||||
// MeshMessageDeliveriesWeight: -576, // max penalty is -100
|
||||
// MeshMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Minute),
|
||||
// MeshMessageDeliveriesCap: 10, // 10 blocks in a minute
|
||||
// MeshMessageDeliveriesThreshold: 0.41666, // 10/12/2 blocks/min
|
||||
// MeshMessageDeliveriesWindow: 10 * time.Millisecond,
|
||||
// MeshMessageDeliveriesActivation: time.Minute,
|
||||
//
|
||||
// // decays after 15 min
|
||||
// MeshFailurePenaltyWeight: -576,
|
||||
// MeshFailurePenaltyDecay: pubsub.ScoreParameterDecay(15 * time.Minute),
|
||||
|
||||
// invalid messages decay after 1 hour
|
||||
InvalidMessageDeliveriesWeight: -1000,
|
||||
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
},
|
||||
build.MessagesTopic(in.Nn): {
|
||||
// expected > 1 tx/second
|
||||
TopicWeight: 0.1, // max cap is 5, single invalid message is -100
|
||||
|
||||
// 1 tick per second, maxes at 1 hour
|
||||
TimeInMeshWeight: 0.0002778, // ~1/3600
|
||||
TimeInMeshQuantum: time.Second,
|
||||
TimeInMeshCap: 1,
|
||||
|
||||
// deliveries decay after 10min, cap at 100 tx
|
||||
FirstMessageDeliveriesWeight: 0.5, // max value is 50
|
||||
FirstMessageDeliveriesDecay: pubsub.ScoreParameterDecay(10 * time.Minute),
|
||||
FirstMessageDeliveriesCap: 100, // 100 messages in 10 minutes
|
||||
|
||||
// Mesh Delivery Failure is currently turned off for messages
|
||||
// This is on purpose as the network is still too small, which results in
|
||||
// asymmetries and potential unmeshing from negative scores.
|
||||
// // tracks deliveries in the last minute
|
||||
// // penalty activates at 1 min and expects 2.5 txs
|
||||
// MeshMessageDeliveriesWeight: -16, // max penalty is -100
|
||||
// MeshMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Minute),
|
||||
// MeshMessageDeliveriesCap: 100, // 100 txs in a minute
|
||||
// MeshMessageDeliveriesThreshold: 2.5, // 60/12/2 txs/minute
|
||||
// MeshMessageDeliveriesWindow: 10 * time.Millisecond,
|
||||
// MeshMessageDeliveriesActivation: time.Minute,
|
||||
|
||||
// // decays after 5min
|
||||
// MeshFailurePenaltyWeight: -16,
|
||||
// MeshFailurePenaltyDecay: pubsub.ScoreParameterDecay(5 * time.Minute),
|
||||
|
||||
// invalid messages decay after 1 hour
|
||||
InvalidMessageDeliveriesWeight: -1000,
|
||||
InvalidMessageDeliveriesDecay: pubsub.ScoreParameterDecay(time.Hour),
|
||||
},
|
||||
},
|
||||
Topics: topicParams,
|
||||
},
|
||||
&pubsub.PeerScoreThresholds{
|
||||
GossipThreshold: -500,
|
||||
@ -278,11 +291,6 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
||||
}
|
||||
|
||||
// validation queue RED
|
||||
pgTopicWeights := map[string]float64{
|
||||
drandTopic: 5,
|
||||
build.BlocksTopic(in.Nn): 10,
|
||||
build.MessagesTopic(in.Nn): 1,
|
||||
}
|
||||
var pgParams *pubsub.PeerGaterParams
|
||||
|
||||
if isBootstrapNode {
|
||||
|
@ -126,19 +126,27 @@ type RandomBeaconParams struct {
|
||||
|
||||
PubSub *pubsub.PubSub `optional:"true"`
|
||||
Cs *store.ChainStore
|
||||
DrandConfig dtypes.DrandConfig
|
||||
DrandConfig dtypes.DrandSchedule
|
||||
}
|
||||
|
||||
func BuiltinDrandConfig() dtypes.DrandConfig {
|
||||
return build.DrandConfig()
|
||||
func BuiltinDrandConfig() dtypes.DrandSchedule {
|
||||
return build.DrandConfigSchedule()
|
||||
}
|
||||
|
||||
func RandomBeacon(p RandomBeaconParams, _ dtypes.AfterGenesisSet) (beacon.RandomBeacon, error) {
|
||||
func RandomSchedule(p RandomBeaconParams, _ dtypes.AfterGenesisSet) (beacon.Schedule, error) {
|
||||
gen, err := p.Cs.GetGenesis()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//return beacon.NewMockBeacon(build.BlockDelaySecs * time.Second)
|
||||
return drand.NewDrandBeacon(gen.Timestamp, build.BlockDelaySecs, p.PubSub, p.DrandConfig)
|
||||
shd := beacon.Schedule{}
|
||||
for _, dc := range p.DrandConfig {
|
||||
bc, err := drand.NewDrandBeacon(gen.Timestamp, build.BlockDelaySecs, p.PubSub, dc.Config)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("creating drand beacon: %w", err)
|
||||
}
|
||||
shd = append(shd, beacon.BeaconPoint{Start: dc.Start, Beacon: bc})
|
||||
}
|
||||
|
||||
return shd, nil
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
)
|
||||
|
||||
func RandomBeacon() (beacon.RandomBeacon, error) {
|
||||
return beacon.NewMockBeacon(time.Duration(build.BlockDelaySecs) * time.Second), nil
|
||||
func RandomBeacon() (beacon.Schedule, error) {
|
||||
return beacon.Schedule{
|
||||
{Start: 0,
|
||||
Beacon: beacon.NewMockBeacon(time.Duration(build.BlockDelaySecs) * time.Second),
|
||||
}}, nil
|
||||
}
|
||||
|
@ -7,4 +7,4 @@ export TRUST_PARAMS=1
|
||||
tag=${TAG:-debug}
|
||||
|
||||
go run -tags=$tag ./cmd/lotus wallet import ~/.genesis-sectors/pre-seal-t01000.key
|
||||
go run -tags=$tag ./cmd/lotus-miner init --actor=t01000 --genesis-miner --pre-sealed-sectors=~/.genesis-sectors --pre-sealed-metadata=~/.genesis-sectors/pre-seal-t01000.json
|
||||
go run -tags=$tag ./cmd/lotus-storage-miner init --actor=t01000 --genesis-miner --pre-sealed-sectors=~/.genesis-sectors --pre-sealed-metadata=~/.genesis-sectors/pre-seal-t01000.json
|
||||
|
Loading…
Reference in New Issue
Block a user