1use crate::config::env::read_string_from_env_then_parse;
2use bitcoin::{Amount, Network};
3use bridge_circuit_host::utils::is_dev_mode;
4use circuits_lib::bridge_circuit::constants::{
5 DEVNET_LC_IMAGE_ID, MAINNET_LC_IMAGE_ID, REGTEST_LC_IMAGE_ID, TESTNET4_LC_IMAGE_ID,
6};
7pub use clementine_config::{
8 ProtocolParamset, ProtocolParamsetName, BLOCKS_PER_HOUR, REGTEST_PARAMSET, WINTERNITZ_LOG_D,
9};
10use clementine_errors::BridgeError;
11use eyre::Context;
12
13pub const BLOCKS_PER_DAY: u16 = BLOCKS_PER_HOUR * 24;
14pub const BLOCKS_PER_WEEK: u16 = BLOCKS_PER_DAY * 7;
15
16pub trait ProtocolParamsetExt {
17 fn bridge_circuit_constant(&self) -> Result<&'static [u8; 32], BridgeError>;
18 fn get_lcp_image_id(&self) -> Result<[u8; 32], BridgeError>;
19 fn from_env() -> Result<ProtocolParamset, BridgeError>;
20}
21
22impl ProtocolParamsetExt for ProtocolParamset {
23 fn bridge_circuit_constant(&self) -> Result<&'static [u8; 32], BridgeError> {
24 match self.network {
25 Network::Regtest => {
26 if is_dev_mode() {
27 Ok(®TEST_TEST_BRIDGE_CIRCUIT_CONSTANT)
28 } else {
29 Ok(®TEST_BRIDGE_CIRCUIT_CONSTANT)
30 }
31 }
32 Network::Bitcoin => Ok(&MAINNET_BRIDGE_CIRCUIT_CONSTANT),
33 Network::Testnet4 => {
34 if is_dev_mode() {
35 Ok(&TESTNET4_TEST_BRIDGE_CIRCUIT_CONSTANT)
36 } else {
37 Ok(&TESTNET4_BRIDGE_CIRCUIT_CONSTANT)
38 }
39 }
40 Network::Signet => {
41 if is_dev_mode() {
42 Ok(&SIGNET_TEST_BRIDGE_CIRCUIT_CONSTANT)
43 } else {
44 Ok(&SIGNET_BRIDGE_CIRCUIT_CONSTANT)
45 }
46 }
47 _ => Err(BridgeError::UnsupportedNetwork),
48 }
49 }
50
51 fn get_lcp_image_id(&self) -> Result<[u8; 32], BridgeError> {
53 Ok(match self.network {
54 bitcoin::Network::Bitcoin => MAINNET_LC_IMAGE_ID,
55 bitcoin::Network::Testnet4 => TESTNET4_LC_IMAGE_ID,
56 bitcoin::Network::Signet => DEVNET_LC_IMAGE_ID,
57 bitcoin::Network::Regtest => REGTEST_LC_IMAGE_ID,
58 _ => return Err(eyre::eyre!("Unsupported Bitcoin network").into()),
59 })
60 }
61
62 fn from_env() -> Result<Self, BridgeError> {
63 let config = ProtocolParamset {
64 network: read_string_from_env_then_parse::<Network>("NETWORK")?,
65 num_round_txs: read_string_from_env_then_parse::<usize>("NUM_ROUND_TXS")?,
66 num_kickoffs_per_round: read_string_from_env_then_parse::<usize>(
67 "NUM_KICKOFFS_PER_ROUND",
68 )?,
69 num_signed_kickoffs: read_string_from_env_then_parse::<usize>("NUM_SIGNED_KICKOFFS")?,
70 bridge_amount: Amount::from_sat(read_string_from_env_then_parse::<u64>(
71 "BRIDGE_AMOUNT",
72 )?),
73 kickoff_amount: Amount::from_sat(read_string_from_env_then_parse::<u64>(
74 "KICKOFF_AMOUNT",
75 )?),
76 operator_challenge_amount: Amount::from_sat(read_string_from_env_then_parse::<u64>(
77 "OPERATOR_CHALLENGE_AMOUNT",
78 )?),
79 collateral_funding_amount: Amount::from_sat(read_string_from_env_then_parse::<u64>(
80 "COLLATERAL_FUNDING_AMOUNT",
81 )?),
82 kickoff_blockhash_commit_length: read_string_from_env_then_parse::<u32>(
83 "KICKOFF_BLOCKHASH_COMMIT_LENGTH",
84 )?,
85 watchtower_challenge_bytes: read_string_from_env_then_parse::<usize>(
86 "WATCHTOWER_CHALLENGE_BYTES",
87 )?,
88 winternitz_log_d: read_string_from_env_then_parse::<u32>("WINTERNITZ_LOG_D")?,
89 user_takes_after: read_string_from_env_then_parse::<u16>("USER_TAKES_AFTER")?,
90 operator_challenge_timeout_timelock: read_string_from_env_then_parse::<u16>(
91 "OPERATOR_CHALLENGE_TIMEOUT_TIMELOCK",
92 )?,
93 operator_challenge_nack_timelock: read_string_from_env_then_parse::<u16>(
94 "OPERATOR_CHALLENGE_NACK_TIMELOCK",
95 )?,
96 disprove_timeout_timelock: read_string_from_env_then_parse::<u16>(
97 "DISPROVE_TIMEOUT_TIMELOCK",
98 )?,
99 assert_timeout_timelock: read_string_from_env_then_parse::<u16>(
100 "ASSERT_TIMEOUT_TIMELOCK",
101 )?,
102 operator_reimburse_timelock: read_string_from_env_then_parse::<u16>(
103 "OPERATOR_REIMBURSE_TIMELOCK",
104 )?,
105 watchtower_challenge_timeout_timelock: read_string_from_env_then_parse::<u16>(
106 "WATCHTOWER_CHALLENGE_TIMEOUT_TIMELOCK",
107 )?,
108 finality_depth: read_string_from_env_then_parse::<u32>("FINALITY_DEPTH")?,
109 start_height: read_string_from_env_then_parse::<u32>("START_HEIGHT")?,
110 genesis_height: read_string_from_env_then_parse::<u32>("GENESIS_HEIGHT")?,
111 genesis_chain_state_hash: convert_hex_string_to_bytes(
112 &read_string_from_env_then_parse::<String>("GENESIS_CHAIN_STATE_HASH")?,
113 )?,
114 latest_blockhash_timeout_timelock: read_string_from_env_then_parse::<u16>(
115 "LATEST_BLOCKHASH_TIMEOUT_TIMELOCK",
116 )?,
117 bridge_nonstandard: read_string_from_env_then_parse::<bool>("BRIDGE_NONSTANDARD")?,
118 };
119
120 if config.finality_depth < 1 {
121 return Err(BridgeError::ConfigError(
122 "Finality depth must be at least 1".to_string(),
123 ));
124 }
125
126 Ok(config)
127 }
128}
129
130fn convert_hex_string_to_bytes(hex: &str) -> Result<[u8; 32], BridgeError> {
131 let hex_decode = hex::decode(hex).wrap_err("Failed to decode hex string")?;
132 let hex_bytes: [u8; 32] = hex_decode
133 .as_slice()
134 .try_into()
135 .wrap_err("Hex string is not 32 bytes")?;
136 Ok(hex_bytes)
137}
138
139#[cfg(test)]
140pub const TESTNET4_TEST_PARAMSET: ProtocolParamset = ProtocolParamset {
141 network: Network::Testnet4,
142 num_round_txs: 2,
143 num_kickoffs_per_round: 10,
144 num_signed_kickoffs: 2,
145 bridge_amount: Amount::from_sat(1_000_000),
146 kickoff_amount: Amount::from_sat(0),
147 operator_challenge_amount: Amount::from_sat(200_000),
148 collateral_funding_amount: Amount::from_sat(99_000),
149 watchtower_challenge_bytes: 144,
150 kickoff_blockhash_commit_length: 40,
151 winternitz_log_d: WINTERNITZ_LOG_D,
152 user_takes_after: 200,
153 operator_challenge_timeout_timelock: 4 * BLOCKS_PER_HOUR,
154 operator_challenge_nack_timelock: 4 * BLOCKS_PER_HOUR * 3,
155 disprove_timeout_timelock: 4 * BLOCKS_PER_HOUR * 5,
156 assert_timeout_timelock: 4 * BLOCKS_PER_HOUR * 4,
157 operator_reimburse_timelock: 2,
158 watchtower_challenge_timeout_timelock: 4 * BLOCKS_PER_HOUR * 2,
159 latest_blockhash_timeout_timelock: 4 * BLOCKS_PER_HOUR * 5 / 2,
160 finality_depth: 1,
161 start_height: 92700,
162 genesis_height: 92700,
163 genesis_chain_state_hash: [
164 0xe4, 0xe1, 0x28, 0xa8, 0x99, 0xaf, 0xee, 0xb1, 0x85, 0x5b, 0x4a, 0xb7, 0x2e, 0x4d, 0x88,
165 0x50, 0xab, 0x35, 0x1b, 0xde, 0xf9, 0x4f, 0xc2, 0x78, 0xe8, 0x5c, 0x13, 0x11, 0xe2, 0x72,
166 0xfe, 0x6a,
167 ],
168 bridge_nonstandard: true,
169};
170
171pub const REGTEST_TEST_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
172 114, 212, 219, 106, 251, 50, 248, 9, 2, 194, 84, 239, 229, 92, 195, 40, 218, 21, 55, 242, 230,
173 201, 145, 209, 251, 25, 77, 124, 129, 131, 194, 20,
174];
175
176pub const REGTEST_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
177 233, 84, 200, 234, 120, 196, 185, 119, 174, 126, 140, 238, 189, 210, 149, 97, 161, 4, 229, 219,
178 47, 124, 117, 197, 89, 165, 120, 138, 221, 74, 157, 71,
179];
180
181pub const SIGNET_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
182 73, 219, 48, 6, 223, 104, 179, 207, 180, 104, 112, 231, 210, 2, 0, 47, 87, 166, 183, 168, 211,
183 250, 76, 145, 200, 214, 169, 135, 151, 47, 202, 184,
184];
185
186pub const SIGNET_TEST_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
187 234, 217, 1, 13, 50, 162, 237, 187, 139, 172, 117, 214, 39, 142, 252, 26, 47, 173, 67, 109, 98,
188 47, 59, 121, 185, 133, 184, 164, 241, 44, 113, 58,
189];
190
191pub const MAINNET_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
192 129, 78, 18, 124, 221, 80, 148, 108, 252, 53, 139, 39, 96, 60, 162, 140, 241, 131, 111, 46, 52,
193 145, 169, 103, 131, 115, 17, 113, 68, 193, 151, 45,
194];
195
196pub const TESTNET4_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
197 123, 6, 8, 84, 79, 122, 249, 123, 48, 241, 129, 10, 215, 65, 243, 68, 174, 66, 239, 146, 1, 75,
198 168, 108, 46, 59, 223, 127, 125, 127, 97, 90,
199];
200
201pub const TESTNET4_TEST_BRIDGE_CIRCUIT_CONSTANT: [u8; 32] = [
202 83, 191, 166, 41, 241, 95, 11, 84, 148, 1, 21, 128, 190, 167, 207, 165, 143, 209, 232, 169,
203 211, 120, 188, 115, 219, 48, 108, 224, 129, 254, 54, 214,
204];
205
206#[cfg(test)]
207mod tests {
208 use bridge_circuit_host::{
209 bridge_circuit_host::{
210 MAINNET_BRIDGE_CIRCUIT_ELF, REGTEST_BRIDGE_CIRCUIT_ELF, SIGNET_BRIDGE_CIRCUIT_ELF,
211 SIGNET_BRIDGE_CIRCUIT_ELF_TEST, TESTNET4_BRIDGE_CIRCUIT_ELF,
212 TESTNET4_BRIDGE_CIRCUIT_ELF_TEST,
213 },
214 utils::calculate_succinct_output_prefix,
215 };
216 use circuits_lib::{
217 bridge_circuit::constants::{
218 MAINNET_WORK_ONLY_METHOD_ID, REGTEST_WORK_ONLY_METHOD_ID, SIGNET_WORK_ONLY_METHOD_ID,
219 TESTNET4_WORK_ONLY_METHOD_ID,
220 },
221 common::constants::{
222 MAINNET_HEADER_CHAIN_METHOD_ID, REGTEST_HEADER_CHAIN_METHOD_ID,
223 SIGNET_HEADER_CHAIN_METHOD_ID, TESTNET4_HEADER_CHAIN_METHOD_ID,
224 },
225 };
226 use risc0_zkvm::compute_image_id;
227
228 use bridge_circuit_host::bridge_circuit_host::{
229 MAINNET_HEADER_CHAIN_ELF, MAINNET_WORK_ONLY_ELF, REGTEST_HEADER_CHAIN_ELF,
230 REGTEST_WORK_ONLY_ELF, SIGNET_HEADER_CHAIN_ELF, SIGNET_WORK_ONLY_ELF,
231 TESTNET4_HEADER_CHAIN_ELF, TESTNET4_WORK_ONLY_ELF,
232 };
233
234 use super::*;
235
236 #[test]
237 fn test_regtest_test_bridge_circuit_constant() {
238 let regtest_bridge_elf =
239 include_bytes!("../../../risc0-circuits/elfs/test-regtest-bridge-circuit-guest.bin");
240 let regtest_bridge_circuit_method_id =
241 compute_image_id(regtest_bridge_elf).expect("should compute image id");
242 let calculated_regtest_bridge_circuit_constant =
243 calculate_succinct_output_prefix(regtest_bridge_circuit_method_id.as_bytes());
244
245 let regtest_bridge_circuit_constant = REGTEST_TEST_BRIDGE_CIRCUIT_CONSTANT;
246 assert_eq!(
247 calculated_regtest_bridge_circuit_constant,
248 regtest_bridge_circuit_constant,
249 "You forgot to update regtest-(test) bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
250 calculated_regtest_bridge_circuit_constant,
251 hex::encode(calculated_regtest_bridge_circuit_constant)
252 );
253 }
254
255 #[test]
256 fn test_regtest_bridge_circuit_constant() {
257 let regtest_bridge_elf = REGTEST_BRIDGE_CIRCUIT_ELF;
258 let regtest_bridge_circuit_method_id =
259 compute_image_id(regtest_bridge_elf).expect("should compute image id");
260 let calculated_regtest_bridge_circuit_constant =
261 calculate_succinct_output_prefix(regtest_bridge_circuit_method_id.as_bytes());
262
263 let regtest_bridge_circuit_constant = REGTEST_BRIDGE_CIRCUIT_CONSTANT;
264 assert_eq!(
265 calculated_regtest_bridge_circuit_constant,
266 regtest_bridge_circuit_constant,
267 "You forgot to update regtest bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
268 calculated_regtest_bridge_circuit_constant,
269 hex::encode(calculated_regtest_bridge_circuit_constant)
270 );
271 }
272
273 #[test]
274 fn test_mainnet_bridge_circuit_constant() {
275 let mainnet_bridge_elf = MAINNET_BRIDGE_CIRCUIT_ELF;
276 let mainnet_bridge_circuit_method_id =
277 compute_image_id(mainnet_bridge_elf).expect("should compute image id");
278 let calculated_mainnet_bridge_circuit_constant =
279 calculate_succinct_output_prefix(mainnet_bridge_circuit_method_id.as_bytes());
280
281 let mainnet_bridge_circuit_constant = MAINNET_BRIDGE_CIRCUIT_CONSTANT;
282 assert_eq!(
283 calculated_mainnet_bridge_circuit_constant,
284 mainnet_bridge_circuit_constant,
285 "You forgot to update mainnet bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
286 calculated_mainnet_bridge_circuit_constant,
287 hex::encode(calculated_mainnet_bridge_circuit_constant)
288 );
289 }
290
291 #[test]
292 fn test_testnet4_bridge_circuit_constant() {
293 let testnet4_bridge_elf = TESTNET4_BRIDGE_CIRCUIT_ELF;
294 let testnet4_bridge_circuit_method_id =
295 compute_image_id(testnet4_bridge_elf).expect("should compute image id");
296 let calculated_testnet4_bridge_circuit_constant =
297 calculate_succinct_output_prefix(testnet4_bridge_circuit_method_id.as_bytes());
298
299 let testnet4_bridge_circuit_constant = TESTNET4_BRIDGE_CIRCUIT_CONSTANT;
300 assert_eq!(
301 calculated_testnet4_bridge_circuit_constant,
302 testnet4_bridge_circuit_constant,
303 "You forgot to update testnet4 bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
304 calculated_testnet4_bridge_circuit_constant,
305 hex::encode(calculated_testnet4_bridge_circuit_constant)
306 );
307 }
308
309 #[test]
310 fn test_testnet4_test_bridge_circuit_constant() {
311 let testnet4_bridge_elf = TESTNET4_BRIDGE_CIRCUIT_ELF_TEST;
312 let testnet4_bridge_circuit_method_id =
313 compute_image_id(testnet4_bridge_elf).expect("should compute image id");
314 let calculated_testnet4_bridge_circuit_constant =
315 calculate_succinct_output_prefix(testnet4_bridge_circuit_method_id.as_bytes());
316
317 let testnet4_bridge_circuit_constant = TESTNET4_TEST_BRIDGE_CIRCUIT_CONSTANT;
318 assert_eq!(
319 calculated_testnet4_bridge_circuit_constant,
320 testnet4_bridge_circuit_constant,
321 "You forgot to update testnet4-test bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
322 calculated_testnet4_bridge_circuit_constant,
323 hex::encode(calculated_testnet4_bridge_circuit_constant)
324 );
325 }
326
327 #[test]
328 fn test_signet_bridge_circuit_constant() {
329 let signet_bridge_elf = SIGNET_BRIDGE_CIRCUIT_ELF;
330 let signet_bridge_circuit_method_id =
331 compute_image_id(signet_bridge_elf).expect("should compute image id");
332 let calculated_signet_bridge_circuit_constant =
333 calculate_succinct_output_prefix(signet_bridge_circuit_method_id.as_bytes());
334
335 let signet_bridge_circuit_constant = SIGNET_BRIDGE_CIRCUIT_CONSTANT;
336 assert_eq!(
337 calculated_signet_bridge_circuit_constant,
338 signet_bridge_circuit_constant,
339 "You forgot to update signet bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
340 calculated_signet_bridge_circuit_constant,
341 hex::encode(calculated_signet_bridge_circuit_constant)
342 );
343 }
344
345 #[test]
346 fn test_signet_test_bridge_circuit_constant() {
347 let signet_bridge_elf = SIGNET_BRIDGE_CIRCUIT_ELF_TEST;
348 let signet_bridge_circuit_method_id =
349 compute_image_id(signet_bridge_elf).expect("should compute image id");
350 let calculated_signet_bridge_circuit_constant =
351 calculate_succinct_output_prefix(signet_bridge_circuit_method_id.as_bytes());
352
353 let signet_bridge_circuit_constant = SIGNET_TEST_BRIDGE_CIRCUIT_CONSTANT;
354 assert_eq!(
355 calculated_signet_bridge_circuit_constant,
356 signet_bridge_circuit_constant,
357 "You forgot to update signet-test bridge_circuit_constant with the new method id. Please change it in these places: core/src/config/protocol.rs. The expected value is: {:?}, hex format: {:?}",
358 calculated_signet_bridge_circuit_constant,
359 hex::encode(calculated_signet_bridge_circuit_constant)
360 );
361 }
362
363 #[test]
364 fn test_header_chain_method_ids() {
365 let networks = [
366 (
367 MAINNET_HEADER_CHAIN_ELF,
368 MAINNET_HEADER_CHAIN_METHOD_ID,
369 "mainnet",
370 ),
371 (
372 TESTNET4_HEADER_CHAIN_ELF,
373 TESTNET4_HEADER_CHAIN_METHOD_ID,
374 "testnet4",
375 ),
376 (
377 SIGNET_HEADER_CHAIN_ELF,
378 SIGNET_HEADER_CHAIN_METHOD_ID,
379 "signet",
380 ),
381 (
382 REGTEST_HEADER_CHAIN_ELF,
383 REGTEST_HEADER_CHAIN_METHOD_ID,
384 "regtest",
385 ),
386 ];
387
388 for (elf, method_id, network) in networks.into_iter() {
389 let header_chain_circuit_method_id = compute_image_id(elf);
390 assert_eq!(
391 header_chain_circuit_method_id.expect("should compute image id").as_words(),
392 method_id,
393 "Header chain method ID mismatch for {network}, please update the constant here: circuits-lib/src/common/constants.rs",
394 );
395 }
396 }
397
398 #[test]
399 fn test_work_only_method_ids() {
400 let networks = [
401 (
402 MAINNET_WORK_ONLY_ELF,
403 MAINNET_WORK_ONLY_METHOD_ID,
404 "mainnet",
405 ),
406 (
407 TESTNET4_WORK_ONLY_ELF,
408 TESTNET4_WORK_ONLY_METHOD_ID,
409 "testnet4",
410 ),
411 (SIGNET_WORK_ONLY_ELF, SIGNET_WORK_ONLY_METHOD_ID, "signet"),
412 (
413 REGTEST_WORK_ONLY_ELF,
414 REGTEST_WORK_ONLY_METHOD_ID,
415 "regtest",
416 ),
417 ];
418
419 for (elf, method_id, network) in networks.into_iter() {
420 let work_only_circuit_method_id =
421 compute_image_id(elf).expect("should compute image id");
422 let current_method_id = work_only_circuit_method_id.as_bytes();
423 assert_eq!(
424 current_method_id,
425 method_id,
426 "Work only method ID mismatch for {network}, please update the constant here: circuits-lib/src/bridge_circuit/constants.rs. Hex format of correct value: {:?}",
427 hex::encode(current_method_id)
428 );
429 }
430 }
431}