Skip to content

Commit d038a34

Browse files
committed
feat(transition_frontier): avoid proving genesis until we have to, two minutes before the won slot
1 parent 95d965b commit d038a34

File tree

10 files changed

+99
-53
lines changed

10 files changed

+99
-53
lines changed

node/src/action_kind.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ pub enum ActionKind {
615615
TransactionPoolVerifyError,
616616
TransactionPoolEffectfulFetchAccounts,
617617
TransitionFrontierGenesisInject,
618+
TransitionFrontierGenesisProvenInject,
618619
TransitionFrontierSyncFailed,
619620
TransitionFrontierSynced,
620621
TransitionFrontierGenesisLedgerLoadInit,
@@ -704,7 +705,7 @@ pub enum ActionKind {
704705
}
705706

706707
impl ActionKind {
707-
pub const COUNT: u16 = 589;
708+
pub const COUNT: u16 = 590;
708709
}
709710

710711
impl std::fmt::Display for ActionKind {
@@ -858,6 +859,7 @@ impl ActionKindGet for TransitionFrontierAction {
858859
Self::GenesisEffect(a) => a.kind(),
859860
Self::Sync(a) => a.kind(),
860861
Self::GenesisInject => ActionKind::TransitionFrontierGenesisInject,
862+
Self::GenesisProvenInject => ActionKind::TransitionFrontierGenesisProvenInject,
861863
Self::Synced { .. } => ActionKind::TransitionFrontierSynced,
862864
Self::SyncFailed { .. } => ActionKind::TransitionFrontierSyncFailed,
863865
}

node/src/block_producer/block_producer_actions.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use ledger::scan_state::transaction_logic::valid;
24
use mina_p2p_messages::v2::MinaBaseProofStableV2;
35
use openmina_core::block::ArcBlockWithHash;
@@ -100,9 +102,18 @@ impl redux::EnablingCondition<crate::State> for BlockProducerAction {
100102
BlockProducerAction::WonSlotWait => state
101103
.block_producer
102104
.with(false, |this| this.current.won_slot_should_wait(time)),
103-
BlockProducerAction::WonSlotProduceInit { .. } => state
104-
.block_producer
105-
.with(false, |this| this.current.won_slot_should_produce(time)),
105+
BlockProducerAction::WonSlotProduceInit { .. } => {
106+
state.block_producer.with(false, |this| {
107+
let has_genesis_proven_if_needed = || {
108+
state.transition_frontier.best_tip().map_or(false, |tip| {
109+
let proven_block = state.transition_frontier.genesis.proven_block();
110+
!tip.is_genesis()
111+
|| proven_block.map_or(false, |b| Arc::ptr_eq(&b.block, &tip.block))
112+
})
113+
};
114+
this.current.won_slot_should_produce(time) && has_genesis_proven_if_needed()
115+
})
116+
}
106117
BlockProducerAction::WonSlotTransactionsGet => {
107118
state.block_producer.with(false, |this| {
108119
matches!(

node/src/block_producer/block_producer_reducer.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,29 @@ impl BlockProducerEnabled {
104104
};
105105
}
106106
}
107+
BlockProducerAction::WonSlotProduceInit => {
108+
if let Some(won_slot) = state.current.won_slot() {
109+
if let Some(chain) = best_chain.last().map(|best_tip| {
110+
if best_tip.global_slot() == won_slot.global_slot() {
111+
best_chain
112+
.get(..best_chain.len().saturating_sub(1))
113+
.unwrap_or(&[])
114+
.to_vec()
115+
} else {
116+
best_chain.to_vec()
117+
}
118+
}) {
119+
state.current = BlockProducerCurrentState::WonSlotProduceInit {
120+
time: meta.time(),
121+
won_slot: won_slot.clone(),
122+
chain,
123+
};
124+
};
125+
}
126+
127+
let dispatcher = state_context.into_dispatcher();
128+
dispatcher.push(BlockProducerAction::WonSlotTransactionsGet);
129+
}
107130
BlockProducerAction::WonSlotTransactionsGet => {
108131
let BlockProducerCurrentState::WonSlotProduceInit {
109132
won_slot, chain, ..
@@ -141,29 +164,6 @@ impl BlockProducerEnabled {
141164
let dispatcher = state_context.into_dispatcher();
142165
dispatcher.push(BlockProducerAction::StagedLedgerDiffCreateInit);
143166
}
144-
BlockProducerAction::WonSlotProduceInit => {
145-
if let Some(won_slot) = state.current.won_slot() {
146-
if let Some(chain) = best_chain.last().map(|best_tip| {
147-
if best_tip.global_slot() == won_slot.global_slot() {
148-
best_chain
149-
.get(..best_chain.len().saturating_sub(1))
150-
.unwrap_or(&[])
151-
.to_vec()
152-
} else {
153-
best_chain.to_vec()
154-
}
155-
}) {
156-
state.current = BlockProducerCurrentState::WonSlotProduceInit {
157-
time: meta.time(),
158-
won_slot: won_slot.clone(),
159-
chain,
160-
};
161-
};
162-
}
163-
164-
let dispatcher = state_context.into_dispatcher();
165-
dispatcher.push(BlockProducerAction::WonSlotTransactionsGet);
166-
}
167167
BlockProducerAction::StagedLedgerDiffCreateInit => {
168168
let dispatcher = state_context.into_dispatcher();
169169
dispatcher.push(BlockProducerEffectfulAction::StagedLedgerDiffCreateInit);

node/src/block_producer/block_producer_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ impl BlockProducerCurrentState {
296296
#[cfg(not(target_arch = "wasm32"))]
297297
const BLOCK_PRODUCTION_ESTIMATE: u64 = Duration::from_secs(5).as_nanos() as u64;
298298
#[cfg(target_arch = "wasm32")]
299-
const BLOCK_PRODUCTION_ESTIMATE: u64 = Duration::from_secs(20).as_nanos() as u64;
299+
const BLOCK_PRODUCTION_ESTIMATE: u64 = Duration::from_secs(18).as_nanos() as u64;
300300

301301
let slot_interval = Duration::from_secs(3 * 60).as_nanos() as u64;
302302
match self {

node/src/effects.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub fn effects<S: Service>(store: &mut Store<S>, action: ActionWithMeta) {
3737
store.dispatch(TransitionFrontierGenesisAction::LedgerLoadInit);
3838
store.dispatch(ExternalSnarkWorkerAction::Start);
3939

40+
store.dispatch(TransitionFrontierGenesisAction::ProveInit);
41+
4042
if store.state().p2p.ready().is_some() {
4143
p2p_request_best_tip_if_needed(store);
4244
p2p_request_transactions_if_needed(store);

node/src/state.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::sync::Arc;
2+
use std::time::Duration;
23

34
use mina_p2p_messages::v2::{MinaBaseUserCommandStableV2, MinaBlockBlockStableV2};
45
use rand::prelude::*;
@@ -333,17 +334,19 @@ impl State {
333334
)
334335
}
335336

336-
pub fn should_produce_blocks_after_genesis(&self) -> bool {
337-
self.block_producer.is_enabled()
338-
&& self.genesis_block().map_or(false, |b| {
339-
let slot = &b.consensus_state().curr_global_slot_since_hard_fork;
340-
let epoch = slot
341-
.slot_number
342-
.as_u32()
343-
.checked_div(slot.slots_per_epoch.as_u32())
344-
.expect("division by 0");
345-
self.current_epoch() <= Some(epoch)
346-
})
337+
pub fn producing_block_after_genesis(&self) -> bool {
338+
let two_mins_in_future = self.time() + Duration::from_secs(2 * 60);
339+
self.block_producer.with(false, |bp| {
340+
bp.current.won_slot_should_produce(two_mins_in_future)
341+
}) && self.genesis_block().map_or(false, |b| {
342+
let slot = &b.consensus_state().curr_global_slot_since_hard_fork;
343+
let epoch = slot
344+
.slot_number
345+
.as_u32()
346+
.checked_div(slot.slots_per_epoch.as_u32())
347+
.expect("division by 0");
348+
self.current_epoch() <= Some(epoch)
349+
})
347350
}
348351

349352
pub fn should_log_node_id(&self) -> bool {

node/src/transition_frontier/genesis/transition_frontier_genesis_actions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl redux::EnablingCondition<crate::State> for TransitionFrontierGenesisAction
5151
TransitionFrontierGenesisState::LedgerLoadSuccess { .. }
5252
),
5353
TransitionFrontierGenesisAction::ProveInit => {
54-
state.should_produce_blocks_after_genesis()
54+
state.producing_block_after_genesis()
5555
&& matches!(
5656
genesis_state,
5757
TransitionFrontierGenesisState::Produced { .. }

node/src/transition_frontier/transition_frontier_actions.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::BTreeSet;
2+
use std::sync::Arc;
23

34
use mina_p2p_messages::v2::StateHash;
45
use openmina_core::block::ArcBlockWithHash;
@@ -25,6 +26,8 @@ pub enum TransitionFrontierAction {
2526
/// block, otherwise we don't need it so we use dummy proof instead.
2627
#[action_event(level = info)]
2728
GenesisInject,
29+
#[action_event(level = info)]
30+
GenesisProvenInject,
2831

2932
Sync(TransitionFrontierSyncAction),
3033
/// Transition frontier synced.
@@ -44,15 +47,20 @@ impl redux::EnablingCondition<crate::State> for TransitionFrontierAction {
4447
TransitionFrontierAction::Genesis(a) => a.is_enabled(state, time),
4548
TransitionFrontierAction::GenesisEffect(a) => a.is_enabled(state, time),
4649
TransitionFrontierAction::GenesisInject => {
47-
if state.transition_frontier.best_tip().is_some() {
50+
state.transition_frontier.root().is_none()
51+
&& state
52+
.transition_frontier
53+
.genesis
54+
.block_with_real_or_dummy_proof()
55+
.is_some()
56+
}
57+
TransitionFrontierAction::GenesisProvenInject => {
58+
let Some(genesis) = state.transition_frontier.genesis.proven_block() else {
4859
return false;
49-
}
50-
let genesis_state = &state.transition_frontier.genesis;
51-
if state.should_produce_blocks_after_genesis() {
52-
genesis_state.proven_block().is_some()
53-
} else {
54-
genesis_state.block_with_dummy_proof().is_some()
55-
}
60+
};
61+
state.transition_frontier.root().map_or(true, |b| {
62+
b.is_genesis() && !Arc::ptr_eq(&genesis.block, &b.block)
63+
})
5664
}
5765
TransitionFrontierAction::Sync(a) => a.is_enabled(state, time),
5866
TransitionFrontierAction::Synced { .. } => matches!(

node/src/transition_frontier/transition_frontier_effects.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ pub fn transition_frontier_effects<S: crate::Service>(
3434
// TODO(refactor): this should be handled by a callback and removed from here
3535
// whenever any of these is going to happen, genesisinject must happen first
3636
match &a {
37-
TransitionFrontierGenesisAction::Produce
38-
| TransitionFrontierGenesisAction::ProveSuccess { .. } => {
37+
TransitionFrontierGenesisAction::Produce => {
3938
store.dispatch(TransitionFrontierAction::GenesisInject);
4039
}
40+
TransitionFrontierGenesisAction::ProveSuccess { .. } => {
41+
store.dispatch(TransitionFrontierAction::GenesisProvenInject);
42+
}
4143
_ => {}
4244
}
4345
}
@@ -47,6 +49,11 @@ pub fn transition_frontier_effects<S: crate::Service>(
4749
TransitionFrontierAction::GenesisInject => {
4850
synced_effects(&meta, store);
4951
}
52+
TransitionFrontierAction::GenesisProvenInject => {
53+
if store.state().transition_frontier.sync.is_synced() {
54+
synced_effects(&meta, store);
55+
}
56+
}
5057
TransitionFrontierAction::Sync(a) => {
5158
match a {
5259
TransitionFrontierSyncAction::Init {

node/src/transition_frontier/transition_frontier_reducer.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,22 @@ impl TransitionFrontierState {
3434
block: genesis,
3535
just_emitted_a_proof: true,
3636
};
37-
let new_chain = vec![genesis];
38-
state.chain_diff = state.maybe_make_chain_diff(&new_chain);
39-
state.best_chain = new_chain;
37+
state.best_chain = vec![genesis];
38+
state.sync = TransitionFrontierSyncState::Synced { time: meta.time() };
39+
}
40+
TransitionFrontierAction::GenesisProvenInject => {
41+
let Some(genesis) = state.genesis.proven_block() else {
42+
return;
43+
};
44+
if let Some(block) = state.best_chain.get_mut(0) {
45+
block.block = genesis.clone();
46+
} else {
47+
let genesis = AppliedBlock {
48+
block: genesis.clone(),
49+
just_emitted_a_proof: true,
50+
};
51+
state.best_chain = vec![genesis];
52+
}
4053
if !state.sync.is_pending() {
4154
state.sync = TransitionFrontierSyncState::Synced { time: meta.time() };
4255
}

0 commit comments

Comments
 (0)