diff --git a/.github/workflows/zebra-test-ci.yaml b/.github/workflows/zebra-test-ci.yaml index 06dd044..64aec7e 100644 --- a/.github/workflows/zebra-test-ci.yaml +++ b/.github/workflows/zebra-test-ci.yaml @@ -18,6 +18,13 @@ jobs: runs-on: ubuntu-latest steps: + - name: Free disk space (safe cleanup for Rust CI) + run: | + # Remove heavy preinstalled SDKs and toolchains + sudo rm -rf /usr/local/lib/android || true + sudo rm -rf /opt/hostedtoolcache || true + df -h + - name: Checkout tx-tool code uses: actions/checkout@v3 with: diff --git a/src/commands/test_orchard.rs b/src/commands/test_orchard.rs index 87f1b62..92e7b1c 100644 --- a/src/commands/test_orchard.rs +++ b/src/commands/test_orchard.rs @@ -52,7 +52,8 @@ impl Runnable for TestOrchardCmd { let shielding_tx = create_shield_coinbase_transaction(miner_addr, coinbase_txid, &mut wallet); - mine(&mut wallet, &mut rpc_client, Vec::from([shielding_tx])); + mine(&mut wallet, &mut rpc_client, Vec::from([shielding_tx])) + .expect("block mined successfully"); let expected_balances = expected_balances_after_mine(&balances, 0); check_balances( @@ -84,7 +85,7 @@ impl Runnable for TestOrchardCmd { let txs = txi.to_transactions(&mut wallet); - mine(&mut wallet, &mut rpc_client, txs); + mine(&mut wallet, &mut rpc_client, txs).expect("block mined successfully"); check_balances( AssetBase::native(), @@ -104,6 +105,7 @@ impl Runnable for TestOrchardCmd { fn prepare_test(target_height: u32, wallet: &mut User, rpc_client: &mut ReqwestRpcClient) -> TxId { sync_from_height(target_height, wallet, rpc_client); let activate = wallet.last_block_height().is_none(); - let (_, coinbase_txid) = mine_empty_blocks(100, rpc_client, activate); // coinbase maturity = 100 + let (_, coinbase_txid) = + mine_empty_blocks(100, rpc_client, activate).expect("block mined successfully"); // coinbase maturity = 100 coinbase_txid } diff --git a/src/commands/test_orchard_zsa.rs b/src/commands/test_orchard_zsa.rs index 2454ffe..b5431af 100644 --- a/src/commands/test_orchard_zsa.rs +++ b/src/commands/test_orchard_zsa.rs @@ -16,7 +16,9 @@ use crate::commands::test_balances::{ BurnInfo, TestBalances, TransferInfo, TxiBatch, }; use crate::components::rpc_client::reqwest::ReqwestRpcClient; -use crate::components::transactions::{create_issue_transaction, mine, sync_from_height}; +use crate::components::transactions::{ + create_issue_transaction, create_finalization_transaction, mine, sync_from_height, +}; use crate::components::user::User; use crate::prelude::*; @@ -55,7 +57,8 @@ impl Runnable for TestOrchardZSACmd { let balances = TestBalances::get_asset_balances(asset, num_users, &mut wallet); print_balances("=== Initial balances ===", asset, &balances); - mine(&mut wallet, &mut rpc_client, Vec::from([issue_tx])); + mine(&mut wallet, &mut rpc_client, Vec::from([issue_tx])) + .expect("block mined successfully"); let balances = TestBalances::get_asset_balances(asset, num_users, &mut wallet); print_balances("=== Balances after issue ===", asset, &balances); @@ -69,7 +72,7 @@ impl Runnable for TestOrchardZSACmd { let txs = txi.to_transactions(&mut wallet); - mine(&mut wallet, &mut rpc_client, txs); + mine(&mut wallet, &mut rpc_client, txs).expect("block mined successfully"); check_balances(asset, &expected_balances, &mut wallet, num_users); @@ -91,12 +94,30 @@ impl Runnable for TestOrchardZSACmd { let txs = txi.to_transactions(&mut wallet); - mine(&mut wallet, &mut rpc_client, txs); + mine(&mut wallet, &mut rpc_client, txs).expect("block mined successfully"); // burn from issuer(account0) and alice(account1) check_balances(asset, &expected_balances, &mut wallet, num_users); print_balances("=== Balances after burning ===", asset, &expected_balances); + + // --------------------- Finalization --------------------- + + let finalization_tx = create_finalization_transaction(asset_desc_hash, &mut wallet); + mine(&mut wallet, &mut rpc_client, Vec::from([finalization_tx])) + .expect("block mined successfully"); + + let invalid_issue_tx = + create_issue_transaction(issuer_addr, 2000, asset_desc_hash, true, &mut wallet); + let result = mine( + &mut wallet, + &mut rpc_client, + Vec::from([invalid_issue_tx.0]), + ); + assert!( + result.is_err(), + "Issue transaction was unexpectedly accepted after asset finalization" + ); } } diff --git a/src/commands/test_three_party.rs b/src/commands/test_three_party.rs index fc4a9e1..c5d5998 100644 --- a/src/commands/test_three_party.rs +++ b/src/commands/test_three_party.rs @@ -57,7 +57,8 @@ impl Runnable for TestThreePartyCmd { let balances = TestBalances::get_asset_balances(asset, num_users, &mut wallet); print_balances("=== Initial balances ===", asset, &balances); - mine(&mut wallet, &mut rpc_client, Vec::from([issue_tx])); + mine(&mut wallet, &mut rpc_client, Vec::from([issue_tx])) + .expect("block mined successfully"); let balances = TestBalances::get_asset_balances(asset, num_users, &mut wallet); print_balances("=== Balances after issue ===", asset, &balances); @@ -72,7 +73,7 @@ impl Runnable for TestThreePartyCmd { let txs = txi.to_transactions(&mut wallet); - mine(&mut wallet, &mut rpc_client, txs); + mine(&mut wallet, &mut rpc_client, txs).expect("block mined successfully"); check_balances(asset, &expected_balances, &mut wallet, num_users); @@ -96,7 +97,7 @@ impl Runnable for TestThreePartyCmd { let txs = txi.to_transactions(&mut wallet); - mine(&mut wallet, &mut rpc_client, txs); + mine(&mut wallet, &mut rpc_client, txs).expect("block mined successfully"); check_balances(asset, &expected_balances, &mut wallet, num_users); @@ -118,7 +119,7 @@ impl Runnable for TestThreePartyCmd { let txs = txi.to_transactions(&mut wallet); - mine(&mut wallet, &mut rpc_client, txs); + mine(&mut wallet, &mut rpc_client, txs).expect("block mined successfully"); check_balances(asset, &expected_balances, &mut wallet, num_users); diff --git a/src/components/transactions.rs b/src/components/transactions.rs index a290415..28ef58c 100644 --- a/src/components/transactions.rs +++ b/src/components/transactions.rs @@ -9,6 +9,7 @@ use orchard::note::AssetBase; use orchard::value::NoteValue; use orchard::Address; use rand::rngs::OsRng; +use std::error::Error; use std::convert::TryFrom; use std::ops::Add; use orchard::keys::{IssuanceValidatingKey, SpendAuthorizingKey}; @@ -27,10 +28,15 @@ use zcash_transparent::bundle::{OutPoint, TxOut}; const COINBASE_VALUE: u64 = 625_000_000; /// Mine a block with the given transactions and sync the user -pub fn mine(wallet: &mut User, rpc_client: &mut dyn RpcClient, txs: Vec) { +pub fn mine( + wallet: &mut User, + rpc_client: &mut dyn RpcClient, + txs: Vec, +) -> Result<(), Box> { let activate = wallet.last_block_height().is_none(); - let (_, _) = mine_block(rpc_client, txs, activate); + let (_, _) = mine_block(rpc_client, txs, activate)?; sync(wallet, rpc_client); + Ok(()) } /// Mine a block with the given transactions and return the block height and coinbase txid @@ -38,16 +44,16 @@ pub fn mine_block( rpc_client: &mut dyn RpcClient, txs: Vec, activate: bool, -) -> (u32, TxId) { - let block_template = rpc_client.get_block_template().unwrap(); +) -> Result<(u32, TxId), Box> { + let block_template = rpc_client.get_block_template()?; let block_height = block_template.height; let block_proposal = template_into_proposal(block_template, txs, activate); let coinbase_txid = block_proposal.transactions.first().unwrap().txid(); - rpc_client.submit_block(block_proposal).unwrap(); + rpc_client.submit_block(block_proposal)?; - (block_height, coinbase_txid) + Ok((block_height, coinbase_txid)) } /// Mine the given number of empty blocks and return the block height and coinbase txid of the first block @@ -55,18 +61,18 @@ pub fn mine_empty_blocks( num_blocks: u32, rpc_client: &mut dyn RpcClient, activate: bool, -) -> (u32, TxId) { +) -> Result<(u32, TxId), Box> { if num_blocks == 0 { panic!("num_blocks must be greater than 0") } - let (block_height, coinbase_txid) = mine_block(rpc_client, vec![], activate); + let (block_height, coinbase_txid) = mine_block(rpc_client, vec![], activate)?; for _ in 1..num_blocks { - mine_block(rpc_client, vec![], false); + mine_block(rpc_client, vec![], false)?; } - (block_height, coinbase_txid) + Ok((block_height, coinbase_txid)) } /// Create a shielded coinbase transaction