Skip to content

Commit

Permalink
Merge pull request #593 from pacu/arot-tx-height-changes
Browse files Browse the repository at this point in the history
Advanced ReOrg Test: ReOrg changes tx height
  • Loading branch information
fluidvanadium authored Nov 22, 2023
2 parents 16ff2b7 + 023a313 commit ceaef35
Show file tree
Hide file tree
Showing 36 changed files with 855 additions and 15 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion darkside-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
zingolib = { path = "../zingolib", features = ["test"] }
zingo-cli = { path = "../zingocli" }
zingolib = { path = "../zingolib", features = ["test", "darkside_tests"] }
zingo-testutils = { path = "../zingo-testutils" }
zingoconfig = { path = "../zingoconfig" }
tokio = { version = "1.25.0", features = ["full"] }
Expand Down
9 changes: 9 additions & 0 deletions darkside-tests/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
use crate::darkside_types::TreeState;

pub const ADVANCED_REORG_TESTS_USER_WALLET: &str =
"wrong when collect sponsor always simple control color exercise dad merry diet script attract public lucky pen pistol depend deposit salad room similar hour";
pub const REORG_CHANGES_INCOMING_TX_HEIGHT_AFTER: &str =
"tests/data/wallets/advanced_reorg_tests/tx_height_changes/after_reorg.txt";
pub const REORG_CHANGES_INCOMING_TX_HEIGHT_BEFORE: &str =
"tests/data/wallets/advanced_reorg_tests/tx_height_changes/before_reorg.txt";
pub const TREE_STATE_FOLDER_PATH: &str =
"tests/data/wallets/advanced_reorg_tests/tx_height_changes/tree_states";

