Skip to content

Commit 631ddc1

Browse files
authored
Merge pull request #6425 from oasisprotocol/peternose/internal/committee-transition
go/worker/common: Replace epoch transitions with committee transitions
2 parents f73f73c + 2d0afc6 commit 631ddc1

15 files changed

Lines changed: 515 additions & 438 deletions

File tree

.changelog/6425.internal.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
go/worker/common: Replace epoch transitions with committee transitions
2+
3+
The following metric has been removed:
4+
5+
- `oasis_worker_epoch_transition_count`
6+
7+
The following metric has been added:
8+
9+
- `oasis_worker_committee_transition_count`

docs/oasis-node/metrics.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,16 @@ oasis_worker_batch_runtime_processing_time | Summary | Time it takes for a batch
102102
oasis_worker_batch_size | Summary | Number of transactions in a batch. | runtime | [worker/compute/executor/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go)
103103
oasis_worker_client_lb_healthy_instance_count | Gauge | Number of healthy instances in the load balancer. | runtime | [runtime/host/loadbalance](https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/loadbalance/metrics.go)
104104
oasis_worker_client_lb_requests | Counter | Number of requests processed by the given load balancer instance. | runtime, lb_instance | [runtime/host/loadbalance](https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/loadbalance/metrics.go)
105-
oasis_worker_epoch_number | Gauge | Current epoch number as seen by the worker. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
106-
oasis_worker_epoch_transition_count | Counter | Number of epoch transitions. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
105+
oasis_worker_committee_transition_count | Counter | Number of committee transitions. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
106+
oasis_worker_epoch_number | Gauge | Current epoch number as seen by the worker. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
107107
oasis_worker_execution_discrepancy_detected_count | Counter | Number of detected execute discrepancies. | runtime | [worker/compute/executor/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go)
108-
oasis_worker_executor_committee_p2p_peers | Gauge | Number of executor committee P2P peers. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
109-
oasis_worker_executor_is_backup_worker | Gauge | 1 if worker is currently an executor backup worker, 0 otherwise. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
110-
oasis_worker_executor_is_worker | Gauge | 1 if worker is currently an executor worker, 0 otherwise. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
111-
oasis_worker_executor_liveness_live_ratio | Gauge | Ratio between live and total rounds. Reports 1 if node is not in committee. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
112-
oasis_worker_executor_liveness_live_rounds | Gauge | Number of live rounds in last epoch. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
113-
oasis_worker_executor_liveness_total_rounds | Gauge | Number of total rounds in last epoch. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
114-
oasis_worker_failed_round_count | Counter | Number of failed roothash rounds. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
108+
oasis_worker_executor_committee_p2p_peers | Gauge | Number of executor committee P2P peers. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
109+
oasis_worker_executor_is_backup_worker | Gauge | 1 if worker is currently an executor backup worker, 0 otherwise. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
110+
oasis_worker_executor_is_worker | Gauge | 1 if worker is currently an executor worker, 0 otherwise. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
111+
oasis_worker_executor_liveness_live_ratio | Gauge | Ratio between live and total rounds. Reports 1 if node is not in committee. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
112+
oasis_worker_executor_liveness_live_rounds | Gauge | Number of live rounds in last epoch. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
113+
oasis_worker_executor_liveness_total_rounds | Gauge | Number of total rounds in last epoch. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
114+
oasis_worker_failed_round_count | Counter | Number of failed roothash rounds. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
115115
oasis_worker_keymanager_churp_committee_size | Gauge | Number of nodes in the committee | runtime, churp | [worker/keymanager](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go)
116116
oasis_worker_keymanager_churp_confirmed_applications_total | Gauge | Number of confirmed applications | runtime, churp | [worker/keymanager](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go)
117117
oasis_worker_keymanager_churp_enclave_rpc_failures_total | Counter | Number of failed enclave rpc calls. | runtime, churp, method | [worker/keymanager](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go)
@@ -142,7 +142,7 @@ oasis_worker_node_registration_eligible | Gauge | Is oasis node eligible for reg
142142
oasis_worker_node_status_frozen | Gauge | Is oasis node frozen (binary). | | [worker/registration](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go)
143143
oasis_worker_node_status_runtime_faults | Gauge | Number of runtime faults. | runtime | [worker/registration](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go)
144144
oasis_worker_node_status_runtime_suspended | Gauge | Runtime node suspension status (binary). | runtime | [worker/registration](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go)
145-
oasis_worker_processed_block_count | Counter | Number of processed roothash blocks. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go)
145+
oasis_worker_processed_block_count | Counter | Number of processed roothash blocks. | runtime | [worker/common/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/metrics.go)
146146
oasis_worker_processed_event_count | Counter | Number of processed roothash events. | runtime | [worker/compute/executor/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go)
147147
oasis_worker_storage_commit_latency | Summary | Latency of storage commit calls (state + outputs) (seconds). | runtime | [worker/compute/executor/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go)
148148
oasis_worker_storage_full_round | Gauge | The last round that was fully synced and finalized. | runtime | [worker/storage/committee](https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go)

