sawtooth/journal/genesis/
builder.rs

1/*
2 * Copyright 2018-2020 Cargill Incorporated
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * ------------------------------------------------------------------------------
16 */
17
18use std::path::PathBuf;
19
20use cylinder::Signer;
21
22use crate::journal::block_manager::BlockManager;
23use crate::journal::chain::ChainObserver;
24use crate::journal::{chain::ChainReader, chain_id_manager::ChainIdManager};
25use crate::state::merkle::CborMerkleState;
26use crate::state::state_view_factory::StateViewFactory;
27use crate::transact::execution::executor::ExecutionTaskSubmitter;
28use crate::transact::scheduler::SchedulerFactory;
29
30use super::error::GenesisControllerBuildError;
31use super::GenesisController;
32
33const GENESIS_FILE: &str = "genesis.batch";
34
35/// Builder for creating a `GenesisController`
36#[derive(Default)]
37pub struct GenesisControllerBuilder {
38    transaction_executor: Option<ExecutionTaskSubmitter>,
39    scheduler_factory: Option<Box<dyn SchedulerFactory>>,
40    block_manager: Option<BlockManager>,
41    chain_reader: Option<Box<dyn ChainReader>>,
42    state_view_factory: Option<StateViewFactory>,
43    identity_signer: Option<Box<dyn Signer>>,
44    data_dir: Option<String>,
45    chain_id_manager: Option<ChainIdManager>,
46    observers: Option<Vec<Box<dyn ChainObserver>>>,
47    initial_state_root: Option<String>,
48    merkle_state: Option<CborMerkleState>,
49}
50
51impl GenesisControllerBuilder {
52    // Creates an empty builder
53    pub fn new() -> Self {
54        GenesisControllerBuilder::default()
55    }
56
57    pub fn with_transaction_executor(
58        mut self,
59        executor: ExecutionTaskSubmitter,
60    ) -> GenesisControllerBuilder {
61        self.transaction_executor = Some(executor);
62        self
63    }
64
65    pub fn with_scheduler_factory(
66        mut self,
67        scheduler_factory: Box<dyn SchedulerFactory>,
68    ) -> GenesisControllerBuilder {
69        self.scheduler_factory = Some(scheduler_factory);
70        self
71    }
72
73    pub fn with_block_manager(mut self, block_manager: BlockManager) -> GenesisControllerBuilder {
74        self.block_manager = Some(block_manager);
75        self
76    }
77
78    pub fn with_chain_reader(
79        mut self,
80        chain_reader: Box<dyn ChainReader>,
81    ) -> GenesisControllerBuilder {
82        self.chain_reader = Some(chain_reader);
83        self
84    }
85
86    pub fn with_state_view_factory(
87        mut self,
88        state_view_factory: StateViewFactory,
89    ) -> GenesisControllerBuilder {
90        self.state_view_factory = Some(state_view_factory);
91        self
92    }
93
94    pub fn with_data_dir(mut self, data_dir: String) -> GenesisControllerBuilder {
95        self.data_dir = Some(data_dir);
96        self
97    }
98
99    pub fn with_chain_id_manager(
100        mut self,
101        chain_id_manager: ChainIdManager,
102    ) -> GenesisControllerBuilder {
103        self.chain_id_manager = Some(chain_id_manager);
104        self
105    }
106
107    pub fn with_observers(
108        mut self,
109        observers: Vec<Box<dyn ChainObserver>>,
110    ) -> GenesisControllerBuilder {
111        self.observers = Some(observers);
112        self
113    }
114
115    pub fn with_initial_state_root(
116        mut self,
117        initial_state_root: String,
118    ) -> GenesisControllerBuilder {
119        self.initial_state_root = Some(initial_state_root);
120        self
121    }
122
123    pub fn with_merkle_state(mut self, merkle_state: CborMerkleState) -> GenesisControllerBuilder {
124        self.merkle_state = Some(merkle_state);
125        self
126    }
127
128    pub fn with_identity_signer(
129        mut self,
130        identity_signer: Box<dyn Signer>,
131    ) -> GenesisControllerBuilder {
132        self.identity_signer = Some(identity_signer);
133        self
134    }
135
136    /// Builds the `GenesisJounral`
137    ///
138    /// Returns an error if one of the required fields are not provided
139    pub fn build(self) -> Result<GenesisController, GenesisControllerBuildError> {
140        let transaction_executor = self.transaction_executor.ok_or_else(|| {
141            GenesisControllerBuildError::MissingField(
142                "'transaction_executor' field is required".to_string(),
143            )
144        })?;
145
146        let scheduler_factory = self.scheduler_factory.ok_or_else(|| {
147            GenesisControllerBuildError::MissingField(
148                "'scheduler_factory' field is required".to_string(),
149            )
150        })?;
151
152        let block_manager = self.block_manager.ok_or_else(|| {
153            GenesisControllerBuildError::MissingField(
154                "'block_manager' field is required".to_string(),
155            )
156        })?;
157
158        let chain_reader = self.chain_reader.ok_or_else(|| {
159            GenesisControllerBuildError::MissingField(
160                "'chain_reader' field is required".to_string(),
161            )
162        })?;
163
164        let state_view_factory = self.state_view_factory.ok_or_else(|| {
165            GenesisControllerBuildError::MissingField(
166                "'state_view_factory' field is required".to_string(),
167            )
168        })?;
169
170        let data_dir = self.data_dir.ok_or_else(|| {
171            GenesisControllerBuildError::MissingField("'data_dir' field is required".to_string())
172        })?;
173
174        let chain_id_manager = self.chain_id_manager.ok_or_else(|| {
175            GenesisControllerBuildError::MissingField(
176                "'chain_id_manager' field is required".to_string(),
177            )
178        })?;
179
180        let observers = self.observers.ok_or_else(|| {
181            GenesisControllerBuildError::MissingField("'observers' field is required".to_string())
182        })?;
183
184        let initial_state_root = self.initial_state_root.ok_or_else(|| {
185            GenesisControllerBuildError::MissingField(
186                "'initial_state_root' field is required".to_string(),
187            )
188        })?;
189
190        let merkle_state = self.merkle_state.ok_or_else(|| {
191            GenesisControllerBuildError::MissingField(
192                "'merkle_state' field is required".to_string(),
193            )
194        })?;
195
196        let identity_signer = self.identity_signer.ok_or_else(|| {
197            GenesisControllerBuildError::MissingField(
198                "'identity_signer' field is required".to_string(),
199            )
200        })?;
201
202        let mut genesis_path_buf = PathBuf::from(data_dir);
203        genesis_path_buf.push(GENESIS_FILE);
204
205        Ok(GenesisController {
206            transaction_executor,
207            scheduler_factory,
208            block_manager,
209            chain_reader,
210            state_view_factory,
211            identity_signer,
212            chain_id_manager,
213            observers,
214            genesis_file_path: genesis_path_buf,
215            initial_state_root,
216            merkle_state,
217        })
218    }
219}