Merge pull request #8606 from filecoin-project/asr/fix-drand-round
Fix: drand: calculation of round from Filecoin epochs
This commit is contained in:
commit
06279b5f1a
@ -171,14 +171,6 @@ type FullNode interface {
|
||||
// ChainBlockstoreInfo returns some basic information about the blockstore
|
||||
ChainBlockstoreInfo(context.Context) (map[string]interface{}, error) //perm:read
|
||||
|
||||
// MethodGroup: Beacon
|
||||
// The Beacon method group contains methods for interacting with the random beacon (DRAND)
|
||||
|
||||
// BeaconGetEntry returns the beacon entry for the given filecoin epoch. If
|
||||
// the entry has not yet been produced, the call will block until the entry
|
||||
// becomes available
|
||||
BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) //perm:read
|
||||
|
||||
// GasEstimateFeeCap estimates gas fee cap
|
||||
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read
|
||||
|
||||
@ -591,6 +583,11 @@ type FullNode interface {
|
||||
// StateGetRandomnessFromBeacon is used to sample the beacon for randomness.
|
||||
StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
|
||||
|
||||
// StateGetBeaconEntry returns the beacon entry for the given filecoin epoch. If
|
||||
// the entry has not yet been produced, the call will block until the entry
|
||||
// becomes available
|
||||
StateGetBeaconEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) //perm:read
|
||||
|
||||
// MethodGroup: Msig
|
||||
// The Msig methods are used to interact with multisig wallets on the
|
||||
// filecoin network
|
||||
|
@ -91,21 +91,6 @@ func (mr *MockFullNodeMockRecorder) AuthVerify(arg0, arg1 interface{}) *gomock.C
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthVerify", reflect.TypeOf((*MockFullNode)(nil).AuthVerify), arg0, arg1)
|
||||
}
|
||||
|
||||
// BeaconGetEntry mocks base method.
|
||||
func (m *MockFullNode) BeaconGetEntry(arg0 context.Context, arg1 abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeaconGetEntry", arg0, arg1)
|
||||
ret0, _ := ret[0].(*types.BeaconEntry)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// BeaconGetEntry indicates an expected call of BeaconGetEntry.
|
||||
func (mr *MockFullNodeMockRecorder) BeaconGetEntry(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeaconGetEntry", reflect.TypeOf((*MockFullNode)(nil).BeaconGetEntry), arg0, arg1)
|
||||
}
|
||||
|
||||
// ChainBlockstoreInfo mocks base method.
|
||||
func (m *MockFullNode) ChainBlockstoreInfo(arg0 context.Context) (map[string]interface{}, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -2406,6 +2391,21 @@ func (mr *MockFullNodeMockRecorder) StateGetActor(arg0, arg1, arg2 interface{})
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetActor", reflect.TypeOf((*MockFullNode)(nil).StateGetActor), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// StateGetBeaconEntry mocks base method.
|
||||
func (m *MockFullNode) StateGetBeaconEntry(arg0 context.Context, arg1 abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StateGetBeaconEntry", arg0, arg1)
|
||||
ret0, _ := ret[0].(*types.BeaconEntry)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StateGetBeaconEntry indicates an expected call of StateGetBeaconEntry.
|
||||
func (mr *MockFullNodeMockRecorder) StateGetBeaconEntry(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetBeaconEntry", reflect.TypeOf((*MockFullNode)(nil).StateGetBeaconEntry), arg0, arg1)
|
||||
}
|
||||
|
||||
// StateGetRandomnessFromBeacon mocks base method.
|
||||
func (m *MockFullNode) StateGetRandomnessFromBeacon(arg0 context.Context, arg1 crypto.DomainSeparationTag, arg2 abi.ChainEpoch, arg3 []byte, arg4 types.TipSetKey) (abi.Randomness, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -103,8 +103,6 @@ type FullNodeStruct struct {
|
||||
NetStruct
|
||||
|
||||
Internal struct {
|
||||
BeaconGetEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"`
|
||||
|
||||
ChainBlockstoreInfo func(p0 context.Context) (map[string]interface{}, error) `perm:"read"`
|
||||
|
||||
ChainCheckBlockstore func(p0 context.Context) error `perm:"admin"`
|
||||
@ -353,6 +351,8 @@ type FullNodeStruct struct {
|
||||
|
||||
StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"`
|
||||
|
||||
StateGetBeaconEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"`
|
||||
|
||||
StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
|
||||
|
||||
StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
|
||||
@ -1088,17 +1088,6 @@ func (s *CommonStub) Version(p0 context.Context) (APIVersion, error) {
|
||||
return *new(APIVersion), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) BeaconGetEntry(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
if s.Internal.BeaconGetEntry == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.BeaconGetEntry(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) BeaconGetEntry(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) ChainBlockstoreInfo(p0 context.Context) (map[string]interface{}, error) {
|
||||
if s.Internal.ChainBlockstoreInfo == nil {
|
||||
return *new(map[string]interface{}), ErrNotSupported
|
||||
@ -2463,6 +2452,17 @@ func (s *FullNodeStub) StateGetActor(p0 context.Context, p1 address.Address, p2
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) StateGetBeaconEntry(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
if s.Internal.StateGetBeaconEntry == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.StateGetBeaconEntry(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) StateGetBeaconEntry(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) StateGetRandomnessFromBeacon(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) {
|
||||
if s.Internal.StateGetRandomnessFromBeacon == nil {
|
||||
return *new(abi.Randomness), ErrNotSupported
|
||||
|
@ -352,4 +352,8 @@ func (w *WrapperV1Full) ClientQueryAsk(ctx context.Context, p peer.ID, miner add
|
||||
return a.Response, nil
|
||||
}
|
||||
|
||||
func (w *WrapperV1Full) BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
return w.StateGetBeaconEntry(ctx, epoch)
|
||||
}
|
||||
|
||||
var _ FullNode = &WrapperV1Full{}
|
||||
|
Binary file not shown.
@ -3,6 +3,8 @@ package beacon
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
@ -42,10 +44,10 @@ type BeaconPoint struct {
|
||||
type RandomBeacon interface {
|
||||
Entry(context.Context, uint64) <-chan Response
|
||||
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error
|
||||
MaxBeaconRoundForEpoch(abi.ChainEpoch) uint64
|
||||
MaxBeaconRoundForEpoch(network.Version, abi.ChainEpoch) uint64
|
||||
}
|
||||
|
||||
func ValidateBlockValues(bSchedule Schedule, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
|
||||
func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
|
||||
prevEntry types.BeaconEntry) error {
|
||||
{
|
||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||
@ -65,7 +67,7 @@ func ValidateBlockValues(bSchedule Schedule, h *types.BlockHeader, parentEpoch a
|
||||
|
||||
// TODO: fork logic
|
||||
b := bSchedule.BeaconForEpoch(h.Height)
|
||||
maxRound := b.MaxBeaconRoundForEpoch(h.Height)
|
||||
maxRound := b.MaxBeaconRoundForEpoch(nv, 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))
|
||||
@ -92,13 +94,13 @@ func ValidateBlockValues(bSchedule Schedule, h *types.BlockHeader, parentEpoch a
|
||||
return nil
|
||||
}
|
||||
|
||||
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, epoch abi.ChainEpoch, parentEpoch abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.Version, 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)
|
||||
round := currBeacon.MaxBeaconRoundForEpoch(nv, epoch)
|
||||
out := make([]types.BeaconEntry, 2)
|
||||
rch := currBeacon.Entry(ctx, round-1)
|
||||
res := <-rch
|
||||
@ -120,7 +122,7 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, epoch abi.Ch
|
||||
|
||||
start := build.Clock.Now()
|
||||
|
||||
maxRound := beacon.MaxBeaconRoundForEpoch(epoch)
|
||||
maxRound := beacon.MaxBeaconRoundForEpoch(nv, epoch)
|
||||
if maxRound == prev.Round {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
dchain "github.com/drand/drand/chain"
|
||||
dclient "github.com/drand/drand/client"
|
||||
hclient "github.com/drand/drand/client/http"
|
||||
@ -201,11 +203,32 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DrandBeacon) MaxBeaconRoundForEpoch(filEpoch abi.ChainEpoch) uint64 {
|
||||
func (db *DrandBeacon) MaxBeaconRoundForEpoch(nv network.Version, 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
|
||||
|
||||
if nv <= network.Version15 {
|
||||
return db.maxBeaconRoundV1(latestTs)
|
||||
}
|
||||
|
||||
return db.maxBeaconRoundV2(latestTs)
|
||||
}
|
||||
|
||||
func (db *DrandBeacon) maxBeaconRoundV1(latestTs uint64) uint64 {
|
||||
dround := (latestTs - db.drandGenTime) / uint64(db.interval.Seconds())
|
||||
return dround
|
||||
}
|
||||
|
||||
func (db *DrandBeacon) maxBeaconRoundV2(latestTs uint64) uint64 {
|
||||
if latestTs < db.drandGenTime {
|
||||
return 1
|
||||
}
|
||||
|
||||
fromGenesis := latestTs - db.drandGenTime
|
||||
// we take the time from genesis divided by the periods in seconds, that
|
||||
// gives us the number of periods since genesis. We also add +1 because
|
||||
// round 1 starts at genesis time.
|
||||
return fromGenesis/uint64(db.interval.Seconds()) + 1
|
||||
}
|
||||
|
||||
var _ beacon.RandomBeacon = (*DrandBeacon)(nil)
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
dchain "github.com/drand/drand/chain"
|
||||
hclient "github.com/drand/drand/client/http"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -25,3 +27,12 @@ func TestPrintGroupInfo(t *testing.T) {
|
||||
err = chain.ToJSON(os.Stdout)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestMaxBeaconRoundForEpoch(t *testing.T) {
|
||||
todayTs := uint64(1652222222)
|
||||
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandDevnet])
|
||||
assert.NoError(t, err)
|
||||
mbr15 := db.MaxBeaconRoundForEpoch(network.Version15, 100)
|
||||
mbr16 := db.MaxBeaconRoundForEpoch(network.Version16, 100)
|
||||
assert.Equal(t, mbr15+1, mbr16)
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/minio/blake2b-simd"
|
||||
@ -53,7 +55,7 @@ func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mb *mockBeacon) MaxBeaconRoundForEpoch(epoch abi.ChainEpoch) uint64 {
|
||||
func (mb *mockBeacon) MaxBeaconRoundForEpoch(nv network.Version, epoch abi.ChainEpoch) uint64 {
|
||||
// offset for better testing
|
||||
return uint64(epoch + 100)
|
||||
}
|
||||
|
@ -264,7 +264,8 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := beacon.ValidateBlockValues(filec.beacon, h, baseTs.Height(), *prevBeacon); err != nil {
|
||||
nv := filec.sm.GetNetworkVersion(ctx, h.Height)
|
||||
if err := beacon.ValidateBlockValues(filec.beacon, nv, h, baseTs.Height(), *prevBeacon); err != nil {
|
||||
return xerrors.Errorf("failed to validate blocks random beacon values: %w", err)
|
||||
}
|
||||
return nil
|
||||
@ -488,7 +489,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
||||
// Phase 2: (Partial) semantic validation:
|
||||
// the sender exists and is an account actor, and the nonces make sense
|
||||
var sender address.Address
|
||||
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version13 {
|
||||
if nv >= network.Version13 {
|
||||
sender, err = st.LookupID(m.From)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to lookup sender %s: %w", m.From, err)
|
||||
|
@ -198,7 +198,9 @@ func (sr *stateRand) extractBeaconEntryForEpoch(ctx context.Context, filecoinEpo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
round := sr.beacon.BeaconForEpoch(filecoinEpoch).MaxBeaconRoundForEpoch(filecoinEpoch)
|
||||
nv := sr.networkVersionGetter(ctx, filecoinEpoch)
|
||||
|
||||
round := sr.beacon.BeaconForEpoch(filecoinEpoch).MaxBeaconRoundForEpoch(nv, filecoinEpoch)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
cbe := randTs.Blocks()[0].BeaconEntries
|
||||
|
@ -317,7 +317,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
|
||||
prev = &types.BeaconEntry{}
|
||||
}
|
||||
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, bcs, round, ts.Height(), *prev)
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, bcs, sm.GetNetworkVersion(ctx, round), round, ts.Height(), *prev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -8,8 +8,6 @@
|
||||
* [Auth](#Auth)
|
||||
* [AuthNew](#AuthNew)
|
||||
* [AuthVerify](#AuthVerify)
|
||||
* [Beacon](#Beacon)
|
||||
* [BeaconGetEntry](#BeaconGetEntry)
|
||||
* [Chain](#Chain)
|
||||
* [ChainBlockstoreInfo](#ChainBlockstoreInfo)
|
||||
* [ChainCheckBlockstore](#ChainCheckBlockstore)
|
||||
@ -175,6 +173,7 @@
|
||||
* [StateDecodeParams](#StateDecodeParams)
|
||||
* [StateEncodeParams](#StateEncodeParams)
|
||||
* [StateGetActor](#StateGetActor)
|
||||
* [StateGetBeaconEntry](#StateGetBeaconEntry)
|
||||
* [StateGetRandomnessFromBeacon](#StateGetRandomnessFromBeacon)
|
||||
* [StateGetRandomnessFromTickets](#StateGetRandomnessFromTickets)
|
||||
* [StateListActors](#StateListActors)
|
||||
@ -340,33 +339,6 @@ Response:
|
||||
]
|
||||
```
|
||||
|
||||
## Beacon
|
||||
The Beacon method group contains methods for interacting with the random beacon (DRAND)
|
||||
|
||||
|
||||
### BeaconGetEntry
|
||||
BeaconGetEntry returns the beacon entry for the given filecoin epoch. If
|
||||
the entry has not yet been produced, the call will block until the entry
|
||||
becomes available
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
10101
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"Round": 42,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
}
|
||||
```
|
||||
|
||||
## Chain
|
||||
The Chain method group contains methods for interacting with the
|
||||
blockchain, but that do not require any form of state computation.
|
||||
@ -5641,6 +5613,29 @@ Response:
|
||||
}
|
||||
```
|
||||
|
||||
### StateGetBeaconEntry
|
||||
StateGetBeaconEntry returns the beacon entry for the given filecoin epoch. If
|
||||
the entry has not yet been produced, the call will block until the entry
|
||||
becomes available
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
10101
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"Round": 42,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
}
|
||||
```
|
||||
|
||||
### StateGetRandomnessFromBeacon
|
||||
StateGetRandomnessFromBeacon is used to sample the beacon for randomness.
|
||||
|
||||
|
@ -260,7 +260,7 @@ minerLoop:
|
||||
}
|
||||
|
||||
// just wait for the beacon entry to become available before we select our final mining base
|
||||
_, err = m.api.BeaconGetEntry(ctx, prebase.TipSet.Height()+prebase.NullRounds+1)
|
||||
_, err = m.api.StateGetBeaconEntry(ctx, prebase.TipSet.Height()+prebase.NullRounds+1)
|
||||
if err != nil {
|
||||
log.Errorf("failed getting beacon entry: %s", err)
|
||||
if !m.niceSleep(time.Second) {
|
||||
|
@ -35,7 +35,6 @@ type FullNodeAPI struct {
|
||||
full.MsigAPI
|
||||
full.WalletAPI
|
||||
full.SyncAPI
|
||||
full.BeaconAPI
|
||||
|
||||
DS dtypes.MetadataDS
|
||||
NetworkName dtypes.NetworkName
|
||||
|
@ -1,36 +0,0 @@
|
||||
package full
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
type BeaconAPI struct {
|
||||
fx.In
|
||||
|
||||
Beacon beacon.Schedule
|
||||
}
|
||||
|
||||
func (a *BeaconAPI) BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
b := a.Beacon.BeaconForEpoch(epoch)
|
||||
rr := b.MaxBeaconRoundForEpoch(epoch)
|
||||
e := b.Entry(ctx, rr)
|
||||
|
||||
select {
|
||||
case be, ok := <-e:
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("beacon get returned no value")
|
||||
}
|
||||
if be.Err != nil {
|
||||
return nil, be.Err
|
||||
}
|
||||
return &be.Entry, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@ -1457,3 +1458,22 @@ func (a *StateAPI) StateGetRandomnessFromBeacon(ctx context.Context, personaliza
|
||||
return a.StateManager.GetRandomnessFromBeacon(ctx, personalization, randEpoch, entropy, tsk)
|
||||
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateGetBeaconEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
b := a.Beacon.BeaconForEpoch(epoch)
|
||||
rr := b.MaxBeaconRoundForEpoch(a.StateManager.GetNetworkVersion(ctx, epoch), epoch)
|
||||
e := b.Entry(ctx, rr)
|
||||
|
||||
select {
|
||||
case be, ok := <-e:
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("beacon get returned no value")
|
||||
}
|
||||
if be.Err != nil {
|
||||
return nil, be.Err
|
||||
}
|
||||
return &be.Entry, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user