pub const GENESIS_BLOCK: &str = "0400000027e30134d620e9fe61f719938320bab63e7e72c91b5e23025676f90ed8119f02c94c1ef3fa94b348f1b6d1bdf5899ad1eac7bfbf0de6d2cd1a4bedf84699b09c415071fecf148b458b159d1d310b2d072e8250bfefcd1a7ead2b309071f6e954ecf581640f0f0f201b0092b34257e0a52315e66f950db025ae0b0b3b6c71aa017c8a2348b4dd00002400f5c2c1b120d8abc30adf542ee48f6301eb0f730839c15bfcdbb42df0a8d4a326cd9389010400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff000000000001000000c041bfdaffffffff0001fc0ffba31852cdff6ccbbb61157848f9fb42e6a6eb831806a5e1955f21dc943c5fcb897f9314fc5ebac4510b86706f45458c6db1d36dbab6ee23315e9654c54cfdd8aaf1af233dee596a2f03d42315fde064eade886a2b10843807d9498e9a83604227bb3dcc516b05c1f87ff343099d89d8fe27196be88ea0f6a59503bbdf4992a740469cd449dd253e18eaeb6392e435e22d3d1dc75530b30a06f1ae3ea8dab48e637cea7747a571f7539e338461fd5938581878f9b6111b59de5c25d93043b99c8472d04bb0300eaa68eeba6ccac5de0d36fe25bf3639d58fbc2480b8fcab31dada9929d9bf44515c5d1517817047d22badd35a37f174b3803fe6a9dece7f11c93af94c33eb8b442bc94d728452a545ce35a41ad2580c8c737a245d5cdc5f36df5bdd4ed27ffb6568893c909c690c95d6db22f09680f4febe906d456070dc9363b497c67b854125572a811a24a65b63e191e09026b7409b71e18e5fe62d3d1840a557d4b222e07e00dac01131f0993a91914e70ed8f6a609f0c894f6eeaf3b35fcc830159851fff0d38ed3c0f15acb3d4de404ead0bfdd9c10d169cdd4bb1cf4a074349c330b57636b093a9b3b749ed14ef347326b313267f34be94ec9b9b7ae41d4ccd7364ed647a5a74b432cd3c063d5b2bbaedddba11e25107ec4e89c41ff45173ae49e3a323280aa9a3cdc8d9a7c264d1f08cc2bcc486d02fa2158054aaa55e82448e827a7a50778d04308a99401eeb7c835568c15ca2104bd05ebe569eed9ac64ef63143eeb4bf203ac6215cd63f921bfc2b3d704533cb32a82fbbe4caa677ee1a970e10dd4a36b4a8cd3003adc2962776a74aadb5577c457664a4970fa0c78d4edcb48e5743433d5f4d329148bf2d4a6c3f536ebad618ece61ebe09c60a8ec0ac73d9c6ba0429ac4a63d6b37db740fff665c9a2daf2b8c24f0269a9fe34ea99578926efa81b40da08d66bc4c04ccbf0f6a96a0bbda3966282af280600a686365ab3eb47a46a4204d40340aea39c0ebb910a786e0b88a115d9d9d95e1661d4548ba1cb5941082d3249aa37444b844fb1932e81d4427efad6ebc4addff3daf3246a0f77273aa1ad352fcbddf4fa617bcee201eae7c763737f2168d236fa764e17addf1ecb42706e30918378b1b2a0aca3233a129f55685264c6f5a49867fdaa73797616c785d18a707805c2514e91af9015f0cbf2097be74ee4ee81eed4723afd0d45f656c539e2e6e4578ad342d84a2d812199486e0d57094125551fd3a268a383c1f9642809858b23aa11a7e242012f49c0d66417177d4cd0de2ca4430929a7e50e9cd8b569cfd17cf648473e80cea7003e4aa0cc382d6bf962bed6a00cade090c0b43ff689dcd535085e2aac6fe807e6263b2564b86c469baeb3586c1e0db5039ced9ac723f3911e28e396655e825101";
pub const DARKSIDE_SEED: &str =
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread";
Expand Down
55 changes: 53 additions & 2 deletions darkside-tests/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::{
path::PathBuf,
fs,
fs::File,
io::{self, BufRead},
path::{Path, PathBuf},
process::{Child, Command},
sync::Arc,
time::Duration,
Expand Down Expand Up @@ -66,7 +69,7 @@ impl DarksideConnector {
Self(uri)
}

pub(crate) fn get_client(
pub fn get_client(
&self,
) -> impl std::future::Future<
Output = Result<DarksideStreamerClient<UnderlyingService>, Box<dyn std::error::Error>>,
Expand Down Expand Up @@ -333,3 +336,51 @@ pub async fn update_tree_states_for_transaction(
.unwrap();
new_tree_state
}

// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
// source: https://doc.rust-lang.org/rust-by-example/std_misc/file/read_lines.html
pub fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where
P: AsRef<Path>,
{
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}

pub fn read_block_dataset<P>(filename: P) -> Vec<String>
where
P: AsRef<Path>,
{
read_lines(filename)
.unwrap()
.map(|line| line.unwrap())
.collect()
}

impl TreeState {
pub fn from_file<P>(filename: P) -> Result<TreeState, Box<dyn std::error::Error>>
where
P: AsRef<Path>,
{
let state_string = fs::read_to_string(filename)?;
let json_state: serde_json::Value = serde_json::from_str(&state_string)?;

let network = json_state["network"].as_str().unwrap();
let height = json_state["height"].as_u64().unwrap();
let hash = json_state["hash"].as_str().unwrap();
let time = json_state["time"].as_i64().unwrap();
let time_32: u32 = u32::try_from(time)?;
let sapling_tree = json_state["saplingTree"].as_str().unwrap();
let orchard_tree = json_state["orchardTree"].as_str().unwrap();

Ok(TreeState {
network: network.to_string(),
height,
hash: hash.to_string(),
time: time_32,
sapling_tree: sapling_tree.to_string(),
orchard_tree: orchard_tree.to_string(),
})
}
}
204 changes: 204 additions & 0 deletions darkside-tests/tests/advanced_reorg_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
use darkside_tests::{
constants::{
ADVANCED_REORG_TESTS_USER_WALLET, BRANCH_ID, REORG_CHANGES_INCOMING_TX_HEIGHT_AFTER,
REORG_CHANGES_INCOMING_TX_HEIGHT_BEFORE, TREE_STATE_FOLDER_PATH,
},
darkside_types::{Empty, TreeState},
utils::{read_block_dataset, read_lines, DarksideConnector, DarksideHandler},
};

use tokio::time::sleep;
use zcash_primitives::consensus::BlockHeight;
use zingo_testutils::{regtest::get_cargo_manifest_dir, scenarios::setup::ClientBuilder};
use zingoconfig::RegtestNetwork;
use zingolib::lightclient::PoolBalances;

#[tokio::test]
async fn reorg_changes_incoming_tx_height() {
let darkside_handler = DarksideHandler::new(None);

let server_id = zingoconfig::construct_lightwalletd_uri(Some(format!(
"http://127.0.0.1:{}",
darkside_handler.grpc_port
)));

prepare_before_tx_height_change_reorg(server_id.clone())
.await
.unwrap();

let light_client = ClientBuilder::new(server_id.clone(), darkside_handler.darkside_dir.clone())
.build_client(
ADVANCED_REORG_TESTS_USER_WALLET.to_string(),
202,
true,
RegtestNetwork::all_upgrades_active(),
)
.await;

light_client.do_sync(true).await.unwrap();
assert_eq!(
light_client.do_balance().await,
PoolBalances {
sapling_balance: Some(0),
verified_sapling_balance: Some(0),
spendable_sapling_balance: Some(0),
unverified_sapling_balance: Some(0),
orchard_balance: Some(100000000),
verified_orchard_balance: Some(100000000),
spendable_orchard_balance: Some(100000000),
unverified_orchard_balance: Some(0),
transparent_balance: Some(0)
}
);

let before_reorg_transactions = light_client.do_list_txsummaries().await;

assert_eq!(before_reorg_transactions.len(), 1);
assert_eq!(
before_reorg_transactions[0].block_height,
BlockHeight::from_u32(203)
);

prepare_after_tx_height_change_reorg(server_id.clone())
.await
.unwrap();

let reorg_sync_result = light_client.do_sync(true).await;

match reorg_sync_result {
Ok(value) => println!("{}", value),
Err(err_str) => println!("{}", err_str),
};

// Assert that balance holds
assert_eq!(
light_client.do_balance().await,
PoolBalances {
sapling_balance: Some(0),
verified_sapling_balance: Some(0),
spendable_sapling_balance: Some(0),
unverified_sapling_balance: Some(0),
orchard_balance: Some(100000000),
verified_orchard_balance: Some(100000000),
spendable_orchard_balance: Some(100000000),
unverified_orchard_balance: Some(0),
transparent_balance: Some(0)
}
);

let after_reorg_transactions = light_client.do_list_txsummaries().await;

assert_eq!(after_reorg_transactions.len(), 1);
assert_eq!(
after_reorg_transactions[0].block_height,
BlockHeight::from_u32(206)
);
}

async fn prepare_before_tx_height_change_reorg(uri: http::Uri) -> Result<(), String> {
dbg!(&uri);
let connector = DarksideConnector(uri.clone());

let mut client = connector.get_client().await.unwrap();
// Setup prodedures. Up to this point there's no communication between the client and the dswd
client.clear_address_utxo(Empty {}).await.unwrap();

// reset with parameters
connector
.reset(202, String::from(BRANCH_ID), String::from("regtest"))
.await
.unwrap();

let dataset_path = format!(
"{}/{}",
get_cargo_manifest_dir().to_string_lossy(),
REORG_CHANGES_INCOMING_TX_HEIGHT_BEFORE
);

println!("dataset path: {}", dataset_path);

connector
.stage_blocks_stream(read_block_dataset(dataset_path))
.await?;

for i in 201..207 {
let tree_state_path = format!(
"{}/{}/{}.json",
get_cargo_manifest_dir().to_string_lossy(),
TREE_STATE_FOLDER_PATH,
i
);
let tree_state = TreeState::from_file(tree_state_path).unwrap();
connector.add_tree_state(tree_state).await.unwrap();
}

connector.apply_staged(204).await?;

sleep(std::time::Duration::new(1, 0)).await;

Ok(())
}

async fn prepare_after_tx_height_change_reorg(uri: http::Uri) -> Result<(), String> {
dbg!(&uri);
let connector = DarksideConnector(uri.clone());

let mut client = connector.get_client().await.unwrap();
// Setup prodedures. Up to this point there's no communication between the client and the dswd
client.clear_address_utxo(Empty {}).await.unwrap();

let dataset_path = format!(
"{}/{}",
get_cargo_manifest_dir().to_string_lossy(),
REORG_CHANGES_INCOMING_TX_HEIGHT_AFTER
);
connector
.stage_blocks_stream(
read_lines(dataset_path)
.unwrap()
.map(|line| line.unwrap())
.collect(),
)
.await?;

connector.apply_staged(206).await?;

sleep(std::time::Duration::new(1, 0)).await;

Ok(())
}

#[tokio::test]
async fn test_read_block_dataset() {
let dataset_path = format!(
"{}/{}",
get_cargo_manifest_dir().to_string_lossy(),
REORG_CHANGES_INCOMING_TX_HEIGHT_BEFORE
);
let blocks = read_block_dataset(dataset_path);
assert_eq!(blocks.len(), 21)
}

#[tokio::test]
async fn test_read_tree_state_from_file() {
let tree_state_path = format!(
"{}/{}/{}.json",
get_cargo_manifest_dir().to_string_lossy(),
TREE_STATE_FOLDER_PATH,
203
);

println!("{}", tree_state_path);

let tree_state = TreeState::from_file(tree_state_path).unwrap();

assert_eq!(tree_state.network.as_str(), "regtest");
assert_eq!(tree_state.height, 203);
assert_eq!(
tree_state.hash,
"016da97020ab191559f34f1d3f992ce2ec7c609cb0e5b932c45f1693eeb2192f"
);
assert_eq!(tree_state.time, 1694454196);
assert_eq!(tree_state.sapling_tree, "000000");
assert_eq!(tree_state.orchard_tree, "01136febe0db97210efb679e378d3b3a49d6ac72d0161ae478b1faaa9bd26a2118012246dd85ba2d9510caa03c40f0b75f7b02cb0cfac88ec1c4b9193d58bb6d44201f000001f0328e13a28669f9a5bd2a1c5301549ea28ccb7237347b9c76c05276952ad135016be8aefe4f98825b5539a2b47b90a8057e52c1e1badc725d67c06b4cc2a32e24000000000000000000000000000000000000000000000000000000");
}
Loading

0 comments on commit ceaef35

Please sign in to comment.