# confidential_transfer In this tutorial, we are going to generate test data and test its functionalities. We assume that you already unserstand what [Confidential Transfer](./2_1_confidential_transfer.md) is. The steps are following. 1. Define the `confidential_transfer` as depencencies 2. Generate test data used for `confidential_transfer` 3. Test funcitonalities ## 1. Define the confidential_transfer as depencencies First of all, you need to define the `confidential_transfer`. - /Cargo.toml ```toml confidential_transfer = { git = "https://github.com/zero-network/zero", branch = "master", default-features = false } pallet_encrypted_balance = { git = "https://github.com/zero-network/zero", branch = "master", default-features = false } pallet_plonk = { git = "https://github.com/zero-network/zero", branch = "master", default-features = false } zero_elgamal = { git = "https://github.com/zero-network/zero", branch = "master", default-features = false } zero_bls12_381 = { git = "https://github.com/zero-network/zero", branch = "master", default-features = false } rand_core = {version="0.6", default-features = false } ``` The `confidential_transfer` depends on `rand_core` so please import it. ## 2. Generate test data used for `confidential_transfer` Secondly, we would like like to setup the Alice and Bob account on testing runtime. Define the `new_test_ext` for genesis config and reflect the testing data for runtime storage. ```rust fn new_test_ext( alice_address: u64, alice_private_key: Fp, alice_balance: u32, alice_radomness: Fp, bob_private_key: Fp, bob_address: u64, bob_balance: u32, bob_radomness: Fp, ) -> sp_io::TestExternalities { let alice_balance = EncryptedNumber::encrypt(alice_private_key, alice_balance, alice_radomness); let bob_balance = EncryptedNumber::encrypt(bob_private_key, bob_balance, bob_radomness); let mut t = frame_system::GenesisConfig::default() .build_storage::() .unwrap(); pallet_encrypted_balance::GenesisConfig:: { balances: vec![(alice_address, alice_balance), (bob_address, bob_balance)], } .assimilate_storage(&mut t) .unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); ext } ``` Thirdly, we define `generate_default_test_data` to generate parameters used for `confidential_transfer`. ```rust fn generate_default_test_data() -> (u64, Fp, u16, Fp, Fp, u64, u16, Fp, u16, u16, u16) { let mut rng = rand::thread_rng(); let alice_address = rng.gen::(); let alice_private_key = Fp::random(OsRng); let alice_balance = rng.gen::(); let alice_radomness = Fp::random(OsRng); let bob_private_key = Fp::random(OsRng); let bob_address = rng.gen::(); let bob_balance = rng.gen::(); let bob_radomness = Fp::random(OsRng); let transfer_amount = rng.gen_range(0..alice_balance); let alice_after_balance = alice_balance - transfer_amount; let bob_after_balance = bob_balance + transfer_amount; ( alice_address, alice_private_key, alice_balance, alice_radomness, bob_private_key, bob_address, bob_balance, bob_radomness, transfer_amount, alice_after_balance, bob_after_balance, ) } ``` ## 3. Test funcitonalities Finally, we combine previous sections together and test functionalities. ```rust fn main() { let k = 14; let label = b"verify"; let mut rng = get_rng(); let ( alice_address, alice_private_key, alice_balance, alice_radomness, bob_private_key, bob_address, bob_balance, bob_radomness, transfer_amount, alice_after_balance, bob_after_balance, transfer_randomness, ) = generate_default_test_data(); new_test_ext( alice_address, alice_private_key, alice_balance, alice_radomness, bob_private_key, bob_address, bob_balance, bob_radomness, ) .execute_with(|| { // default balance decryption check let alice_encrypted_balance = ConfidentialTransfer::total_balance(&alice_address); let alice_raw_balance = alice_encrypted_balance.decrypt(alice_private_key); let bob_encrypted_balance = ConfidentialTransfer::total_balance(&bob_address); let bob_raw_balance = bob_encrypted_balance.decrypt(bob_private_key); assert_eq!(alice_raw_balance.unwrap() as u16, alice_balance); assert_eq!(bob_raw_balance.unwrap() as u16, bob_balance); // trusted setup check let result = ConfidentialTransfer::trusted_setup(Origin::signed(alice_address), k, rng.clone()); assert_ok!(result); // proof generation let pp = Plonk::public_parameter().unwrap(); let alice_public_key = GENERATOR_EXTENDED * alice_private_key; let bob_public_key = GENERATOR_EXTENDED * bob_private_key; let transfer_amount_scalar = Fp::from(transfer_amount as u64); let alice_after_balance_scalar = Fp::from(alice_after_balance as u64); let alice_balance = EncryptedNumber::encrypt(alice_private_key, alice_balance.into(), alice_radomness); let alice_transfer_amount = EncryptedNumber::encrypt( alice_private_key, transfer_amount.into(), transfer_randomness, ); let bob_encrypted_transfer_amount = (GENERATOR_EXTENDED * transfer_amount_scalar) + (bob_public_key * transfer_randomness); let alice_public_key = JubJubAffine::from(alice_public_key); let bob_public_key = JubJubAffine::from(bob_public_key); let bob_encrypted_transfer_amount = JubJubAffine::from(bob_encrypted_transfer_amount); let bob_encrypted_transfer_amount_other = (GENERATOR_EXTENDED * transfer_randomness).into(); let confidential_transfer_circuit = ConfidentialTransferCircuit::new( alice_public_key, bob_public_key, alice_balance, alice_transfer_amount, bob_encrypted_transfer_amount, alice_private_key, transfer_amount_scalar, alice_after_balance_scalar, transfer_randomness, ); let prover = Compiler::compile::(&pp, label) .expect("failed to compile circuit"); let proof = prover .0 .prove(&mut rng, &confidential_transfer_circuit) .expect("failed to prove"); // confidential transfer check let transaction_params = ConfidentialTransferTransaction::new( alice_public_key, bob_public_key, alice_transfer_amount, bob_encrypted_transfer_amount, bob_encrypted_transfer_amount_other, ); let result = ConfidentialTransfer::confidential_transfer( Origin::signed(alice_address), bob_address, proof.0, transaction_params, ); assert_ok!(result); // balance transition check let alice_balance = ConfidentialTransfer::total_balance(&alice_address); let alice_raw_balance = alice_balance.decrypt(alice_private_key); let bob_balance = ConfidentialTransfer::total_balance(&bob_address); let bob_raw_balance = bob_balance.decrypt(bob_private_key); assert_eq!(alice_raw_balance.unwrap() as u16, alice_after_balance); assert_eq!(bob_raw_balance.unwrap() as u16, bob_after_balance); }) } ``` With above tests, we can confirm that confidential transfer works correctly. You can check the `confidential_transfer` example [here](https://github.com/zero-network/zero/confidential_transfer.rs). Happy hacking!