diem_config/config/
execution_config.rs1use crate::config::{Error, RootPath, SecureBackend};
9use diem_types::transaction::Transaction;
10use serde::{Deserialize, Serialize};
11use std::{
12 fs::File,
13 io::{Read, Write},
14 net::SocketAddr,
15 path::PathBuf,
16};
17
18const GENESIS_DEFAULT: &str = "genesis.blob";
19
20#[derive(Clone, Deserialize, PartialEq, Serialize)]
21#[serde(default, deny_unknown_fields)]
22pub struct ExecutionConfig {
23 #[serde(skip)]
24 pub genesis: Option<Transaction>,
25 pub sign_vote_proposal: bool,
26 pub genesis_file_location: PathBuf,
27 pub service: ExecutionCorrectnessService,
28 pub backend: SecureBackend,
29 pub network_timeout_ms: u64,
30}
31
32impl std::fmt::Debug for ExecutionConfig {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(f, "ExecutionConfig {{ genesis: ")?;
35 if self.genesis.is_some() {
36 write!(f, "Some(...)")?;
37 } else {
38 write!(f, "None")?;
39 }
40 write!(
41 f,
42 ", genesis_file_location: {:?} ",
43 self.genesis_file_location
44 )?;
45 write!(
46 f,
47 ", sign_vote_proposal: {:?}, service: {:?}, backend: {:?} }}",
48 self.sign_vote_proposal, self.service, self.backend
49 )?;
50 self.service.fmt(f)
51 }
52}
53
54impl Default for ExecutionConfig {
55 fn default() -> ExecutionConfig {
56 ExecutionConfig {
57 genesis: None,
58 genesis_file_location: PathBuf::new(),
59 service: ExecutionCorrectnessService::Thread,
60 backend: SecureBackend::InMemoryStorage,
61 sign_vote_proposal: true,
62 network_timeout_ms: 30_000,
64 }
65 }
66}
67
68impl ExecutionConfig {
69 pub fn load(&mut self, root_dir: &RootPath) -> Result<(), Error> {
70 if !self.genesis_file_location.as_os_str().is_empty() {
71 let path = root_dir.full_path(&self.genesis_file_location);
72 let mut file = File::open(&path)
73 .map_err(|e| Error::IO("genesis".into(), e))?;
74 let mut buffer = vec![];
75 file.read_to_end(&mut buffer)
76 .map_err(|e| Error::IO("genesis".into(), e))?;
77 let data = bcs::from_bytes(&buffer)
78 .map_err(|e| Error::BCS("genesis", e))?;
79 self.genesis = Some(data);
80 }
81
82 Ok(())
83 }
84
85 pub fn save(&mut self, root_dir: &RootPath) -> Result<(), Error> {
86 if let Some(genesis) = &self.genesis {
87 if self.genesis_file_location.as_os_str().is_empty() {
88 self.genesis_file_location = PathBuf::from(GENESIS_DEFAULT);
89 }
90 let path = root_dir.full_path(&self.genesis_file_location);
91 let mut file = File::create(&path)
92 .map_err(|e| Error::IO("genesis".into(), e))?;
93 let data = bcs::to_bytes(&genesis)
94 .map_err(|e| Error::BCS("genesis", e))?;
95 file.write_all(&data)
96 .map_err(|e| Error::IO("genesis".into(), e))?;
97 }
98 Ok(())
99 }
100
101 pub fn set_data_dir(&mut self, data_dir: PathBuf) {
102 if let SecureBackend::OnDiskStorage(backend) = &mut self.backend {
103 backend.set_data_dir(data_dir);
104 }
105 }
106}
107
108#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
110#[serde(rename_all = "snake_case", tag = "type")]
111pub enum ExecutionCorrectnessService {
112 Local,
114 Process(RemoteExecutionService),
116 Serializer,
119 Thread,
122}
123
124#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
125#[serde(deny_unknown_fields)]
126pub struct RemoteExecutionService {
127 pub server_address: SocketAddr,
128}
129
130#[cfg(test)]
131mod test {
132 use super::*;
133 use diem_temppath::TempPath;
134 use diem_types::{
135 transaction::{ChangeSet, Transaction, WriteSetPayload},
136 write_set::WriteSetMut,
137 };
138
139 #[test]
140 fn test_no_genesis() {
141 let (mut config, path) = generate_config();
142 assert_eq!(config.genesis, None);
143 let root_dir = RootPath::new_path(path.path());
144 let result = config.load(&root_dir);
145 assert!(result.is_ok());
146 assert_eq!(config.genesis_file_location, PathBuf::new());
147 }
148
149 #[test]
150 fn test_some_and_load_genesis() {
151 let fake_genesis = Transaction::GenesisTransaction(
152 WriteSetPayload::Direct(ChangeSet::new(
153 WriteSetMut::new(vec![]).freeze().unwrap(),
154 vec![],
155 )),
156 );
157 let (mut config, path) = generate_config();
158 config.genesis = Some(fake_genesis.clone());
159 let root_dir = RootPath::new_path(path.path());
160 config.save(&root_dir).expect("Unable to save");
161 assert_eq!(
163 config.genesis_file_location,
164 PathBuf::from(GENESIS_DEFAULT)
165 );
166
167 config.genesis = None;
168 let result = config.load(&root_dir);
169 assert!(result.is_ok());
170 assert_eq!(config.genesis, Some(fake_genesis));
171 }
172
173 fn generate_config() -> (ExecutionConfig, TempPath) {
174 let temp_dir = TempPath::new();
175 temp_dir.create_as_dir().expect("error creating tempdir");
176 let execution_config = ExecutionConfig::default();
177 (execution_config, temp_dir)
178 }
179}