Skip to content

Commit f4d4ecc

Browse files
committed
go/consensus/cometbft/abci: Include all events in the events root
The events root in block metadata system transaction now includes all events, not just provable ones.
1 parent 21a9a4f commit f4d4ecc

7 files changed

Lines changed: 76 additions & 53 deletions

File tree

.changelog/6289.breaking.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
go/consensus/cometbft/abci: Include all events in the events root
2+
3+
The events root in block metadata system transaction now includes all events,
4+
not just provable ones.

go/consensus/api/meta.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const BlockMetadataMaxSize = 16_384
2323
type BlockMetadata struct {
2424
// StateRoot is the state root after executing all logic in the block.
2525
StateRoot hash.Hash `json:"state_root"`
26-
// EventsRoot is the provable events root.
26+
// EventsRoot is the root hash of all events emitted in the block.
2727
EventsRoot []byte `json:"events_root"`
2828
}
2929

go/consensus/cometbft/abci/mux.go

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -531,28 +531,25 @@ func (mux *abciMux) executeProposal(
531531
mux.state.resetProposal()
532532
mux.state.proposal.hash = hash
533533

534-
resultsBeginBlock := mux.BeginBlock(types.RequestBeginBlock{
534+
// The proposal is updated inside every call, as the end block phase
535+
// requires these results immediately to validate system transactions.
536+
mux.BeginBlock(types.RequestBeginBlock{
535537
Hash: hash,
536538
Header: header,
537539
LastCommitInfo: lastCommit,
538540
ByzantineValidators: misbehavior,
539541
})
540542

541-
resultsDeliverTx := make([]*types.ResponseDeliverTx, 0, len(txs))
542543
for _, tx := range txs {
543-
resp := mux.DeliverTx(types.RequestDeliverTx{
544+
mux.DeliverTx(types.RequestDeliverTx{
544545
Tx: tx,
545546
})
546-
resultsDeliverTx = append(resultsDeliverTx, &resp)
547547
}
548548

549-
resultsEndBlock := mux.EndBlock(types.RequestEndBlock{
549+
mux.EndBlock(types.RequestEndBlock{
550550
Height: header.Height,
551551
})
552552

553-
// Update the proposal with results, marking the proposal as executed.
554-
mux.state.proposal.setResults(&resultsBeginBlock, resultsDeliverTx, &resultsEndBlock)
555-
556553
return nil
557554
}
558555

@@ -638,19 +635,22 @@ func (mux *abciMux) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginB
638635
}
639636
}
640637

641-
response := mux.BaseApplication.BeginBlock(req)
638+
result := mux.BaseApplication.BeginBlock(req)
642639

643640
// During the first block, also collect and prepend application events generated during
644641
// InitChain to BeginBlock events.
645642
if mux.state.BlockHeight() == 0 {
646-
response.Events = append(response.Events, mux.state.initEvents...)
643+
result.Events = append(result.Events, mux.state.initEvents...)
647644
}
648645

649646
// Collect and return events from the application's BeginBlock calls.
650-
response.Events = append(response.Events, ctx.GetEvents()...)
647+
result.Events = append(result.Events, ctx.GetEvents()...)
651648
mux.processProvableEvents(ctx)
652649

653-
return response
650+
// Update the proposal.
651+
mux.state.proposal.resultsBeginBlock = &result
652+
653+
return result
654654
}
655655

656656
func (mux *abciMux) notifyInvalidatedCheckTx(txHash hash.Hash, err error) {
@@ -715,7 +715,17 @@ func (mux *abciMux) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverT
715715
ctx := mux.state.NewContext(api.ContextDeliverTx)
716716
defer ctx.Close()
717717

718-
if err := mux.executeTx(ctx, req.Tx); err != nil {
718+
var results types.ResponseDeliverTx
719+
switch err := mux.executeTx(ctx, req.Tx); err {
720+
case nil:
721+
results = types.ResponseDeliverTx{
722+
Code: types.CodeTypeOK,
723+
Data: cbor.Marshal(ctx.Data()),
724+
Events: ctx.GetEvents(),
725+
GasWanted: int64(ctx.Gas().GasWanted()),
726+
GasUsed: int64(ctx.Gas().GasUsed()),
727+
}
728+
default:
719729
if api.IsUnavailableStateError(err) {
720730
// Make sure to not commit any transactions which include results based on unavailable
721731
// and/or corrupted state -- doing so can further corrupt state.
@@ -726,9 +736,7 @@ func (mux *abciMux) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverT
726736
}
727737
module, code := errors.Code(err)
728738

729-
mux.processProvableEvents(ctx)
730-
731-
return types.ResponseDeliverTx{
739+
results = types.ResponseDeliverTx{
732740
Codespace: module,
733741
Code: code,
734742
Log: err.Error(),
@@ -740,13 +748,10 @@ func (mux *abciMux) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverT
740748

741749
mux.processProvableEvents(ctx)
742750

743-
return types.ResponseDeliverTx{
744-
Code: types.CodeTypeOK,
745-
Data: cbor.Marshal(ctx.Data()),
746-
Events: ctx.GetEvents(),
747-
GasWanted: int64(ctx.Gas().GasWanted()),
748-
GasUsed: int64(ctx.Gas().GasUsed()),
749-
}
751+
// Update the proposal.
752+
mux.state.proposal.resultsDeliverTx = append(mux.state.proposal.resultsDeliverTx, &results)
753+
754+
return results
750755
}
751756

752757
func (mux *abciMux) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
@@ -768,9 +773,9 @@ func (mux *abciMux) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
768773
defer ctx.Close()
769774

770775
// Dispatch EndBlock to all applications.
771-
resp := mux.BaseApplication.EndBlock(req)
776+
results := mux.BaseApplication.EndBlock(req)
772777
for _, app := range mux.appsByLexOrder {
773-
newResp, err := app.EndBlock(ctx)
778+
newResults, err := app.EndBlock(ctx)
774779
if err != nil {
775780
mux.logger.Error("EndBlock: fatal error in application",
776781
"err", err,
@@ -779,7 +784,7 @@ func (mux *abciMux) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
779784
panic(fmt.Errorf("mux: EndBlock: fatal error in application: '%s': %w", app.Name(), err))
780785
}
781786
if app.Blessed() {
782-
resp = newResp
787+
results = newResults
783788
}
784789
}
785790

@@ -798,22 +803,25 @@ func (mux *abciMux) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
798803
}
799804

800805
// Collect and return events.
801-
resp.Events = ctx.GetEvents()
806+
results.Events = ctx.GetEvents()
802807
mux.processProvableEvents(ctx)
803808

804809
// Update version to what we are actually running.
805-
resp.ConsensusParamUpdates = &cmtproto.ConsensusParams{
810+
results.ConsensusParamUpdates = &cmtproto.ConsensusParams{
806811
Version: &cmtproto.VersionParams{
807812
App: version.CometBFTAppVersion,
808813
},
809814
}
810815

816+
// Update the proposal.
817+
mux.state.proposal.resultsEndBlock = &results
818+
811819
// Validate system transactions included by the proposer.
812820
if err := mux.validateSystemTxs(); err != nil {
813821
panic(fmt.Errorf("proposed block has invalid system transactions: %w", err))
814822
}
815823

816-
return resp
824+
return results
817825
}
818826

819827
func (mux *abciMux) Commit() types.ResponseCommit {

go/consensus/cometbft/abci/state.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,6 @@ func (ps *proposalState) needsExecution() bool {
112112
return ps.resultsBeginBlock == nil || ps.resultsDeliverTx == nil || ps.resultsEndBlock == nil
113113
}
114114

115-
// setResults sets the proposal execution results.
116-
func (ps *proposalState) setResults(
117-
resultsBeginBlock *types.ResponseBeginBlock,
118-
resultsDeliverTx []*types.ResponseDeliverTx,
119-
resultsEndBlock *types.ResponseEndBlock,
120-
) {
121-
ps.resultsBeginBlock = resultsBeginBlock
122-
ps.resultsDeliverTx = resultsDeliverTx
123-
ps.resultsEndBlock = resultsEndBlock
124-
}
125-
126115
type applicationState struct { // nolint: maligned
127116
logger *logging.Logger
128117

go/consensus/cometbft/abci/system.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
1414
cmtcrypto "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/crypto"
1515
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/crypto/merkle"
16+
"github.com/oasisprotocol/oasis-core/go/upgrade/migrations"
1617
)
1718

1819
// prepareSystemTxs prepares a list of system transactions to be included in a proposed block in
@@ -28,9 +29,9 @@ func (mux *abciMux) prepareSystemTxs() ([][]byte, []*types.ResponseDeliverTx, er
2829
if err != nil {
2930
return nil, nil, fmt.Errorf("failed to compute working state root: %w", err)
3031
}
31-
eventsRoot, err := mux.computeProvableEventsRoot()
32+
eventsRoot, err := mux.computeEventsRoot()
3233
if err != nil {
33-
return nil, nil, fmt.Errorf("failed to compute provable events root: %w", err)
34+
return nil, nil, fmt.Errorf("failed to compute events root: %w", err)
3435
}
3536

3637
blockMeta := consensus.NewBlockMetadataTx(&consensus.BlockMetadata{
@@ -124,10 +125,10 @@ func (mux *abciMux) validateSystemTxs() error {
124125
return fmt.Errorf("invalid state root in block metadata (expected: %s got: %s)", stateRoot, meta.StateRoot)
125126
}
126127

127-
// Verify provable events root.
128-
eventsRoot, err := mux.computeProvableEventsRoot()
128+
// Verify events root.
129+
eventsRoot, err := mux.computeEventsRoot()
129130
if err != nil {
130-
return fmt.Errorf("failed to compute provable events root: %w", err)
131+
return fmt.Errorf("failed to compute events root: %w", err)
131132
}
132133
if !bytes.Equal(eventsRoot, meta.EventsRoot) {
133134
return fmt.Errorf("invalid events root in block metadata (expected: %x got: %x)", eventsRoot, meta.EventsRoot)
@@ -148,11 +149,30 @@ func (mux *abciMux) validateSystemTxs() error {
148149
return nil
149150
}
150151

151-
func (mux *abciMux) computeProvableEventsRoot() ([]byte, error) {
152-
provable := mux.state.blockCtx.ProvableEvents
153-
provableEvents := make([][]byte, len(provable))
154-
for i, pe := range provable {
155-
provableEvents[i] = cbor.Marshal(pe.ProvableRepresentation())
152+
func (mux *abciMux) computeEventsRoot() ([]byte, error) {
153+
if !mux.state.ConsensusParameters().IsFeatureVersion(migrations.Version256) {
154+
// Events root used to be computed only from provable events.
155+
provable := mux.state.blockCtx.ProvableEvents
156+
provableEvents := make([][]byte, len(provable))
157+
for i, pe := range provable {
158+
provableEvents[i] = cbor.Marshal(pe.ProvableRepresentation())
159+
}
160+
return merkle.RootHash(provableEvents), nil
161+
}
162+
163+
// Events root is now computed from all emitted events.
164+
var events [][]byte
165+
for _, ev := range mux.state.proposal.resultsBeginBlock.Events {
166+
events = append(events, cbor.Marshal(ev))
156167
}
157-
return merkle.RootHash(provableEvents), nil
168+
for _, res := range mux.state.proposal.resultsDeliverTx {
169+
for _, ev := range res.Events {
170+
events = append(events, cbor.Marshal(ev))
171+
}
172+
}
173+
for _, ev := range mux.state.proposal.resultsEndBlock.Events {
174+
events = append(events, cbor.Marshal(ev))
175+
}
176+
177+
return merkle.RootHash(events), nil
158178
}

go/upgrade/migrations/consensus_256.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
// This upgrade includes:
1515
// - The `MayQuery“ field in the CHURP SGX policy, which defines which enclave identities
1616
// are allowed to query runtime key shares.
17+
// - An updated events root in the block metadata system transaction to capture all events
18+
// emitted in the block.
1719
const Consensus256 = "consensus256"
1820

1921
// Version256 is the Oasis Core 25.6 version.

runtime/src/consensus/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ pub enum Event {
4747
pub struct BlockMetadata {
4848
/// State root after executing all logic in the block.
4949
pub state_root: Hash,
50-
// EventsRoot is the provable events root.
50+
// Root hash of all events emitted in the block.
5151
pub events_root: Vec<u8>,
5252
}

0 commit comments

Comments
 (0)