Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix panic when number of blocks <= reorg buffer offset #574

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions zingocli/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@ use zingolib::{
},
};

#[tokio::test]
async fn send_without_reorg_buffer_blocks_gives_correct_error() {
let (_regtest_manager, _cph, faucet, mut recipient) =
scenarios::two_wallet_one_miner_fund().await;
recipient
.wallet
.transaction_context
.config
.reorg_buffer_offset = 4;
println!(
"{}",
serde_json::to_string_pretty(&recipient.do_balance().await).unwrap()
);
assert_eq!(
recipient
.do_send(vec![(&get_base_address!(faucet, "unified"), 100_000, None)])
.await
.unwrap_err(),
"The reorg buffer offset has been set to 4 but there are only 1 blocks in the wallet. Please sync at least 4 more blocks before trying again"
);
}

#[tokio::test]
async fn dont_write_unconfirmed() {
let (regtest_manager, _cph, faucet, recipient) = scenarios::two_wallet_one_miner_fund().await;
Expand Down
2 changes: 1 addition & 1 deletion zingolib/src/blaze/fetch_full_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use zingoconfig::{ChainType, ZingoConfig};

#[derive(Clone)]
pub struct TransactionContext {
pub(crate) config: ZingoConfig,
pub config: ZingoConfig,
pub(crate) key: Arc<WalletCapability>,
pub transaction_metadata_set: Arc<RwLock<TransactionMetadataSet>>,
}
Expand Down
40 changes: 32 additions & 8 deletions zingolib/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use orchard::tree::MerkleHashOrchard;
use orchard::Anchor;
use rand::rngs::OsRng;
use rand::Rng;
use shardtree::error::{QueryError, ShardTreeError};
use shardtree::store::memory::MemoryShardStore;
use shardtree::ShardTree;
use std::convert::Infallible;
Expand Down Expand Up @@ -479,11 +480,10 @@ impl LightWallet {
COMMITMENT_TREE_LEVELS,
MAX_SHARD_LEVEL,
>,
) -> Result<Anchor, String> {
Ok(orchard::Anchor::from(
tree.root_at_checkpoint(self.transaction_context.config.reorg_buffer_offset as usize)
.map_err(|e| format!("failed to get orchard anchor: {e}"))?,
))
) -> Result<Anchor, ShardTreeError<Infallible>> {
Ok(orchard::Anchor::from(tree.root_at_checkpoint(
self.transaction_context.config.reorg_buffer_offset as usize,
)?))
}

// Get the current sending status.
Expand Down Expand Up @@ -1031,7 +1031,7 @@ impl LightWallet {
&self,
submission_height: BlockHeight,
witness_trees: &WitnessTrees,
) -> Result<TxBuilder, String> {
) -> Result<TxBuilder, ShardTreeError<Infallible>> {
let orchard_anchor = self
.get_orchard_anchor(&witness_trees.witness_tree_orchard)
.await?;
Expand Down Expand Up @@ -1272,10 +1272,34 @@ impl LightWallet {
receivers.len()
);
loop {
tx_builder = self
tx_builder = match self
.create_tx_builder(submission_height, witness_trees)
.await
.expect("To populate a builder with notes.");
{
Err(ShardTreeError::Query(QueryError::NotContained(addr))) => Err(format!(
"could not create anchor, missing address {addr:?}. \
If you are fully synced, you may need to rescan to proceed"
)),
Err(ShardTreeError::Query(QueryError::CheckpointPruned)) => {
let blocks = self.blocks.read().await.len();
let offset = self.transaction_context.config.reorg_buffer_offset;
Err(format!(
"The reorg buffer offset has been set to {} \
but there are only {} blocks in the wallet. \
Please sync at least {} more blocks before trying again",
offset,
blocks,
offset + 1 - blocks as u32
))
}
Err(ShardTreeError::Query(QueryError::TreeIncomplete(addrs))) => Err(format!(
"could not create anchor, missing addresses {addrs:?}. \
If you are fully synced, you may need to rescan to proceed"
)),
Err(ShardTreeError::Insert(_)) => unreachable!(),
Err(ShardTreeError::Storage(_infallible)) => unreachable!(),
Ok(v) => Ok(v),
}?;

// Select notes to cover the target value
info!("{}: Adding outputs", now() - start_time);
Expand Down