1use super::*;
17use crate::TRANSACTION_PREFIX;
18use snarkvm_console_algorithms::{
19 BHP256,
20 BHP512,
21 BHP768,
22 BHP1024,
23 Blake2Xs,
24 Keccak256,
25 Keccak384,
26 Keccak512,
27 Pedersen64,
28 Pedersen128,
29 Poseidon2,
30 Poseidon4,
31 Poseidon8,
32 Sha3_256,
33 Sha3_384,
34 Sha3_512,
35};
36
37lazy_static! {
38 static ref GENERATOR_G: Vec<Group<TestnetV0 >> = TestnetV0::new_bases("AleoAccountEncryptionAndSignatureScheme0");
40
41 static ref VARUNA_FS_PARAMETERS: FiatShamirParameters<TestnetV0> = FiatShamir::<TestnetV0>::sample_parameters();
43
44 static ref COMMITMENT_DOMAIN: Field<TestnetV0> = Field::<TestnetV0>::new_domain_separator("AleoCommitment0");
46 static ref ENCRYPTION_DOMAIN: Field<TestnetV0> = Field::<TestnetV0>::new_domain_separator("AleoSymmetricEncryption0");
48 static ref GRAPH_KEY_DOMAIN: Field<TestnetV0> = Field::<TestnetV0>::new_domain_separator("AleoGraphKey0");
50 static ref SERIAL_NUMBER_DOMAIN: Field<TestnetV0> = Field::<TestnetV0>::new_domain_separator("AleoSerialNumber0");
52
53 pub static ref TESTNET_BHP_256: BHP256<TestnetV0> = BHP256::<TestnetV0>::setup("AleoBHP256").expect("Failed to setup BHP256");
55 pub static ref TESTNET_BHP_512: BHP512<TestnetV0> = BHP512::<TestnetV0>::setup("AleoBHP512").expect("Failed to setup BHP512");
57 pub static ref TESTNET_BHP_768: BHP768<TestnetV0> = BHP768::<TestnetV0>::setup("AleoBHP768").expect("Failed to setup BHP768");
59 pub static ref TESTNET_BHP_1024: BHP1024<TestnetV0> = BHP1024::<TestnetV0>::setup("AleoBHP1024").expect("Failed to setup BHP1024");
61
62 pub static ref TESTNET_PEDERSEN_64: Pedersen64<TestnetV0> = Pedersen64::<TestnetV0>::setup("AleoPedersen64");
64 pub static ref TESTNET_PEDERSEN_128: Pedersen128<TestnetV0> = Pedersen128::<TestnetV0>::setup("AleoPedersen128");
66
67 pub static ref TESTNET_POSEIDON_2: Poseidon2<TestnetV0> = Poseidon2::<TestnetV0>::setup("AleoPoseidon2").expect("Failed to setup Poseidon2");
69 pub static ref TESTNET_POSEIDON_4: Poseidon4<TestnetV0> = Poseidon4::<TestnetV0>::setup("AleoPoseidon4").expect("Failed to setup Poseidon4");
71 pub static ref TESTNET_POSEIDON_8: Poseidon8<TestnetV0> = Poseidon8::<TestnetV0>::setup("AleoPoseidon8").expect("Failed to setup Poseidon8");
73
74 pub static ref TESTNET_CREDITS_V0_PROVING_KEYS: IndexMap<String, Arc<VarunaProvingKey<Console>>> = {
75 let mut map = IndexMap::new();
76 snarkvm_parameters::insert_testnet_credit_v0_keys!(map, VarunaProvingKey<Console>, Prover);
77 map
78 };
79 pub static ref TESTNET_CREDITS_V0_VERIFYING_KEYS: IndexMap<String, Arc<VarunaVerifyingKey<Console>>> = {
80 let mut map = IndexMap::new();
81 snarkvm_parameters::insert_testnet_credit_v0_keys!(map, VarunaVerifyingKey<Console>, Verifier);
82 map
83 };
84
85 pub static ref TESTNET_CREDITS_PROVING_KEYS: IndexMap<String, Arc<VarunaProvingKey<Console>>> = {
86 let mut map = IndexMap::new();
87 snarkvm_parameters::insert_testnet_credit_keys!(map, VarunaProvingKey<Console>, Prover);
88 map
89 };
90 pub static ref TESTNET_CREDITS_VERIFYING_KEYS: IndexMap<String, Arc<VarunaVerifyingKey<Console>>> = {
91 let mut map = IndexMap::new();
92 snarkvm_parameters::insert_testnet_credit_keys!(map, VarunaVerifyingKey<Console>, Verifier);
93 map
94 };
95}
96
97#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
98pub struct TestnetV0;
99
100impl TestnetV0 {
101 fn new_bases(message: &str) -> Vec<Group<Self>> {
103 let (base, _, _) = Blake2Xs::hash_to_curve::<<Self as Environment>::Affine>(message);
105
106 let mut g = Group::<Self>::new(base);
108 let mut g_bases = Vec::with_capacity(Scalar::<Self>::size_in_bits());
109 for _ in 0..Scalar::<Self>::size_in_bits() {
110 g_bases.push(g);
111 g = g.double();
112 }
113 g_bases
114 }
115}
116
117impl Environment for TestnetV0 {
118 type Affine = <Console as Environment>::Affine;
119 type BigInteger = <Console as Environment>::BigInteger;
120 type Field = <Console as Environment>::Field;
121 type PairingCurve = <Console as Environment>::PairingCurve;
122 type Projective = <Console as Environment>::Projective;
123 type Scalar = <Console as Environment>::Scalar;
124
125 const EDWARDS_A: Self::Field = Console::EDWARDS_A;
127 const EDWARDS_D: Self::Field = Console::EDWARDS_D;
129 const MONTGOMERY_A: Self::Field = Console::MONTGOMERY_A;
131 const MONTGOMERY_B: Self::Field = Console::MONTGOMERY_B;
133}
134
135impl Network for TestnetV0 {
136 type BlockHash = AleoID<Field<Self>, { hrp2!("ab") }>;
138 type RatificationID = AleoID<Field<Self>, { hrp2!("ar") }>;
140 type StateRoot = AleoID<Field<Self>, { hrp2!("sr") }>;
142 type TransactionID = AleoID<Field<Self>, { hrp2!(TRANSACTION_PREFIX) }>;
144 type TransitionID = AleoID<Field<Self>, { hrp2!("au") }>;
146 type TransmissionChecksum = u128;
148
149 #[cfg(not(feature = "test_targets"))]
151 const GENESIS_COINBASE_TARGET: u64 = (1u64 << 29).saturating_sub(1);
152 #[cfg(feature = "test_targets")]
153 const GENESIS_COINBASE_TARGET: u64 = (1u64 << 5).saturating_sub(1);
154 #[cfg(not(feature = "test_targets"))]
156 const GENESIS_PROOF_TARGET: u64 = 1u64 << 27;
157 #[cfg(feature = "test_targets")]
158 const GENESIS_PROOF_TARGET: u64 = 1u64 << 3;
159 const GENESIS_TIMESTAMP: i64 = 1715776496 ;
161 const ID: u16 = 1;
163 const INCLUSION_FUNCTION_NAME: &'static str = snarkvm_parameters::testnet::NETWORK_INCLUSION_FUNCTION_NAME;
165 #[cfg(not(any(test, feature = "test")))]
167 const MAX_CERTIFICATES: [(ConsensusVersion, u16); 5] = [
168 (ConsensusVersion::V1, 100),
169 (ConsensusVersion::V3, 100),
170 (ConsensusVersion::V5, 100),
171 (ConsensusVersion::V6, 100),
172 (ConsensusVersion::V9, 100),
173 ];
174 #[cfg(any(test, feature = "test"))]
176 const MAX_CERTIFICATES: [(ConsensusVersion, u16); 5] = [
177 (ConsensusVersion::V1, 25),
178 (ConsensusVersion::V3, 25),
179 (ConsensusVersion::V5, 25),
180 (ConsensusVersion::V6, 25),
181 (ConsensusVersion::V9, 25),
182 ];
183 const NAME: &'static str = "Aleo Testnet (v0)";
185 const SHORT_NAME: &'static str = "testnet";
187 const _CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] =
191 TESTNET_V0_CONSENSUS_VERSION_HEIGHTS;
192
193 #[allow(non_snake_case)]
195 fn INCLUSION_UPGRADE_HEIGHT() -> Result<u32> {
196 Self::CONSENSUS_HEIGHT(ConsensusVersion::V8)
197 }
198
199 fn genesis_bytes() -> &'static [u8] {
201 snarkvm_parameters::testnet::GenesisBytes::load_bytes()
202 }
203
204 fn restrictions_list_as_str() -> &'static str {
206 snarkvm_parameters::testnet::RESTRICTIONS_LIST
207 }
208
209 fn get_credits_v0_proving_key(function_name: String) -> Result<&'static Arc<VarunaProvingKey<Self>>> {
211 TESTNET_CREDITS_V0_PROVING_KEYS
212 .get(&function_name)
213 .ok_or_else(|| anyhow!("Proving key (v0) for credits.aleo/{function_name}' not found"))
214 }
215
216 fn get_credits_v0_verifying_key(function_name: String) -> Result<&'static Arc<VarunaVerifyingKey<Self>>> {
218 TESTNET_CREDITS_V0_VERIFYING_KEYS
219 .get(&function_name)
220 .ok_or_else(|| anyhow!("Verifying key (v0) for credits_v0.aleo/{function_name}' not found"))
221 }
222
223 fn get_credits_proving_key(function_name: String) -> Result<&'static Arc<VarunaProvingKey<Self>>> {
225 TESTNET_CREDITS_PROVING_KEYS
226 .get(&function_name)
227 .ok_or_else(|| anyhow!("Proving key for credits.aleo/{function_name}' not found"))
228 }
229
230 fn get_credits_verifying_key(function_name: String) -> Result<&'static Arc<VarunaVerifyingKey<Self>>> {
232 TESTNET_CREDITS_VERIFYING_KEYS
233 .get(&function_name)
234 .ok_or_else(|| anyhow!("Verifying key for credits.aleo/{function_name}' not found"))
235 }
236
237 #[cfg(not(feature = "wasm"))]
238 fn inclusion_v0_proving_key() -> &'static Arc<VarunaProvingKey<Self>> {
240 static INSTANCE: OnceLock<Arc<VarunaProvingKey<Console>>> = OnceLock::new();
241 INSTANCE.get_or_init(|| {
242 Arc::new(
244 CircuitProvingKey::from_bytes_le(&snarkvm_parameters::testnet::INCLUSION_V0_PROVING_KEY[1..])
245 .expect("Failed to load inclusion_v0 proving key."),
246 )
247 })
248 }
249
250 #[cfg(feature = "wasm")]
251 fn inclusion_v0_proving_key(inclusion_key_bytes: Option<Vec<u8>>) -> &'static Arc<VarunaProvingKey<Self>> {
253 static INSTANCE: OnceLock<Arc<VarunaProvingKey<Console>>> = OnceLock::new();
254 INSTANCE.get_or_init(|| {
255 inclusion_key_bytes
256 .map(|bytes| {
257 snarkvm_parameters::testnet::InclusionV0Prover::verify_bytes(&bytes)
258 .expect("Bytes provided did not match expected inclusion checksum.");
259 Arc::new(
260 CircuitProvingKey::from_bytes_le(&bytes[1..]).expect("Failed to load inclusion proving key."),
261 )
262 })
263 .unwrap_or_else(|| {
264 Arc::new(
265 CircuitProvingKey::from_bytes_le(&snarkvm_parameters::testnet::INCLUSION_V0_PROVING_KEY[1..])
266 .expect("Failed to load inclusion proving key."),
267 )
268 })
269 })
270 }
271
272 fn inclusion_v0_verifying_key() -> &'static Arc<VarunaVerifyingKey<Self>> {
274 static INSTANCE: OnceLock<Arc<VarunaVerifyingKey<Console>>> = OnceLock::new();
275 INSTANCE.get_or_init(|| {
276 Arc::new(
278 CircuitVerifyingKey::from_bytes_le(&snarkvm_parameters::testnet::INCLUSION_V0_VERIFYING_KEY[1..])
279 .expect("Failed to load inclusion_v0 verifying key."),
280 )
281 })
282 }
283
284 #[cfg(not(feature = "wasm"))]
285 fn inclusion_proving_key() -> &'static Arc<VarunaProvingKey<Self>> {
287 static INSTANCE: OnceLock<Arc<VarunaProvingKey<Console>>> = OnceLock::new();
288 INSTANCE.get_or_init(|| {
289 Arc::new(
291 CircuitProvingKey::from_bytes_le(&snarkvm_parameters::testnet::INCLUSION_PROVING_KEY[1..])
292 .expect("Failed to load inclusion proving key."),
293 )
294 })
295 }
296
297 #[cfg(feature = "wasm")]
298 fn inclusion_proving_key(inclusion_key_bytes: Option<Vec<u8>>) -> &'static Arc<VarunaProvingKey<Self>> {
300 static INSTANCE: OnceLock<Arc<VarunaProvingKey<Console>>> = OnceLock::new();
301 INSTANCE.get_or_init(|| {
302 inclusion_key_bytes
303 .map(|bytes| {
304 snarkvm_parameters::testnet::InclusionProver::verify_bytes(&bytes)
305 .expect("Bytes provided did not match expected inclusion checksum.");
306 Arc::new(
307 CircuitProvingKey::from_bytes_le(&bytes[1..]).expect("Failed to load inclusion proving key."),
308 )
309 })
310 .unwrap_or_else(|| {
311 Arc::new(
312 CircuitProvingKey::from_bytes_le(&snarkvm_parameters::testnet::INCLUSION_PROVING_KEY[1..])
313 .expect("Failed to load inclusion proving key."),
314 )
315 })
316 })
317 }
318
319 fn inclusion_verifying_key() -> &'static Arc<VarunaVerifyingKey<Self>> {
321 static INSTANCE: OnceLock<Arc<VarunaVerifyingKey<Console>>> = OnceLock::new();
322 INSTANCE.get_or_init(|| {
323 Arc::new(
325 CircuitVerifyingKey::from_bytes_le(&snarkvm_parameters::testnet::INCLUSION_VERIFYING_KEY[1..])
326 .expect("Failed to load inclusion verifying key."),
327 )
328 })
329 }
330
331 fn g_powers() -> &'static Vec<Group<Self>> {
333 &GENERATOR_G
334 }
335
336 fn g_scalar_multiply(scalar: &Scalar<Self>) -> Group<Self> {
338 GENERATOR_G
339 .iter()
340 .zip_eq(&scalar.to_bits_le())
341 .filter_map(|(base, bit)| match bit {
342 true => Some(base),
343 false => None,
344 })
345 .sum()
346 }
347
348 fn varuna_universal_prover() -> &'static UniversalProver<Self::PairingCurve> {
350 MainnetV0::varuna_universal_prover()
351 }
352
353 fn varuna_universal_verifier() -> &'static UniversalVerifier<Self::PairingCurve> {
355 MainnetV0::varuna_universal_verifier()
356 }
357
358 fn varuna_fs_parameters() -> &'static FiatShamirParameters<Self> {
360 &VARUNA_FS_PARAMETERS
361 }
362
363 fn commitment_domain() -> Field<Self> {
365 *COMMITMENT_DOMAIN
366 }
367
368 fn encryption_domain() -> Field<Self> {
370 *ENCRYPTION_DOMAIN
371 }
372
373 fn graph_key_domain() -> Field<Self> {
375 *GRAPH_KEY_DOMAIN
376 }
377
378 fn serial_number_domain() -> Field<Self> {
380 *SERIAL_NUMBER_DOMAIN
381 }
382
383 fn commit_bhp256(input: &[bool], randomizer: &Scalar<Self>) -> Result<Field<Self>> {
385 TESTNET_BHP_256.commit(input, randomizer)
386 }
387
388 fn commit_bhp512(input: &[bool], randomizer: &Scalar<Self>) -> Result<Field<Self>> {
390 TESTNET_BHP_512.commit(input, randomizer)
391 }
392
393 fn commit_bhp768(input: &[bool], randomizer: &Scalar<Self>) -> Result<Field<Self>> {
395 TESTNET_BHP_768.commit(input, randomizer)
396 }
397
398 fn commit_bhp1024(input: &[bool], randomizer: &Scalar<Self>) -> Result<Field<Self>> {
400 TESTNET_BHP_1024.commit(input, randomizer)
401 }
402
403 fn commit_ped64(input: &[bool], randomizer: &Scalar<Self>) -> Result<Field<Self>> {
405 TESTNET_PEDERSEN_64.commit(input, randomizer)
406 }
407
408 fn commit_ped128(input: &[bool], randomizer: &Scalar<Self>) -> Result<Field<Self>> {
410 TESTNET_PEDERSEN_128.commit(input, randomizer)
411 }
412
413 fn commit_to_group_bhp256(input: &[bool], randomizer: &Scalar<Self>) -> Result<Group<Self>> {
415 TESTNET_BHP_256.commit_uncompressed(input, randomizer)
416 }
417
418 fn commit_to_group_bhp512(input: &[bool], randomizer: &Scalar<Self>) -> Result<Group<Self>> {
420 TESTNET_BHP_512.commit_uncompressed(input, randomizer)
421 }
422
423 fn commit_to_group_bhp768(input: &[bool], randomizer: &Scalar<Self>) -> Result<Group<Self>> {
425 TESTNET_BHP_768.commit_uncompressed(input, randomizer)
426 }
427
428 fn commit_to_group_bhp1024(input: &[bool], randomizer: &Scalar<Self>) -> Result<Group<Self>> {
430 TESTNET_BHP_1024.commit_uncompressed(input, randomizer)
431 }
432
433 fn commit_to_group_ped64(input: &[bool], randomizer: &Scalar<Self>) -> Result<Group<Self>> {
435 TESTNET_PEDERSEN_64.commit_uncompressed(input, randomizer)
436 }
437
438 fn commit_to_group_ped128(input: &[bool], randomizer: &Scalar<Self>) -> Result<Group<Self>> {
440 TESTNET_PEDERSEN_128.commit_uncompressed(input, randomizer)
441 }
442
443 fn hash_bhp256(input: &[bool]) -> Result<Field<Self>> {
445 TESTNET_BHP_256.hash(input)
446 }
447
448 fn hash_bhp512(input: &[bool]) -> Result<Field<Self>> {
450 TESTNET_BHP_512.hash(input)
451 }
452
453 fn hash_bhp768(input: &[bool]) -> Result<Field<Self>> {
455 TESTNET_BHP_768.hash(input)
456 }
457
458 fn hash_bhp1024(input: &[bool]) -> Result<Field<Self>> {
460 TESTNET_BHP_1024.hash(input)
461 }
462
463 fn hash_keccak256(input: &[bool]) -> Result<Vec<bool>> {
465 Keccak256::default().hash(input)
466 }
467
468 fn hash_keccak384(input: &[bool]) -> Result<Vec<bool>> {
470 Keccak384::default().hash(input)
471 }
472
473 fn hash_keccak512(input: &[bool]) -> Result<Vec<bool>> {
475 Keccak512::default().hash(input)
476 }
477
478 fn hash_ped64(input: &[bool]) -> Result<Field<Self>> {
480 TESTNET_PEDERSEN_64.hash(input)
481 }
482
483 fn hash_ped128(input: &[bool]) -> Result<Field<Self>> {
485 TESTNET_PEDERSEN_128.hash(input)
486 }
487
488 fn hash_psd2(input: &[Field<Self>]) -> Result<Field<Self>> {
490 TESTNET_POSEIDON_2.hash(input)
491 }
492
493 fn hash_psd4(input: &[Field<Self>]) -> Result<Field<Self>> {
495 TESTNET_POSEIDON_4.hash(input)
496 }
497
498 fn hash_psd8(input: &[Field<Self>]) -> Result<Field<Self>> {
500 TESTNET_POSEIDON_8.hash(input)
501 }
502
503 fn hash_sha3_256(input: &[bool]) -> Result<Vec<bool>> {
505 Sha3_256::default().hash(input)
506 }
507
508 fn hash_sha3_384(input: &[bool]) -> Result<Vec<bool>> {
510 Sha3_384::default().hash(input)
511 }
512
513 fn hash_sha3_512(input: &[bool]) -> Result<Vec<bool>> {
515 Sha3_512::default().hash(input)
516 }
517
518 fn hash_many_psd2(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
520 TESTNET_POSEIDON_2.hash_many(input, num_outputs)
521 }
522
523 fn hash_many_psd4(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
525 TESTNET_POSEIDON_4.hash_many(input, num_outputs)
526 }
527
528 fn hash_many_psd8(input: &[Field<Self>], num_outputs: u16) -> Vec<Field<Self>> {
530 TESTNET_POSEIDON_8.hash_many(input, num_outputs)
531 }
532
533 fn hash_to_group_bhp256(input: &[bool]) -> Result<Group<Self>> {
535 TESTNET_BHP_256.hash_uncompressed(input)
536 }
537
538 fn hash_to_group_bhp512(input: &[bool]) -> Result<Group<Self>> {
540 TESTNET_BHP_512.hash_uncompressed(input)
541 }
542
543 fn hash_to_group_bhp768(input: &[bool]) -> Result<Group<Self>> {
545 TESTNET_BHP_768.hash_uncompressed(input)
546 }
547
548 fn hash_to_group_bhp1024(input: &[bool]) -> Result<Group<Self>> {
550 TESTNET_BHP_1024.hash_uncompressed(input)
551 }
552
553 fn hash_to_group_ped64(input: &[bool]) -> Result<Group<Self>> {
555 TESTNET_PEDERSEN_64.hash_uncompressed(input)
556 }
557
558 fn hash_to_group_ped128(input: &[bool]) -> Result<Group<Self>> {
560 TESTNET_PEDERSEN_128.hash_uncompressed(input)
561 }
562
563 fn hash_to_group_psd2(input: &[Field<Self>]) -> Result<Group<Self>> {
565 TESTNET_POSEIDON_2.hash_to_group(input)
566 }
567
568 fn hash_to_group_psd4(input: &[Field<Self>]) -> Result<Group<Self>> {
570 TESTNET_POSEIDON_4.hash_to_group(input)
571 }
572
573 fn hash_to_group_psd8(input: &[Field<Self>]) -> Result<Group<Self>> {
575 TESTNET_POSEIDON_8.hash_to_group(input)
576 }
577
578 fn hash_to_scalar_psd2(input: &[Field<Self>]) -> Result<Scalar<Self>> {
580 TESTNET_POSEIDON_2.hash_to_scalar(input)
581 }
582
583 fn hash_to_scalar_psd4(input: &[Field<Self>]) -> Result<Scalar<Self>> {
585 TESTNET_POSEIDON_4.hash_to_scalar(input)
586 }
587
588 fn hash_to_scalar_psd8(input: &[Field<Self>]) -> Result<Scalar<Self>> {
590 TESTNET_POSEIDON_8.hash_to_scalar(input)
591 }
592
593 fn merkle_tree_bhp<const DEPTH: u8>(leaves: &[Vec<bool>]) -> Result<BHPMerkleTree<Self, DEPTH>> {
595 MerkleTree::new(&*TESTNET_BHP_1024, &*TESTNET_BHP_512, leaves)
596 }
597
598 fn merkle_tree_psd<const DEPTH: u8>(leaves: &[Vec<Field<Self>>]) -> Result<PoseidonMerkleTree<Self, DEPTH>> {
600 MerkleTree::new(&*TESTNET_POSEIDON_4, &*TESTNET_POSEIDON_2, leaves)
601 }
602
603 fn verify_merkle_path_bhp<const DEPTH: u8>(
605 path: &MerklePath<Self, DEPTH>,
606 root: &Field<Self>,
607 leaf: &Vec<bool>,
608 ) -> bool {
609 path.verify(&*TESTNET_BHP_1024, &*TESTNET_BHP_512, root, leaf)
610 }
611
612 fn verify_merkle_path_psd<const DEPTH: u8>(
614 path: &MerklePath<Self, DEPTH>,
615 root: &Field<Self>,
616 leaf: &Vec<Field<Self>>,
617 ) -> bool {
618 path.verify(&*TESTNET_POSEIDON_4, &*TESTNET_POSEIDON_2, root, leaf)
619 }
620}
621
622#[cfg(test)]
623mod tests {
624 use super::*;
625
626 type CurrentNetwork = TestnetV0;
627
628 #[test]
629 fn test_g_scalar_multiply() {
630 let scalar = Scalar::rand(&mut TestRng::default());
632 let group = CurrentNetwork::g_scalar_multiply(&scalar);
633 assert_eq!(group, CurrentNetwork::g_powers()[0] * scalar);
634 }
635}