فهرست منبع

src/contract/money/verification_bench: test alice2alice_random_amounts_multiplecoins added

aggstam 3 سال پیش
والد
کامیت
830e73ad2f
1فایلهای تغییر یافته به همراه148 افزوده شده و 2 حذف شده
  1. 148 2
      src/contract/money/tests/verification_bench.rs

+ 148 - 2
src/contract/money/tests/verification_bench.rs

@@ -27,7 +27,7 @@ use darkfi_sdk::{
 };
 };
 use darkfi_serial::Encodable;
 use darkfi_serial::Encodable;
 use log::info;
 use log::info;
-use rand::{rngs::OsRng, Rng};
+use rand::{prelude::IteratorRandom, rngs::OsRng, Rng};
 
 
 use darkfi_money_contract::{
 use darkfi_money_contract::{
     client::{build_transfer_tx, Coin, EncryptedNote, OwnCoin},
     client::{build_transfer_tx, Coin, EncryptedNote, OwnCoin},
@@ -85,7 +85,7 @@ async fn alice2alice_random_amounts() -> Result<()> {
 
 
     for i in 0..n {
     for i in 0..n {
         info!("Building Alice2Alice transfer tx {}", i);
         info!("Building Alice2Alice transfer tx {}", i);
-        
+
         info!("Alice coins: {}", owncoins.len());
         info!("Alice coins: {}", owncoins.len());
         for (i, c) in owncoins.iter().enumerate() {
         for (i, c) in owncoins.iter().enumerate() {
             info!("\t coin {} value: {}", i, c.note.value);
             info!("\t coin {} value: {}", i, c.note.value);
@@ -152,3 +152,149 @@ async fn alice2alice_random_amounts() -> Result<()> {
 
 
     Ok(())
     Ok(())
 }
 }
+
+#[async_std::test]
+async fn alice2alice_random_amounts_multiplecoins() -> Result<()> {
+    init_logger()?;
+
+    // N blocks to simulate
+    let mut n = 3;
+    for arg in env::args() {
+        match usize::from_str(&arg) {
+            Ok(v) => {
+                n = v;
+                break
+            }
+            Err(_) => continue,
+        };
+    }
+
+    // Initialize harness
+    let mut th = MoneyTestHarness::new().await?;
+    let contract_id = ContractId::from(pallas::Base::from(u64::MAX - 420));
+
+    // Generating 10 airdrop coins
+    let mut token_ids = vec![];
+    let mut airdrops_amounts = vec![];
+    let mut owncoins = vec![];
+    for i in 0..10 {
+        let token_id = TokenId::from(pallas::Base::random(&mut OsRng));
+        let amount = rand::thread_rng().gen_range(1..1000);
+
+        info!("Generating token {}: ID {} - amount {}", i, token_id, amount);
+
+        let (airdrop_tx, airdrop_params) = th.airdrop(amount, token_id, &th.alice_kp.public)?;
+
+        th.faucet_state.read().await.verify_transactions(&[airdrop_tx.clone()], true).await?;
+        th.faucet_merkle_tree.append(&MerkleNode::from(airdrop_params.outputs[0].coin));
+
+        th.alice_state.read().await.verify_transactions(&[airdrop_tx.clone()], true).await?;
+        th.alice_merkle_tree.append(&MerkleNode::from(airdrop_params.outputs[0].coin));
+        let leaf_position = th.alice_merkle_tree.witness().unwrap();
+
+        let ciphertext = airdrop_params.outputs[0].ciphertext.clone();
+        let ephem_public = airdrop_params.outputs[0].ephem_public;
+        let e_note = EncryptedNote { ciphertext, ephem_public };
+        let note = e_note.decrypt(&th.alice_kp.secret)?;
+
+        owncoins.push(vec![OwnCoin {
+            coin: Coin::from(airdrop_params.outputs[0].coin),
+            note: note.clone(),
+            secret: th.alice_kp.secret,
+            nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+            leaf_position,
+        }]);
+        airdrops_amounts.push(amount);
+        token_ids.push(token_id);
+    }
+
+    // Simulating N blocks
+    for b in 0..n {
+        info!("Generating transactions for block: {}", b);
+        // Get a random sized sample of owncoins
+        let sample =
+            (0..10).choose_multiple(&mut rand::thread_rng(), rand::thread_rng().gen_range(0..10));
+        info!("Coins to use: {:?}", sample);
+
+        // Generate a transaction for each coin
+        let mut txs = vec![];
+        for index in sample {
+            info!("Building Alice2Alice transfer tx for coin {}", index);
+
+            let mut coins = owncoins[index].clone();
+            let token_id = token_ids[index];
+            let airdrop_amount = airdrops_amounts[index];
+
+            info!("Alice coins: {}", coins.len());
+            for (i, c) in coins.iter().enumerate() {
+                info!("\t coin {} value: {}", i, c.note.value);
+            }
+
+            let amount = rand::thread_rng().gen_range(1..airdrop_amount);
+            info!("Sending: {}", amount);
+
+            let (params, proofs, secret_keys, spent_coins) = build_transfer_tx(
+                &th.alice_kp,
+                &th.alice_kp.public,
+                amount,
+                token_id,
+                &coins,
+                &th.alice_merkle_tree,
+                &th.mint_zkbin,
+                &th.mint_pk,
+                &th.burn_zkbin,
+                &th.burn_pk,
+                false,
+            )?;
+
+            let mut data = vec![MoneyFunction::Transfer as u8];
+            params.encode(&mut data)?;
+            let calls = vec![ContractCall { contract_id, data }];
+            let proofs = vec![proofs];
+            let mut tx = Transaction { calls, proofs, signatures: vec![] };
+            let sigs = tx.create_sigs(&mut OsRng, &secret_keys)?;
+            tx.signatures = vec![sigs];
+
+            // Remove the owncoins we've spent
+            for spent in spent_coins {
+                coins.retain(|x| x != &spent);
+            }
+
+            // Store transaction
+            txs.push(tx.clone());
+
+            // Gather new owncoins
+            for output in params.outputs {
+                let e_note = EncryptedNote {
+                    ciphertext: output.ciphertext.clone(),
+                    ephem_public: output.ephem_public,
+                };
+                let note = e_note.decrypt(&th.alice_kp.secret)?;
+
+                th.alice_merkle_tree.append(&MerkleNode::from(output.coin));
+                let leaf_position = th.alice_merkle_tree.witness().unwrap();
+
+                let owncoin = OwnCoin {
+                    coin: Coin::from(output.coin),
+                    note: note.clone(),
+                    secret: th.alice_kp.secret,
+                    nullifier: Nullifier::from(poseidon_hash([
+                        th.alice_kp.secret.inner(),
+                        note.serial,
+                    ])),
+                    leaf_position,
+                };
+
+                coins.push(owncoin);
+            }
+
+            // Replace coins
+            owncoins[index] = coins;
+        }
+
+        // Apply the state transitions
+        th.alice_state.read().await.verify_transactions(&txs, true).await?;
+    }
+
+    Ok(())
+}