This commit is contained in:
Daniela Brozzoni 2023-03-02 11:12:13 +01:00
parent b5559767db
commit 303a1703c9
No known key found for this signature in database
GPG Key ID: 7DE4F1FDCED0AB87
5 changed files with 140 additions and 41 deletions

View File

@ -24,8 +24,14 @@
//! /* Updating an empty sparsechain will always succeed */ //! /* Updating an empty sparsechain will always succeed */
//! //!
//! let update = SparseChain::from_checkpoints(vec![ //! let update = SparseChain::from_checkpoints(vec![
//! BlockId { height: 1, hash: hash_a }, //! BlockId {
//! BlockId { height: 2, hash: hash_b }, //! height: 1,
//! hash: hash_a,
//! },
//! BlockId {
//! height: 2,
//! hash: hash_b,
//! },
//! ]); //! ]);
//! let _ = chain //! let _ = chain
//! .apply_update(update) //! .apply_update(update)
@ -34,8 +40,14 @@
//! /* To update a non-empty sparsechain, the update must connect */ //! /* To update a non-empty sparsechain, the update must connect */
//! //!
//! let update = SparseChain::from_checkpoints(vec![ //! let update = SparseChain::from_checkpoints(vec![
//! BlockId { height: 2, hash: hash_b }, //! BlockId {
//! BlockId { height: 3, hash: hash_c }, //! height: 2,
//! hash: hash_b,
//! },
//! BlockId {
//! height: 3,
//! hash: hash_c,
//! },
//! ]); //! ]);
//! let _ = chain //! let _ = chain
//! .apply_update(update) //! .apply_update(update)
@ -56,17 +68,29 @@
//! # let hash_d = new_hash::<BlockHash>("d"); //! # let hash_d = new_hash::<BlockHash>("d");
//! // our sparsechain has 2 checkpoints //! // our sparsechain has 2 checkpoints
//! let chain = SparseChain::<TxHeight>::from_checkpoints(vec![ //! let chain = SparseChain::<TxHeight>::from_checkpoints(vec![
//! BlockId { height: 1, hash: hash_a }, //! BlockId {
//! BlockId { height: 2, hash: hash_b }, //! height: 1,
//! hash: hash_a,
//! },
//! BlockId {
//! height: 2,
//! hash: hash_b,
//! },
//! ]); //! ]);
//! //!
//! /* Example of an ambiguous update that does not fully connect */ //! /* Example of an ambiguous update that does not fully connect */
//! //!
//! let ambiguous_update = SparseChain::from_checkpoints(vec![ //! let ambiguous_update = SparseChain::from_checkpoints(vec![
//! // the update sort of "connects" at checkpoint 1, but... //! // the update sort of "connects" at checkpoint 1, but...
//! BlockId { height: 1, hash: hash_a }, //! BlockId {
//! height: 1,
//! hash: hash_a,
//! },
//! // we cannot determine whether checkpoint 3 connects with checkpoint 2 //! // we cannot determine whether checkpoint 3 connects with checkpoint 2
//! BlockId { height: 3, hash: hash_c }, //! BlockId {
//! height: 3,
//! hash: hash_c,
//! },
//! ]); //! ]);
//! let _ = chain //! let _ = chain
//! .determine_changeset(&ambiguous_update) //! .determine_changeset(&ambiguous_update)
@ -76,8 +100,14 @@
//! //!
//! let disconnected_update = SparseChain::from_checkpoints(vec![ //! let disconnected_update = SparseChain::from_checkpoints(vec![
//! // the last checkpoint in chain is 2, so 3 and 4 do not connect //! // the last checkpoint in chain is 2, so 3 and 4 do not connect
//! BlockId { height: 3, hash: hash_c }, //! BlockId {
//! BlockId { height: 4, hash: hash_d }, //! height: 3,
//! hash: hash_c,
//! },
//! BlockId {
//! height: 4,
//! hash: hash_d,
//! },
//! ]); //! ]);
//! let _ = chain //! let _ = chain
//! .determine_changeset(&disconnected_update) //! .determine_changeset(&disconnected_update)
@ -97,14 +127,21 @@
//! # let hash_c = new_hash::<BlockHash>("c"); //! # let hash_c = new_hash::<BlockHash>("c");
//! # let hash_d = new_hash::<BlockHash>("d"); //! # let hash_d = new_hash::<BlockHash>("d");
//! // our chain has a single checkpoint at height 11 //! // our chain has a single checkpoint at height 11
//! let mut chain = SparseChain::<TxHeight>::from_checkpoints(vec![ //! let mut chain = SparseChain::<TxHeight>::from_checkpoints(vec![BlockId {
//! BlockId { height: 11, hash: hash_a }, //! height: 11,
//! ]); //! hash: hash_a,
//! }]);
//! //!
//! // we detect a reorg at height 11, and we introduce a new checkpoint at height 12 //! // we detect a reorg at height 11, and we introduce a new checkpoint at height 12
//! let update = SparseChain::from_checkpoints(vec![ //! let update = SparseChain::from_checkpoints(vec![
//! BlockId { height: 11, hash: hash_b }, //! BlockId {
//! BlockId { height: 12, hash: hash_c }, //! height: 11,
//! hash: hash_b,
//! },
//! BlockId {
//! height: 12,
//! hash: hash_c,
//! },
//! ]); //! ]);
//! let _ = chain //! let _ = chain
//! .apply_update(update) //! .apply_update(update)
@ -114,8 +151,14 @@
//! // we detect another reorg, this time at height 12... //! // we detect another reorg, this time at height 12...
//! let update = SparseChain::from_checkpoints(vec![ //! let update = SparseChain::from_checkpoints(vec![
//! // we connect at checkpoint 11 as this is our "point of agreement" //! // we connect at checkpoint 11 as this is our "point of agreement"
//! BlockId { height: 11, hash: hash_b }, //! BlockId {
//! BlockId { height: 12, hash: hash_d }, //! height: 11,
//! hash: hash_b,
//! },
//! BlockId {
//! height: 12,
//! hash: hash_d,
//! },
//! ]); //! ]);
//! let _ = chain //! let _ = chain
//! .apply_update(update) //! .apply_update(update)
@ -166,48 +209,102 @@
//! } //! }
//! //!
//! impl Default for TxPosition { //! impl Default for TxPosition {
//! fn default() -> Self { Self::Unconfirmed } //! fn default() -> Self {
//! Self::Unconfirmed
//! }
//! } //! }
//! //!
//! impl ChainPosition for TxPosition { //! impl ChainPosition for TxPosition {
//! fn height(&self) -> TxHeight { //! fn height(&self) -> TxHeight {
//! match self { //! match self {
//! Self::Confirmed{ height, .. } => TxHeight::Confirmed(*height), //! Self::Confirmed { height, .. } => TxHeight::Confirmed(*height),
//! Self::Unconfirmed => TxHeight::Unconfirmed, //! Self::Unconfirmed => TxHeight::Unconfirmed,
//! } //! }
//! } //! }
//! //!
//! fn max_ord_of_height(height: TxHeight) -> Self { //! fn max_ord_of_height(height: TxHeight) -> Self {
//! match height { //! match height {
//! TxHeight::Confirmed(height) => Self::Confirmed{ height, position: u32::MAX }, //! TxHeight::Confirmed(height) => Self::Confirmed {
//! height,
//! position: u32::MAX,
//! },
//! TxHeight::Unconfirmed => Self::Unconfirmed, //! TxHeight::Unconfirmed => Self::Unconfirmed,
//! } //! }
//! } //! }
//! //!
//! fn min_ord_of_height(height: TxHeight) -> Self { //! fn min_ord_of_height(height: TxHeight) -> Self {
//! match height { //! match height {
//! TxHeight::Confirmed(height) => Self::Confirmed{ height, position: u32::MIN }, //! TxHeight::Confirmed(height) => Self::Confirmed {
//! height,
//! position: u32::MIN,
//! },
//! TxHeight::Unconfirmed => Self::Unconfirmed, //! TxHeight::Unconfirmed => Self::Unconfirmed,
//! } //! }
//! } //! }
//! } //! }
//! //!
//! let mut chain = SparseChain::<TxPosition>::default(); //! let mut chain = SparseChain::<TxPosition>::default();
//! let _ = chain.insert_checkpoint(BlockId { height: 10, hash: hash_a }).unwrap(); //! let _ = chain
//! let _ = chain.insert_tx(txid_1, TxPosition::Confirmed{ height: 9, position: 4321 }).unwrap(); //! .insert_checkpoint(BlockId {
//! let _ = chain.insert_tx(txid_2, TxPosition::Confirmed{ height: 9, position: 1234 }).unwrap(); //! height: 10,
//! let _ = chain.insert_tx(txid_3, TxPosition::Confirmed{ height: 10, position: 321 }).unwrap(); //! hash: hash_a,
//! })
//! .unwrap();
//! let _ = chain
//! .insert_tx(
//! txid_1,
//! TxPosition::Confirmed {
//! height: 9,
//! position: 4321,
//! },
//! )
//! .unwrap();
//! let _ = chain
//! .insert_tx(
//! txid_2,
//! TxPosition::Confirmed {
//! height: 9,
//! position: 1234,
//! },
//! )
//! .unwrap();
//! let _ = chain
//! .insert_tx(
//! txid_3,
//! TxPosition::Confirmed {
//! height: 10,
//! position: 321,
//! },
//! )
//! .unwrap();
//! //!
//! // transactions are ordered correctly //! // transactions are ordered correctly
//! assert_eq!( //! assert_eq!(
//! chain.txids().collect::<Vec<_>>(), //! chain.txids().collect::<Vec<_>>(),
//! vec![ //! vec![
//! &(TxPosition::Confirmed{ height: 9, position: 1234 }, txid_2), //! &(
//! &(TxPosition::Confirmed{ height: 9, position: 4321 }, txid_1), //! TxPosition::Confirmed {
//! &(TxPosition::Confirmed{ height: 10, position: 321 }, txid_3), //! height: 9,
//! position: 1234
//! },
//! txid_2
//! ),
//! &(
//! TxPosition::Confirmed {
//! height: 9,
//! position: 4321
//! },
//! txid_1
//! ),
//! &(
//! TxPosition::Confirmed {
//! height: 10,
//! position: 321
//! },
//! txid_3
//! ),
//! ], //! ],
//! ); //! );
//!
//! ``` //! ```
use core::{ use core::{
fmt::Debug, fmt::Debug,
@ -853,7 +950,7 @@ impl<P: ChainPosition> SparseChain<P> {
.iter() .iter()
.filter(|(&txid, pos)| { .filter(|(&txid, pos)| {
pos.is_some() /*it was not a deletion*/ && pos.is_some() /*it was not a deletion*/ &&
self.tx_position(txid).is_none() /*we don't have the txid already*/ self.tx_position(txid).is_none() /* we don't have the txid already */
}) })
.map(|(&txid, _)| txid) .map(|(&txid, _)| txid)
} }

View File

@ -195,11 +195,11 @@ impl<I: Clone + Ord> SpkTxOutIndex<I> {
/// # use bdk_chain::SpkTxOutIndex; /// # use bdk_chain::SpkTxOutIndex;
/// ///
/// // imagine our spks are indexed like (keychain, derivation_index). /// // imagine our spks are indexed like (keychain, derivation_index).
/// let txout_index = SpkTxOutIndex::<(u32,u32)>::default(); /// let txout_index = SpkTxOutIndex::<(u32, u32)>::default();
/// let all_unused_spks = txout_index.unused_spks(..); /// let all_unused_spks = txout_index.unused_spks(..);
/// let change_index = 1; /// let change_index = 1;
/// let unused_change_spks = txout_index /// let unused_change_spks =
/// .unused_spks((change_index, u32::MIN)..(change_index, u32::MAX)); /// txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
/// ``` /// ```
pub fn unused_spks<R>(&self, range: R) -> impl DoubleEndedIterator<Item = (&I, &Script)> pub fn unused_spks<R>(&self, range: R) -> impl DoubleEndedIterator<Item = (&I, &Script)>
where where

View File

@ -52,7 +52,6 @@
//! let additions = graph.apply_update(update); //! let additions = graph.apply_update(update);
//! assert!(additions.is_empty()); //! assert!(additions.is_empty());
//! ``` //! ```
//!
use crate::{collections::*, AsTransaction, ForEachTxOut, IntoOwned}; use crate::{collections::*, AsTransaction, ForEachTxOut, IntoOwned};
use alloc::vec::Vec; use alloc::vec::Vec;
use bitcoin::{OutPoint, Transaction, TxOut, Txid}; use bitcoin::{OutPoint, Transaction, TxOut, Txid};

View File

@ -5,11 +5,11 @@ use bdk_chain::{
}; };
use bdk_file_store::{FileError, IterError, KeychainStore, MAGIC_BYTES, MAGIC_BYTES_LEN}; use bdk_file_store::{FileError, IterError, KeychainStore, MAGIC_BYTES, MAGIC_BYTES_LEN};
use serde; use serde;
use tempfile::NamedTempFile;
use std::{ use std::{
io::{Read, Write}, io::{Read, Write},
vec::Vec, vec::Vec,
}; };
use tempfile::NamedTempFile;
#[derive( #[derive(
Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)] )]
@ -49,8 +49,7 @@ fn new_fails_if_magic_bytes_are_invalid() {
let invalid_magic_bytes = "ldkfs0000000"; let invalid_magic_bytes = "ldkfs0000000";
let mut file = NamedTempFile::new().unwrap(); let mut file = NamedTempFile::new().unwrap();
file file.write_all(invalid_magic_bytes.as_bytes())
.write_all(invalid_magic_bytes.as_bytes())
.expect("should write"); .expect("should write");
match KeychainStore::<TestKeychain, TxHeight, Transaction>::new(file.reopen().unwrap()) { match KeychainStore::<TestKeychain, TxHeight, Transaction>::new(file.reopen().unwrap()) {
@ -83,8 +82,9 @@ fn append_changeset_truncates_invalid_bytes() {
let mut file = NamedTempFile::new().unwrap(); let mut file = NamedTempFile::new().unwrap();
file.write_all(&data).expect("should write"); file.write_all(&data).expect("should write");
let mut store = KeychainStore::<TestKeychain, TxHeight, Transaction>::new(file.reopen().unwrap()) let mut store =
.expect("should open"); KeychainStore::<TestKeychain, TxHeight, Transaction>::new(file.reopen().unwrap())
.expect("should open");
match store.iter_changesets().expect("seek should succeed").next() { match store.iter_changesets().expect("seek should succeed").next() {
Some(Err(IterError::Bincode(_))) => {} Some(Err(IterError::Bincode(_))) => {}
unexpected_res => panic!("unexpected result: {:?}", unexpected_res), unexpected_res => panic!("unexpected result: {:?}", unexpected_res),
@ -96,7 +96,10 @@ fn append_changeset_truncates_invalid_bytes() {
let got_bytes = { let got_bytes = {
let mut buf = Vec::new(); let mut buf = Vec::new();
file.reopen().unwrap().read_to_end(&mut buf).expect("should read"); file.reopen()
.unwrap()
.read_to_end(&mut buf)
.expect("should read");
buf buf
}; };

View File

@ -35,7 +35,7 @@ pub struct PlanKey<Ak> {
impl<Ak> TemplateItem<Ak> { impl<Ak> TemplateItem<Ak> {
pub fn expected_size(&self) -> usize { pub fn expected_size(&self) -> usize {
match self { match self {
TemplateItem::Sign { .. } => 64, /*size of sig TODO: take into consideration sighash falg*/ TemplateItem::Sign { .. } => 64, /* size of sig TODO: take into consideration sighash falg */
TemplateItem::Pk { .. } => 32, TemplateItem::Pk { .. } => 32,
TemplateItem::One => varint_len(1), TemplateItem::One => varint_len(1),
TemplateItem::Zero => 0, /* zero means an empty witness element */ TemplateItem::Zero => 0, /* zero means an empty witness element */