Skip to content

Commit

Permalink
Defer genesis events to first begin block
Browse files Browse the repository at this point in the history
  • Loading branch information
plaidfinch committed May 29, 2024
1 parent 35624bb commit 79e63d1
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
34 changes: 34 additions & 0 deletions crates/core/app/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use penumbra_stake::component::{
use penumbra_transaction::Transaction;
use prost::Message as _;
use tendermint::abci::{self, Event};
use tendermint_proto::v0_34::abci::Event as ProtoEvent;

use tendermint::v0_37::abci::{request, response};
use tendermint::validator::Update;
Expand Down Expand Up @@ -151,6 +152,22 @@ impl App {
}
};

// Apply the state from `init_chain` and return the events generated during genesis. These
// cannot be emitted at this time due to a limitation of ABCI, but they will be emitted
// during the first BeginBlock.
let events = state_tx.apply().1;

// Commit the genesis events to the state.
let mut state_tx = self
.state
.try_begin_transaction()
.expect("state Arc should not be referenced elsewhere");
for (i, event) in events.into_iter().enumerate() {
let mut event_bytes = Vec::new();
tendermint_proto::Protobuf::<ProtoEvent>::encode(event, &mut event_bytes)
.expect("events are always valid and can be encoded");
state_tx.nonverifiable_put_raw(state_key::deferred_event(i), event_bytes);
}
state_tx.apply();
}

Expand Down Expand Up @@ -219,6 +236,23 @@ impl App {
pub async fn begin_block(&mut self, begin_block: &request::BeginBlock) -> Vec<abci::Event> {
let mut state_tx = StateDelta::new(self.state.clone());

// Before anything else, emit the deferred events (only present if right after genesis), and
// delete each one to prevent it from being emitted again.
for i in 0.. {
if let Some(event_bytes) = state_tx
.nonverifiable_get_raw(&state_key::deferred_event(i))
.await
.expect("can attempt to get deferred event")
{
let event = tendermint_proto::Protobuf::<ProtoEvent>::decode(&event_bytes[..])
.expect("deferred event is always valid");
state_tx.record(event);
state_tx.nonverifiable_delete(state_key::deferred_event(i));
} else {
break;
}
}

// If a app parameter change is scheduled for this block, apply it here,
// before any other component has executed. This ensures that app
// parameter changes are consistently applied precisely at the boundary
Expand Down
6 changes: 6 additions & 0 deletions crates/core/app/src/app/state_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ pub mod data {
}
}

pub fn deferred_event(index: usize) -> Vec<u8> {
format!("application/deferred_events/{index}")
.as_bytes()
.to_vec()
}

pub mod cometbft_data {
use crate::COMETBFT_SUBSTORE_PREFIX;

Expand Down

0 comments on commit 79e63d1

Please sign in to comment.