Fix calculation of Drand round from Filecoin epochs

This commit is contained in:
Aayush Rajasekaran 2021-09-26 21:23:41 -04:00
parent 8323ff77b6
commit 6924a3d5f2
17 changed files with 135 additions and 115 deletions

View File

@ -171,14 +171,6 @@ type FullNode interface {
// ChainBlockstoreInfo returns some basic information about the blockstore // ChainBlockstoreInfo returns some basic information about the blockstore
ChainBlockstoreInfo(context.Context) (map[string]interface{}, error) //perm:read 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 estimates gas fee cap
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read 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 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 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 // MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the // The Msig methods are used to interact with multisig wallets on the
// filecoin network // filecoin network

View File

@ -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) 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. // ChainBlockstoreInfo mocks base method.
func (m *MockFullNode) ChainBlockstoreInfo(arg0 context.Context) (map[string]interface{}, error) { func (m *MockFullNode) ChainBlockstoreInfo(arg0 context.Context) (map[string]interface{}, error) {
m.ctrl.T.Helper() 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) 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. // 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) { 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() m.ctrl.T.Helper()

View File

@ -103,8 +103,6 @@ type FullNodeStruct struct {
NetStruct NetStruct
Internal struct { 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"` ChainBlockstoreInfo func(p0 context.Context) (map[string]interface{}, error) `perm:"read"`
ChainCheckBlockstore func(p0 context.Context) error `perm:"admin"` 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"` 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"` 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"` 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 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) { func (s *FullNodeStruct) ChainBlockstoreInfo(p0 context.Context) (map[string]interface{}, error) {
if s.Internal.ChainBlockstoreInfo == nil { if s.Internal.ChainBlockstoreInfo == nil {
return *new(map[string]interface{}), ErrNotSupported return *new(map[string]interface{}), ErrNotSupported
@ -2463,6 +2452,17 @@ func (s *FullNodeStub) StateGetActor(p0 context.Context, p1 address.Address, p2
return nil, ErrNotSupported 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) { 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 { if s.Internal.StateGetRandomnessFromBeacon == nil {
return *new(abi.Randomness), ErrNotSupported return *new(abi.Randomness), ErrNotSupported

View File

@ -352,4 +352,8 @@ func (w *WrapperV1Full) ClientQueryAsk(ctx context.Context, p peer.ID, miner add
return a.Response, nil 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{} var _ FullNode = &WrapperV1Full{}

Binary file not shown.

View File

@ -3,6 +3,8 @@ package beacon
import ( import (
"context" "context"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -42,10 +44,10 @@ type BeaconPoint struct {
type RandomBeacon interface { type RandomBeacon interface {
Entry(context.Context, uint64) <-chan Response Entry(context.Context, uint64) <-chan Response
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error 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 { prevEntry types.BeaconEntry) error {
{ {
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch) parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
@ -65,7 +67,7 @@ func ValidateBlockValues(bSchedule Schedule, h *types.BlockHeader, parentEpoch a
// TODO: fork logic // TODO: fork logic
b := bSchedule.BeaconForEpoch(h.Height) b := bSchedule.BeaconForEpoch(h.Height)
maxRound := b.MaxBeaconRoundForEpoch(h.Height) maxRound := b.MaxBeaconRoundForEpoch(nv, h.Height)
if maxRound == prevEntry.Round { if maxRound == prevEntry.Round {
if len(h.BeaconEntries) != 0 { if len(h.BeaconEntries) != 0 {
return xerrors.Errorf("expected not to have any beacon entries in this block, got %d", len(h.BeaconEntries)) 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 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) parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
currBeacon := bSchedule.BeaconForEpoch(epoch) currBeacon := bSchedule.BeaconForEpoch(epoch)
if parentBeacon != currBeacon { if parentBeacon != currBeacon {
// Fork logic // Fork logic
round := currBeacon.MaxBeaconRoundForEpoch(epoch) round := currBeacon.MaxBeaconRoundForEpoch(nv, epoch)
out := make([]types.BeaconEntry, 2) out := make([]types.BeaconEntry, 2)
rch := currBeacon.Entry(ctx, round-1) rch := currBeacon.Entry(ctx, round-1)
res := <-rch res := <-rch
@ -120,7 +122,7 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, epoch abi.Ch
start := build.Clock.Now() start := build.Clock.Now()
maxRound := beacon.MaxBeaconRoundForEpoch(epoch) maxRound := beacon.MaxBeaconRoundForEpoch(nv, epoch)
if maxRound == prev.Round { if maxRound == prev.Round {
return nil, nil return nil, nil
} }

View File

@ -5,6 +5,8 @@ import (
"context" "context"
"time" "time"
"github.com/filecoin-project/go-state-types/network"
dchain "github.com/drand/drand/chain" dchain "github.com/drand/drand/chain"
dclient "github.com/drand/drand/client" dclient "github.com/drand/drand/client"
hclient "github.com/drand/drand/client/http" hclient "github.com/drand/drand/client/http"
@ -201,11 +203,32 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
return err 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 // TODO: sometimes the genesis time for filecoin is zero and this goes negative
latestTs := ((uint64(filEpoch) * db.filRoundTime) + db.filGenTime) - db.filRoundTime 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()) dround := (latestTs - db.drandGenTime) / uint64(db.interval.Seconds())
return dround 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) var _ beacon.RandomBeacon = (*DrandBeacon)(nil)

View File

@ -6,6 +6,8 @@ import (
"os" "os"
"testing" "testing"
"github.com/filecoin-project/go-state-types/network"
dchain "github.com/drand/drand/chain" dchain "github.com/drand/drand/chain"
hclient "github.com/drand/drand/client/http" hclient "github.com/drand/drand/client/http"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -25,3 +27,12 @@ func TestPrintGroupInfo(t *testing.T) {
err = chain.ToJSON(os.Stdout) err = chain.ToJSON(os.Stdout)
assert.NoError(t, err) 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)
}

View File

@ -6,6 +6,8 @@ import (
"encoding/binary" "encoding/binary"
"time" "time"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/minio/blake2b-simd" "github.com/minio/blake2b-simd"
@ -53,7 +55,7 @@ func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry)
return nil 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 // offset for better testing
return uint64(epoch + 100) return uint64(epoch + 100)
} }

View File

@ -264,7 +264,8 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
return nil 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 xerrors.Errorf("failed to validate blocks random beacon values: %w", err)
} }
return nil return nil
@ -488,7 +489,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
// Phase 2: (Partial) semantic validation: // Phase 2: (Partial) semantic validation:
// the sender exists and is an account actor, and the nonces make sense // the sender exists and is an account actor, and the nonces make sense
var sender address.Address var sender address.Address
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version13 { if nv >= network.Version13 {
sender, err = st.LookupID(m.From) sender, err = st.LookupID(m.From)
if err != nil { if err != nil {
return xerrors.Errorf("failed to lookup sender %s: %w", m.From, err) return xerrors.Errorf("failed to lookup sender %s: %w", m.From, err)

View File

@ -198,7 +198,9 @@ func (sr *stateRand) extractBeaconEntryForEpoch(ctx context.Context, filecoinEpo
return nil, err 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++ { for i := 0; i < 20; i++ {
cbe := randTs.Blocks()[0].BeaconEntries cbe := randTs.Blocks()[0].BeaconEntries

View File

@ -317,7 +317,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
prev = &types.BeaconEntry{} 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 { if err != nil {
return nil, err return nil, err
} }

View File

@ -8,8 +8,6 @@
* [Auth](#Auth) * [Auth](#Auth)
* [AuthNew](#AuthNew) * [AuthNew](#AuthNew)
* [AuthVerify](#AuthVerify) * [AuthVerify](#AuthVerify)
* [Beacon](#Beacon)
* [BeaconGetEntry](#BeaconGetEntry)
* [Chain](#Chain) * [Chain](#Chain)
* [ChainBlockstoreInfo](#ChainBlockstoreInfo) * [ChainBlockstoreInfo](#ChainBlockstoreInfo)
* [ChainCheckBlockstore](#ChainCheckBlockstore) * [ChainCheckBlockstore](#ChainCheckBlockstore)
@ -175,6 +173,7 @@
* [StateDecodeParams](#StateDecodeParams) * [StateDecodeParams](#StateDecodeParams)
* [StateEncodeParams](#StateEncodeParams) * [StateEncodeParams](#StateEncodeParams)
* [StateGetActor](#StateGetActor) * [StateGetActor](#StateGetActor)
* [StateGetBeaconEntry](#StateGetBeaconEntry)
* [StateGetRandomnessFromBeacon](#StateGetRandomnessFromBeacon) * [StateGetRandomnessFromBeacon](#StateGetRandomnessFromBeacon)
* [StateGetRandomnessFromTickets](#StateGetRandomnessFromTickets) * [StateGetRandomnessFromTickets](#StateGetRandomnessFromTickets)
* [StateListActors](#StateListActors) * [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 ## Chain
The Chain method group contains methods for interacting with the The Chain method group contains methods for interacting with the
blockchain, but that do not require any form of state computation. 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
StateGetRandomnessFromBeacon is used to sample the beacon for randomness. StateGetRandomnessFromBeacon is used to sample the beacon for randomness.

View File

@ -260,7 +260,7 @@ minerLoop:
} }
// just wait for the beacon entry to become available before we select our final mining base // 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 { if err != nil {
log.Errorf("failed getting beacon entry: %s", err) log.Errorf("failed getting beacon entry: %s", err)
if !m.niceSleep(time.Second) { if !m.niceSleep(time.Second) {

View File

@ -35,7 +35,6 @@ type FullNodeAPI struct {
full.MsigAPI full.MsigAPI
full.WalletAPI full.WalletAPI
full.SyncAPI full.SyncAPI
full.BeaconAPI
DS dtypes.MetadataDS DS dtypes.MetadataDS
NetworkName dtypes.NetworkName NetworkName dtypes.NetworkName

View File

@ -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()
}
}

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"strconv" "strconv"
"github.com/libp2p/go-libp2p-core/peer" "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) 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()
}
}