go/runtime/api/info.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ type BlockInfo struct {
2121

2222
// Epoch is the epoch the runtime block belongs to.
2323
Epoch beacon.EpochTime
24+
}
25+
26+
// DispatchInfo provides the context for checking, executing, or scheduling
27+
// a batch of transactions.
28+
type DispatchInfo struct {
29+
// BlockInfo holds information about the latest runtime block.
30+
BlockInfo *BlockInfo
2431

25-
// ActiveDescriptor is the runtime descriptor active for the runtime block.
32+
// ActiveDescriptor is the runtime descriptor currently in use for dispatch.
2633
ActiveDescriptor *registry.Runtime
2734
}

go/runtime/txpool/txpool.go

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
1515
"github.com/oasisprotocol/oasis-core/go/common/logging"
1616
"github.com/oasisprotocol/oasis-core/go/common/pubsub"
17-
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
1817
"github.com/oasisprotocol/oasis-core/go/roothash/api/message"
1918
runtime "github.com/oasisprotocol/oasis-core/go/runtime/api"
2019
"github.com/oasisprotocol/oasis-core/go/runtime/history"
@@ -107,8 +106,11 @@ type TransactionPool interface {
107106
// and only the following transactions will be returned.
108107
GetSchedulingExtra(offset *hash.Hash, limit int) []*TxQueueMeta
109108

110-
// ProcessBlock updates the last known runtime block information.
111-
ProcessBlock(bi *runtime.BlockInfo)
109+
// RecheckTxs triggers a recheck of all transactions.
110+
RecheckTxs()
111+
112+
// ProcessDispatchInfo updates the last known runtime dispatch information.
113+
ProcessDispatchInfo(di *runtime.DispatchInfo)
112114

113115
// ProcessIncomingMessages loads transactions from incoming messages into the pool.
114116
ProcessIncomingMessages(inMsgs []*message.IncomingMessage)
@@ -158,10 +160,10 @@ type txPool struct {
158160
proposedTxsLock sync.Mutex
159161
proposedTxs map[hash.Hash]*TxQueueMeta
160162

161-
blockInfoLock sync.Mutex
162-
blockInfo *runtime.BlockInfo
163-
lastBlockProcessed time.Time
164-
lastRecheckRound uint64
163+
dispatchInfoLock sync.Mutex
164+
dispatchInfo *runtime.DispatchInfo
165+
lastDispatchInfoProcessed time.Time
166+
lastRecheckRound uint64
165167

166168
republishCh *channels.RingChannel
167169
}
@@ -385,24 +387,39 @@ HASH_LOOP:
385387
return txs, missingTxs
386388
}
387389

