Skip to content

Commit 05e0dbd

Browse files
authored
Merge pull request #6409 from oasisprotocol/peternose/feature/next-epoch
go/beacon/api: Support fetching next block epoch
2 parents 4aca077 + 3dbc941 commit 05e0dbd

5 files changed

Lines changed: 76 additions & 3 deletions

File tree

.changelog/6409.feature.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
go/beacon/api: Support fetching next block epoch

go/beacon/api/api.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,17 @@ type Backend interface {
7171
GetBaseEpoch(context.Context) (EpochTime, error)
7272

7373
// GetEpoch returns the epoch number at the specified block height.
74+
//
7475
// Calling this method with height `consensus.HeightLatest`, should
75-
// return the epoch of latest known block.
76+
// return the epoch of the latest finalized block.
7677
GetEpoch(context.Context, int64) (EpochTime, error)
7778

79+
// GetNextEpoch returns the epoch number after the specified block height.
80+
//
81+
// Calling this method with height `consensus.HeightLatest`, should
82+
// return the epoch of the next block after the latest finalized block.
83+
GetNextEpoch(context.Context, int64) (EpochTime, error)
84+
7885
// GetFutureEpoch returns any future epoch that is currently scheduled
7986
// to occur at a specific height.
8087
//
@@ -108,6 +115,7 @@ type Backend interface {
108115
WatchLatestEpoch(ctx context.Context) (<-chan EpochTime, pubsub.ClosableSubscription, error)
109116

110117
// GetBeacon gets the beacon for the provided block height.
118+
//
111119
// Calling this method with height `consensus.HeightLatest` should
112120
// return the beacon for the latest finalized block.
113121
GetBeacon(context.Context, int64) ([]byte, error)

go/beacon/api/grpc.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ var (
1818
methodGetBaseEpoch = serviceName.NewMethod("GetBaseEpoch", nil)
1919
// methodGetEpoch is the GetEpoch method.
2020
methodGetEpoch = serviceName.NewMethod("GetEpoch", int64(0))
21+
// methodGetNextEpoch is the GetNextEpoch method.
22+
methodGetNextEpoch = serviceName.NewMethod("GetNextEpoch", int64(0))
2123
// methodGetFutureEpoch is the GetFutureEpoch method.
2224
methodGetFutureEpoch = serviceName.NewMethod("GetFutureEpoch", int64(0))
2325
// methodGetEpochBlock is the GetEpochBlock method.
@@ -47,6 +49,10 @@ var (
4749
MethodName: methodGetEpoch.ShortName(),
4850
Handler: handlerGetEpoch,
4951
},
52+
{
53+
MethodName: methodGetNextEpoch.ShortName(),
54+
Handler: handlerGetNextEpoch,
55+
},
5056
{
5157
MethodName: methodGetFutureEpoch.ShortName(),
5258
Handler: handlerGetFutureEpoch,
@@ -124,6 +130,29 @@ func handlerGetEpoch(
124130
return interceptor(ctx, height, info, handler)
125131
}
126132

133+
func handlerGetNextEpoch(
134+
srv any,
135+
ctx context.Context,
136+
dec func(any) error,
137+
interceptor grpc.UnaryServerInterceptor,
138+
) (any, error) {
139+
var height int64
140+
if err := dec(&height); err != nil {
141+
return nil, err
142+
}
143+
if interceptor == nil {
144+
return srv.(Backend).GetNextEpoch(ctx, height)
145+
}
146+
info := &grpc.UnaryServerInfo{
147+
Server: srv,
148+
FullMethod: methodGetNextEpoch.FullName(),
149+
}
150+
handler := func(ctx context.Context, req any) (any, error) {
151+
return srv.(Backend).GetNextEpoch(ctx, req.(int64))
152+
}
153+
return interceptor(ctx, height, info, handler)
154+
}
155+
127156
func handlerGetFutureEpoch(
128157
srv any,
129158
ctx context.Context,
@@ -323,6 +352,14 @@ func (c *Client) GetEpoch(ctx context.Context, height int64) (EpochTime, error)
323352
return rsp, nil
324353
}
325354

355+
func (c *Client) GetNextEpoch(ctx context.Context, height int64) (EpochTime, error) {
356+
var rsp EpochTime
357+
if err := c.conn.Invoke(ctx, methodGetNextEpoch.FullName(), height, &rsp); err != nil {
358+
return 0, err
359+
}
360+
return rsp, nil
361+
}
362+
326363
func (c *Client) GetFutureEpoch(ctx context.Context, height int64) (*EpochTimeState, error) {
327364
var rsp EpochTimeState
328365
if err := c.conn.Invoke(ctx, methodGetFutureEpoch.FullName(), height, &rsp); err != nil {

go/consensus/cometbft/beacon/beacon.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,33 @@ func (sc *ServiceClient) GetEpoch(ctx context.Context, height int64) (api.EpochT
104104
return epoch, err
105105
}
106106

107+
func (sc *ServiceClient) GetNextEpoch(ctx context.Context, height int64) (api.EpochTime, error) {
108+
if height == consensus.HeightLatest {
109+
latest, err := sc.consensus.GetLatestHeight(ctx)
110+
if err != nil {
111+
return api.EpochInvalid, err
112+
}
113+
height = latest
114+
}
115+
116+
q, err := sc.querier.QueryAt(ctx, height)
117+
if err != nil {
118+
return api.EpochInvalid, err
119+
}
120+
121+
future, err := q.FutureEpoch(ctx)
122+
if err != nil {
123+
return api.EpochInvalid, err
124+
}
125+
126+
if future != nil && future.Height == height+1 {
127+
return future.Epoch, nil
128+
}
129+
130+
epoch, _, err := q.Epoch(ctx)
131+
return epoch, err
132+
}
133+
107134
func (sc *ServiceClient) GetFutureEpoch(ctx context.Context, height int64) (*api.EpochTimeState, error) {
108135
q, err := sc.querier.QueryAt(ctx, height)
109136
if err != nil {

go/worker/common/committee/node.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ func (n *Node) handleSuspend() {
244244

245245
func (n *Node) updateHostedRuntimeVersion(rt *registry.Runtime) {
246246
// Always take the latest epoch to avoid reverting to stale state.
247-
epoch, err := n.Consensus.Beacon().GetEpoch(n.ctx, consensus.HeightLatest)
247+
epoch, err := n.Consensus.Beacon().GetNextEpoch(n.ctx, consensus.HeightLatest)
248248
if err != nil {
249-
n.logger.Error("failed to fetch current epoch",
249+
n.logger.Error("failed to fetch next block epoch",
250250
"err", err,
251251
)
252252
return

0 commit comments

Comments
 (0)