mina_node_common/service/
builder.rs1use ledger::proofs::provers::BlockProver;
2use mina_node::{
3 account::AccountSecretKey,
4 core::channels::mpsc,
5 ledger::{LedgerCtx, LedgerManager},
6 p2p::{
7 identity::SecretKey as P2pSecretKey,
8 service_impl::{
9 webrtc_with_libp2p::{P2pServiceCtx, P2pServiceWebrtcWithLibp2p},
10 TaskSpawner,
11 },
12 },
13 stats::Stats,
14};
15use rand::{rngs::StdRng, SeedableRng};
16use sha3::{
17 digest::{ExtendableOutput, Update},
18 Shake256,
19};
20
21use crate::{
22 rpc::{RpcSender, RpcService},
23 EventReceiver, EventSender, NodeService,
24};
25
26use super::{
27 archive::{config::ArchiveStorageOptions, ArchiveService},
28 block_producer::BlockProducerService,
29};
30
31pub struct NodeServiceCommonBuilder {
32 rng_seed: [u8; 32],
33 rng: StdRng,
34 event_sender: EventSender,
37 event_receiver: EventReceiver,
38 ledger_manager: Option<LedgerManager>,
39 block_producer: Option<BlockProducerService>,
40 archive: Option<ArchiveService>,
41 p2p: Option<P2pServiceCtx>,
42 gather_stats: bool,
43 rpc: RpcService,
44 skip_proof_verification: bool,
45}
46
47#[derive(thiserror::Error, Debug, Clone)]
48pub enum NodeServiceCommonBuildError {
49 #[error("ledger was never initialized! Please call: NodeServiceBuilder::ledger_init")]
50 LedgerNotInit,
51 #[error("p2p was never initialized! Please call: NodeServiceBuilder::p2p_init")]
52 P2pNotInit,
53}
54
55impl NodeServiceCommonBuilder {
56 pub fn new(rng_seed: [u8; 32]) -> Self {
57 let (event_sender, event_receiver) = mpsc::unbounded_channel();
58 Self {
59 rng_seed,
60 rng: StdRng::from_seed(rng_seed),
61 event_sender,
62 event_receiver: event_receiver.into(),
63 ledger_manager: None,
64 block_producer: None,
65 archive: None,
66 p2p: None,
67 rpc: RpcService::new(),
68 gather_stats: false,
69 skip_proof_verification: false,
70 }
71 }
72
73 pub fn event_sender(&self) -> &EventSender {
74 &self.event_sender
75 }
76
77 pub fn rpc_sender(&self) -> RpcSender {
78 self.rpc.req_sender()
79 }
80
81 pub fn ledger_init(&mut self) -> &mut Self {
82 let mut ctx = LedgerCtx::default();
83 ctx.set_event_sender(self.event_sender.clone());
84 if self.archive.is_some() {
85 ctx.set_archive_mode();
86 };
87 self.ledger_manager = Some(LedgerManager::spawn(ctx));
88 self
89 }
90
91 pub fn block_producer_init(
92 &mut self,
93 keypair: AccountSecretKey,
94 provers: Option<BlockProver>,
95 ) -> &mut Self {
96 self.block_producer = Some(BlockProducerService::start(
97 self.event_sender.clone(),
98 keypair,
99 provers,
100 ));
101 self
102 }
103
104 pub fn archive_init(&mut self, options: ArchiveStorageOptions, work_dir: String) -> &mut Self {
105 self.archive = Some(ArchiveService::start(options, work_dir));
106 self
107 }
108
109 pub fn p2p_init<S: TaskSpawner>(
110 &mut self,
111 secret_key: P2pSecretKey,
112 task_spawner: S,
113 ) -> &mut Self {
114 self.p2p = Some(<NodeService as P2pServiceWebrtcWithLibp2p>::init(
115 secret_key.clone(),
116 task_spawner,
117 self.rng_seed,
118 ));
119 self
120 }
121
122 pub fn gather_stats(&mut self) -> &mut Self {
123 self.gather_stats = true;
124 self
125 }
126
127 pub fn skip_proof_verification(&mut self, skip: bool) -> &mut Self {
128 self.skip_proof_verification = skip;
129 self
130 }
131
132 pub fn build(self) -> Result<NodeService, NodeServiceCommonBuildError> {
133 let ledger_manager = self
134 .ledger_manager
135 .ok_or(NodeServiceCommonBuildError::LedgerNotInit)?;
136 let p2p = self.p2p.ok_or(NodeServiceCommonBuildError::P2pNotInit)?;
137
138 Ok(NodeService {
139 rng_seed: self.rng_seed,
140 rng_ephemeral: Shake256::default()
141 .chain(self.rng_seed)
142 .chain(b"ephemeral")
143 .finalize_xof(),
144 rng_static: Shake256::default()
145 .chain(self.rng_seed)
146 .chain(b"static")
147 .finalize_xof(),
148 rng: self.rng,
149 event_sender: self.event_sender.clone(),
150 event_receiver: self.event_receiver,
151 snark_block_proof_verify: NodeService::snark_block_proof_verifier_spawn(
152 self.event_sender,
153 self.skip_proof_verification,
154 ),
155 ledger_manager,
156 block_producer: self.block_producer,
157 snark_worker: None,
159 archive: self.archive,
160 p2p,
161 stats: self.gather_stats.then(Stats::new),
162 rpc: self.rpc,
163 recorder: Default::default(),
164 replayer: None,
165 invariants_state: Default::default(),
166 })
167 }
168}