388-
func (t *txPool) ProcessBlock(bi *runtime.BlockInfo) {
389-
t.blockInfoLock.Lock()
390-
defer t.blockInfoLock.Unlock()
390+
func (t *txPool) ProcessDispatchInfo(di *runtime.DispatchInfo) {
391+
t.dispatchInfoLock.Lock()
392+
defer t.dispatchInfoLock.Unlock()
391393

392-
if t.blockInfo == nil {
394+
if t.dispatchInfo == nil {
393395
close(t.initCh)
394396
}
395397

396-
t.blockInfo = bi
397-
t.lastBlockProcessed = time.Now()
398+
t.dispatchInfo = di
399+
t.lastDispatchInfoProcessed = time.Now()
400+
401+
roundDifference := di.BlockInfo.RuntimeBlock.Header.Round - t.lastRecheckRound
402+
if roundDifference > t.cfg.RecheckInterval {
403+
t.recheckTxsLocked()
404+
}
405+
}
406+
407+
func (t *txPool) RecheckTxs() {
408+
t.dispatchInfoLock.Lock()
409+
defer t.dispatchInfoLock.Unlock()
410+
411+
t.recheckTxsLocked()
412+
}
398413

399-
// Force transaction rechecks on epoch transitions and if needed.
400-
isEpochTransition := bi.RuntimeBlock.Header.HeaderType == block.EpochTransition
401-
roundDifference := bi.RuntimeBlock.Header.Round - t.lastRecheckRound
402-
if isEpochTransition || roundDifference > t.cfg.RecheckInterval {
403-
t.recheckTxCh.In() <- struct{}{}
404-
t.lastRecheckRound = bi.RuntimeBlock.Header.Round
414+
func (t *txPool) recheckTxsLocked() {
415+
select {
416+
case <-t.initCh:
417+
default:
418+
return
405419
}
420+
421+
t.recheckTxCh.In() <- struct{}{}
422+
t.lastRecheckRound = t.dispatchInfo.BlockInfo.RuntimeBlock.Header.Round
406423
}
407424

408425
func (t *txPool) ProcessIncomingMessages(inMsgs []*message.IncomingMessage) {
@@ -427,14 +444,14 @@ func (t *txPool) All() [][]byte {
427444
return txs
428445
}
429446

430-
func (t *txPool) getCurrentBlockInfo() (*runtime.BlockInfo, time.Time, error) {
431-
t.blockInfoLock.Lock()
432-
defer t.blockInfoLock.Unlock()
447+
func (t *txPool) getCurrentDispatchInfo() (*runtime.DispatchInfo, time.Time, error) {
448+
t.dispatchInfoLock.Lock()
449+
defer t.dispatchInfoLock.Unlock()
433450

434-
if t.blockInfo == nil {
435-
return nil, time.Time{}, fmt.Errorf("no current block available")
451+
if t.dispatchInfo == nil {
452+
return nil, time.Time{}, fmt.Errorf("no current dispatch info available")
436453
}
437-
return t.blockInfo, t.lastBlockProcessed, nil
454+
return t.dispatchInfo, t.lastDispatchInfoProcessed, nil
438455
}
439456

440457
// checkTxBatch requests the runtime to check the validity of a transaction batch.
@@ -445,22 +462,22 @@ func (t *txPool) checkTxBatch(ctx context.Context) error {
445462
return fmt.Errorf("runtime is not available")
446463
}
447464

448-
// Get the current block info.
449-
bi, lastBlockProcessed, err := t.getCurrentBlockInfo()
465+
// Get the current dispatch info.
466+
di, lastDispatchInfoProcessed, err := t.getCurrentDispatchInfo()
450467
if err != nil {
451-
return fmt.Errorf("failed to get current block info: %w", err)
468+
return fmt.Errorf("failed to get current dispatch info: %w", err)
452469
}
453470

454471
// Ensure block round is synced to storage.
455472
waitSyncCtx, cancelWaitSyncCtx := context.WithTimeout(ctx, checkTxWaitRoundSyncedTimeout)
456473
defer cancelWaitSyncCtx()
457474

458-
t.logger.Debug("ensuring block round is synced", "round", bi.RuntimeBlock.Header.Round)
459-
if _, err = t.history.WaitRoundSynced(waitSyncCtx, bi.RuntimeBlock.Header.Round); err != nil {
475+
t.logger.Debug("ensuring block round is synced", "round", di.BlockInfo.RuntimeBlock.Header.Round)
476+
if _, err = t.history.WaitRoundSynced(waitSyncCtx, di.BlockInfo.RuntimeBlock.Header.Round); err != nil {
460477
// Block round isn't synced yet, so make sure the batch check is
461478
// retried later to avoid aborting the runtime, as it is not its fault.
462479
t.logger.Info("block round is not synced yet, retrying transaction batch check later",
463-
"round", bi.RuntimeBlock.Header.Round,
480+
"round", di.BlockInfo.RuntimeBlock.Header.Round,
464481
"err", err,
465482
)
466483
t.checkTxCh.In() <- struct{}{}
@@ -482,7 +499,7 @@ func (t *txPool) checkTxBatch(ctx context.Context) error {
482499
for _, pct := range batch {
483500
rawTxBatch = append(rawTxBatch, pct.Raw())
484501
}
485-
return t.runtime.CheckTx(checkCtx, bi.RuntimeBlock, bi.ConsensusBlock, bi.Epoch, bi.ActiveDescriptor.Executor.MaxMessages, rawTxBatch)
502+
return t.runtime.CheckTx(checkCtx, di.BlockInfo.RuntimeBlock, di.BlockInfo.ConsensusBlock, di.BlockInfo.Epoch, di.ActiveDescriptor.Executor.MaxMessages, rawTxBatch)
486503
}()
487504
switch {
488505
case err == nil:
@@ -625,7 +642,7 @@ func (t *txPool) checkTxBatch(ctx context.Context) error {
625642
// Kick off publishing for any new txs after waiting for block publish delay based on when
626643
// we received the block that we just used to check the transaction batch.
627644
go func() {
628-
time.Sleep(time.Until(lastBlockProcessed.Add(newBlockPublishDelay)))
645+
time.Sleep(time.Until(lastDispatchInfoProcessed.Add(newBlockPublishDelay)))
629646
t.republishCh.In() <- struct{}{}
630647
}()
631648

go/worker/client/committee/node.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
cmnBackoff "github.com/oasisprotocol/oasis-core/go/common/backoff"
1313
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
1414
"github.com/oasisprotocol/oasis-core/go/common/logging"
15+
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
16+
roothash "github.com/oasisprotocol/oasis-core/go/roothash/api"
1517
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
1618
runtime "github.com/oasisprotocol/oasis-core/go/runtime/api"
1719
"github.com/oasisprotocol/oasis-core/go/runtime/bundle/component"
@@ -79,13 +81,13 @@ func (n *Node) Initialized() <-chan struct{} {
7981
return n.initCh
8082
}
8183

82-
// HandleNewBlockLocked is guarded by CrossNode.
83-
func (n *Node) HandleNewBlockLocked(*runtime.BlockInfo) {
84+
// HandleNewDispatchInfo implements NodeHooks.
85+
func (n *Node) HandleNewDispatchInfo(*runtime.DispatchInfo) {
8486
// Nothing to do here.
8587
}
8688

87-
// HandleRuntimeHostEventLocked is guarded by CrossNode.
88-
func (n *Node) HandleRuntimeHostEventLocked(ev *host.Event) {
89+
// HandleRuntimeHostEvent implements NodeHooks.
90+
func (n *Node) HandleRuntimeHostEvent(ev *host.Event) {
8991
if n.roleProvider == nil {
9092
return
9193
}
@@ -169,15 +171,14 @@ func (n *Node) CheckTx(ctx context.Context, tx []byte) (*protocol.CheckTxResult,
169171
func (n *Node) Query(ctx context.Context, round uint64, method string, args []byte, comp *component.ID) ([]byte, error) {
170172
hrt := n.commonNode.GetHostedRuntime()
171173

172-
// Fetch the active descriptor so we can get the current message limits.
173-
n.commonNode.CrossNode.Lock()
174-
dsc := n.commonNode.CurrentDescriptor
175-
n.commonNode.CrossNode.Unlock()
176-
177-
if dsc == nil {
178-
return nil, api.ErrNoHostedRuntime
174+
rs, err := n.commonNode.Consensus.RootHash().GetRuntimeState(ctx, &roothash.RuntimeRequest{
175+
RuntimeID: n.commonNode.Runtime.ID(),
176+
Height: consensus.HeightLatest,
177+
})
178+
if err != nil {
179+
return nil, fmt.Errorf("client: failed to get runtime state: %w", err)
179180
}
180-
maxMessages := dsc.Executor.MaxMessages
181+
maxMessages := rs.Runtime.Executor.MaxMessages
181182

182183
annBlk, err := n.commonNode.Runtime.History().GetAnnotatedBlock(ctx, round)
183184
if err != nil {

go/worker/client/worker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func (w *Worker) registerRuntime(commonNode *committeeCommon.Node) error {
148148
// leave it like that before initialization starts, so the registration
149149
// is blocked until the runtime finishes initializing.
150150
// The availability of the role provider is changed in
151-
// HandleRuntimeHostEventLocked in worker/client/committee/node.go.
151+
// HandleRuntimeHostEvent in worker/client/committee/node.go.
152152
default:
153153
}
154154

go/worker/common/committee/group.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,13 @@ func (g *Group) Suspend() {
140140
g.committee = nil
141141
}
142142

143-
// EpochTransition processes an epoch transition that just happened.
144-
func (g *Group) EpochTransition(ctx context.Context, committee *scheduler.Committee) error {
143+
// CommitteeTransition processes a committee transition that just happened.
144+
func (g *Group) CommitteeTransition(ctx context.Context, committee *scheduler.Committee) error {
145145
g.Lock()
146146
defer g.Unlock()
147147

148+
g.logger.Info("committee transition")
149+
148150
// Invalidate current committee. In case we cannot process this transition,
149151
// this should cause the node to transition into NotReady and stay there
150152
// until the next epoch transition.
@@ -203,7 +205,7 @@ func (g *Group) EpochTransition(ctx context.Context, committee *scheduler.Commit
203205
nodes: g.nodes,
204206
}
205207

206-
g.logger.Info("epoch transition complete",
208+
g.logger.Info("committee transition complete",
207209
"epoch", epochNumber,
208210
"executor_roles", g.committee.Roles,
209211
)

0 commit comments

Comments
 (0)