descriptors: rename MultipathDescriptor into LianaDescriptor
This commit is contained in:
parent
f6885e358b
commit
8d1c6de5dd
@ -5,7 +5,7 @@ mod utils;
|
||||
use crate::{
|
||||
bitcoin::{Block, BlockChainTip},
|
||||
config,
|
||||
descriptors::MultipathDescriptor,
|
||||
descriptors::LianaDescriptor,
|
||||
};
|
||||
use utils::{block_before_date, roundup_progress};
|
||||
|
||||
@ -485,7 +485,7 @@ impl BitcoinD {
|
||||
}
|
||||
|
||||
// Import the receive and change descriptors from the multipath descriptor to bitcoind.
|
||||
fn import_descriptor(&self, desc: &MultipathDescriptor) -> Option<String> {
|
||||
fn import_descriptor(&self, desc: &LianaDescriptor) -> Option<String> {
|
||||
let descriptors = [desc.receive_descriptor(), desc.change_descriptor()]
|
||||
.iter()
|
||||
.map(|desc| {
|
||||
@ -553,7 +553,7 @@ impl BitcoinD {
|
||||
/// Create the watchonly wallet on bitcoind, and import it the main descriptor.
|
||||
pub fn create_watchonly_wallet(
|
||||
&self,
|
||||
main_descriptor: &MultipathDescriptor,
|
||||
main_descriptor: &LianaDescriptor,
|
||||
) -> Result<(), BitcoindError> {
|
||||
// Remove any leftover. This can happen if we delete the watchonly wallet but don't restart
|
||||
// bitcoind.
|
||||
@ -627,7 +627,7 @@ impl BitcoinD {
|
||||
/// Perform various sanity checks of our watchonly wallet.
|
||||
pub fn wallet_sanity_checks(
|
||||
&self,
|
||||
main_descriptor: &MultipathDescriptor,
|
||||
main_descriptor: &LianaDescriptor,
|
||||
) -> Result<(), BitcoindError> {
|
||||
// Check our watchonly wallet is loaded
|
||||
if self
|
||||
@ -919,7 +919,7 @@ impl BitcoinD {
|
||||
|
||||
pub fn start_rescan(
|
||||
&self,
|
||||
desc: &MultipathDescriptor,
|
||||
desc: &LianaDescriptor,
|
||||
timestamp: u32,
|
||||
) -> Result<(), BitcoindError> {
|
||||
// Re-import the receive and change descriptors to the watchonly wallet for the purpose of
|
||||
|
||||
@ -87,7 +87,7 @@ pub trait BitcoinInterface: Send {
|
||||
/// the given date.
|
||||
fn start_rescan(
|
||||
&self,
|
||||
desc: &descriptors::MultipathDescriptor,
|
||||
desc: &descriptors::LianaDescriptor,
|
||||
timestamp: u32,
|
||||
) -> Result<(), String>;
|
||||
|
||||
@ -288,7 +288,7 @@ impl BitcoinInterface for d::BitcoinD {
|
||||
|
||||
fn start_rescan(
|
||||
&self,
|
||||
desc: &descriptors::MultipathDescriptor,
|
||||
desc: &descriptors::LianaDescriptor,
|
||||
timestamp: u32,
|
||||
) -> Result<(), String> {
|
||||
// FIXME: in theory i think this could potentially fail to actually start the rescan.
|
||||
@ -374,7 +374,7 @@ impl BitcoinInterface for sync::Arc<sync::Mutex<dyn BitcoinInterface + 'static>>
|
||||
|
||||
fn start_rescan(
|
||||
&self,
|
||||
desc: &descriptors::MultipathDescriptor,
|
||||
desc: &descriptors::LianaDescriptor,
|
||||
timestamp: u32,
|
||||
) -> Result<(), String> {
|
||||
self.lock().unwrap().start_rescan(desc, timestamp)
|
||||
|
||||
@ -300,7 +300,7 @@ pub fn looper(
|
||||
db: sync::Arc<sync::Mutex<dyn DatabaseInterface>>,
|
||||
shutdown: sync::Arc<atomic::AtomicBool>,
|
||||
poll_interval: time::Duration,
|
||||
desc: descriptors::MultipathDescriptor,
|
||||
desc: descriptors::LianaDescriptor,
|
||||
) {
|
||||
let mut last_poll = None;
|
||||
let mut synced = false;
|
||||
|
||||
@ -22,7 +22,7 @@ impl Poller {
|
||||
bit: sync::Arc<sync::Mutex<dyn BitcoinInterface>>,
|
||||
db: sync::Arc<sync::Mutex<dyn DatabaseInterface>>,
|
||||
poll_interval: time::Duration,
|
||||
desc: descriptors::MultipathDescriptor,
|
||||
desc: descriptors::LianaDescriptor,
|
||||
) -> Poller {
|
||||
let shutdown = sync::Arc::from(atomic::AtomicBool::from(false));
|
||||
let handle = thread::Builder::new()
|
||||
|
||||
@ -155,7 +155,7 @@ pub enum InsaneFeeInfo {
|
||||
// Apply some sanity checks on a created transaction's PSBT.
|
||||
// TODO: add more sanity checks from revault_tx
|
||||
fn sanity_check_psbt(
|
||||
spent_desc: &descriptors::MultipathDescriptor,
|
||||
spent_desc: &descriptors::LianaDescriptor,
|
||||
psbt: &Psbt,
|
||||
) -> Result<(), CommandError> {
|
||||
let tx = &psbt.unsigned_tx;
|
||||
@ -783,7 +783,7 @@ impl DaemonControl {
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GetInfoDescriptors {
|
||||
pub main: descriptors::MultipathDescriptor,
|
||||
pub main: descriptors::LianaDescriptor,
|
||||
}
|
||||
|
||||
/// Information about the daemon
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::descriptors::MultipathDescriptor;
|
||||
use crate::descriptors::LianaDescriptor;
|
||||
|
||||
use std::{net::SocketAddr, path::PathBuf, str::FromStr, time::Duration};
|
||||
|
||||
@ -91,7 +91,7 @@ pub struct Config {
|
||||
deserialize_with = "deserialize_fromstr",
|
||||
serialize_with = "serialize_to_string"
|
||||
)]
|
||||
pub main_descriptor: MultipathDescriptor,
|
||||
pub main_descriptor: LianaDescriptor,
|
||||
/// Settings for the Bitcoin interface
|
||||
pub bitcoin_config: BitcoinConfig,
|
||||
/// Settings specific to bitcoind as the Bitcoin interface
|
||||
@ -112,7 +112,7 @@ pub enum ConfigError {
|
||||
DatadirNotFound,
|
||||
FileNotFound,
|
||||
ReadingFile(String),
|
||||
UnexpectedDescriptor(Box<MultipathDescriptor>),
|
||||
UnexpectedDescriptor(Box<LianaDescriptor>),
|
||||
Unexpected(String),
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ use crate::{
|
||||
},
|
||||
Coin, CoinType,
|
||||
},
|
||||
descriptors::MultipathDescriptor,
|
||||
descriptors::LianaDescriptor,
|
||||
};
|
||||
|
||||
use std::{cmp, convert::TryInto, fmt, io, path};
|
||||
@ -39,7 +39,7 @@ pub enum SqliteDbError {
|
||||
FileNotFound(path::PathBuf),
|
||||
UnsupportedVersion(i64),
|
||||
InvalidNetwork(bitcoin::Network),
|
||||
DescriptorMismatch(Box<MultipathDescriptor>),
|
||||
DescriptorMismatch(Box<LianaDescriptor>),
|
||||
Rusqlite(rusqlite::Error),
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ impl From<rusqlite::Error> for SqliteDbError {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FreshDbOptions {
|
||||
pub bitcoind_network: bitcoin::Network,
|
||||
pub main_descriptor: MultipathDescriptor,
|
||||
pub main_descriptor: LianaDescriptor,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -122,7 +122,7 @@ impl SqliteDb {
|
||||
pub fn sanity_check(
|
||||
&self,
|
||||
bitcoind_network: bitcoin::Network,
|
||||
main_descriptor: &MultipathDescriptor,
|
||||
main_descriptor: &LianaDescriptor,
|
||||
) -> Result<(), SqliteDbError> {
|
||||
let mut conn = self.connection()?;
|
||||
|
||||
@ -597,7 +597,7 @@ mod tests {
|
||||
|
||||
fn dummy_options() -> FreshDbOptions {
|
||||
let desc_str = "wsh(andor(pk([aabbccdd]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(10000),pk([aabbccdd]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))#dw4ulnrs";
|
||||
let main_descriptor = MultipathDescriptor::from_str(desc_str).unwrap();
|
||||
let main_descriptor = LianaDescriptor::from_str(desc_str).unwrap();
|
||||
FreshDbOptions {
|
||||
bitcoind_network: bitcoin::Network::Bitcoin,
|
||||
main_descriptor,
|
||||
@ -646,7 +646,7 @@ mod tests {
|
||||
.contains("Database was created for network");
|
||||
fs::remove_file(&db_path).unwrap();
|
||||
let other_desc_str = "wsh(andor(pk([aabbccdd]tpubDExU4YLJkyQ9RRbVScQq2brFxWWha7WmAUByPWyaWYwmcTv3Shx8aHp6mVwuE5n4TeM4z5DTWGf2YhNPmXtfvyr8cUDVvA3txdrFnFgNdF7/<0;1>/*),older(10000),pk([aabbccdd]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))";
|
||||
let other_desc = MultipathDescriptor::from_str(other_desc_str).unwrap();
|
||||
let other_desc = LianaDescriptor::from_str(other_desc_str).unwrap();
|
||||
let db = SqliteDb::new(db_path.clone(), Some(options.clone()), &secp).unwrap();
|
||||
db.sanity_check(bitcoin::Network::Bitcoin, &other_desc)
|
||||
.unwrap_err()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::descriptors::MultipathDescriptor;
|
||||
use crate::descriptors::LianaDescriptor;
|
||||
|
||||
use std::{convert::TryFrom, str::FromStr};
|
||||
|
||||
@ -112,7 +112,7 @@ impl TryFrom<&rusqlite::Row<'_>> for DbTip {
|
||||
pub struct DbWallet {
|
||||
pub id: i64,
|
||||
pub timestamp: u32,
|
||||
pub main_descriptor: MultipathDescriptor,
|
||||
pub main_descriptor: LianaDescriptor,
|
||||
pub deposit_derivation_index: bip32::ChildNumber,
|
||||
pub change_derivation_index: bip32::ChildNumber,
|
||||
pub rescan_timestamp: Option<u32>,
|
||||
@ -126,7 +126,7 @@ impl TryFrom<&rusqlite::Row<'_>> for DbWallet {
|
||||
let timestamp = row.get(1)?;
|
||||
|
||||
let desc_str: String = row.get(2)?;
|
||||
let main_descriptor = MultipathDescriptor::from_str(&desc_str)
|
||||
let main_descriptor = LianaDescriptor::from_str(&desc_str)
|
||||
.expect("Insane database: can't parse deposit descriptor");
|
||||
|
||||
let der_idx: u32 = row.get(3)?;
|
||||
|
||||
@ -62,7 +62,7 @@ impl From<LianaPolicyError> for LianaDescError {
|
||||
/// An [InheritanceDescriptor] that contains multipath keys for (and only for) the receive keychain
|
||||
/// and the change keychain.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct MultipathDescriptor {
|
||||
pub struct LianaDescriptor {
|
||||
multi_desc: descriptor::Descriptor<descriptor::DescriptorPublicKey>,
|
||||
receive_desc: InheritanceDescriptor,
|
||||
change_desc: InheritanceDescriptor,
|
||||
@ -77,16 +77,16 @@ pub struct InheritanceDescriptor(descriptor::Descriptor<descriptor::DescriptorPu
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct DerivedInheritanceDescriptor(descriptor::Descriptor<DerivedPublicKey>);
|
||||
|
||||
impl fmt::Display for MultipathDescriptor {
|
||||
impl fmt::Display for LianaDescriptor {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.multi_desc)
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for MultipathDescriptor {
|
||||
impl str::FromStr for LianaDescriptor {
|
||||
type Err = LianaDescError;
|
||||
|
||||
fn from_str(s: &str) -> Result<MultipathDescriptor, Self::Err> {
|
||||
fn from_str(s: &str) -> Result<LianaDescriptor, Self::Err> {
|
||||
// Parse a descriptor and check it is a multipath descriptor corresponding to a valid Liana
|
||||
// spending policy.
|
||||
let desc = descriptor::Descriptor::<descriptor::DescriptorPublicKey>::from_str(s)
|
||||
@ -106,7 +106,7 @@ impl str::FromStr for MultipathDescriptor {
|
||||
let receive_desc = InheritanceDescriptor(singlepath_descs.next().expect("First of 2"));
|
||||
let change_desc = InheritanceDescriptor(singlepath_descs.next().expect("Second of 2"));
|
||||
|
||||
Ok(MultipathDescriptor {
|
||||
Ok(LianaDescriptor {
|
||||
multi_desc: desc,
|
||||
receive_desc,
|
||||
change_desc,
|
||||
@ -126,8 +126,8 @@ impl PartialEq<descriptor::Descriptor<descriptor::DescriptorPublicKey>> for Inhe
|
||||
}
|
||||
}
|
||||
|
||||
impl MultipathDescriptor {
|
||||
pub fn new(spending_policy: LianaPolicy) -> MultipathDescriptor {
|
||||
impl LianaDescriptor {
|
||||
pub fn new(spending_policy: LianaPolicy) -> LianaDescriptor {
|
||||
// Get the descriptor from the chosen spending policy.
|
||||
let multi_desc = spending_policy.into_multipath_descriptor();
|
||||
|
||||
@ -144,7 +144,7 @@ impl MultipathDescriptor {
|
||||
let receive_desc = InheritanceDescriptor(singlepath_descs.next().expect("First of 2"));
|
||||
let change_desc = InheritanceDescriptor(singlepath_descs.next().expect("Second of 2"));
|
||||
|
||||
MultipathDescriptor {
|
||||
LianaDescriptor {
|
||||
multi_desc,
|
||||
receive_desc,
|
||||
change_desc,
|
||||
@ -400,7 +400,7 @@ mod tests {
|
||||
let heir_key = PathInfo::Single(descriptor::DescriptorPublicKey::from_str("[abcdef01]xpub688Hn4wScQAAiYJLPg9yH27hUpfZAUnmJejRQBCiwfP5PEDzjWMNW1wChcninxr5gyavFqbbDjdV1aK5USJz8NDVjUy7FRQaaqqXHh5SbXe/<0;1>/*").unwrap());
|
||||
let timelock = 52560;
|
||||
let policy = LianaPolicy::new(owner_key.clone(), heir_key.clone(), timelock).unwrap();
|
||||
assert_eq!(MultipathDescriptor::new(policy).to_string(), "wsh(or_d(pk([abcdef01]xpub6Eze7yAT3Y1wGrnzedCNVYDXUqa9NmHVWck5emBaTbXtURbe1NWZbK9bsz1TiVE7Cz341PMTfYgFw1KdLWdzcM1UMFTcdQfCYhhXZ2HJvTW/<0;1>/*),and_v(v:pkh([abcdef01]xpub688Hn4wScQAAiYJLPg9yH27hUpfZAUnmJejRQBCiwfP5PEDzjWMNW1wChcninxr5gyavFqbbDjdV1aK5USJz8NDVjUy7FRQaaqqXHh5SbXe/<0;1>/*),older(52560))))#g7vk9r5l");
|
||||
assert_eq!(LianaDescriptor::new(policy).to_string(), "wsh(or_d(pk([abcdef01]xpub6Eze7yAT3Y1wGrnzedCNVYDXUqa9NmHVWck5emBaTbXtURbe1NWZbK9bsz1TiVE7Cz341PMTfYgFw1KdLWdzcM1UMFTcdQfCYhhXZ2HJvTW/<0;1>/*),and_v(v:pkh([abcdef01]xpub688Hn4wScQAAiYJLPg9yH27hUpfZAUnmJejRQBCiwfP5PEDzjWMNW1wChcninxr5gyavFqbbDjdV1aK5USJz8NDVjUy7FRQaaqqXHh5SbXe/<0;1>/*),older(52560))))#g7vk9r5l");
|
||||
|
||||
// A decaying multisig after 6 months. Note we can't duplicate the keys, so different ones
|
||||
// are used. In practice they would both be controlled by the same entity.
|
||||
@ -421,7 +421,7 @@ mod tests {
|
||||
],
|
||||
);
|
||||
let policy = LianaPolicy::new(primary_keys, recovery_keys, 26352).unwrap();
|
||||
assert_eq!(MultipathDescriptor::new(policy).to_string(), "wsh(or_d(multi(3,[abcdef01]xpub6Eze7yAT3Y1wGrnzedCNVYDXUqa9NmHVWck5emBaTbXtURbe1NWZbK9bsz1TiVE7Cz341PMTfYgFw1KdLWdzcM1UMFTcdQfCYhhXZ2HJvTW/<0;1>/*,[aabb0011/10/4893]xpub6Bw79HbNSeS2xXw1sngPE3ehnk1U3iSPCgLYzC9LpN8m9nDuaKLZvkg8QXxL5pDmEmQtYscmUD8B9MkAAZbh6vxPzNXMaLfGQ9Sb3z85qhR/<0;1>/*,[abcdef01]xpub67zuTXF9Ln4731avKTBSawoVVNRuMfmRvkL7kLUaLBRqma9ZqdHBJg9qx8cPUm3oNQMiXT4TmGovXNoQPuwg17RFcVJ8YrnbcooN7pxVJqC/<0;1>/*),and_v(v:multi(2,[abcdef01]xpub69cP4Y7S9TWcbSNxmk6CEDBsoaqr3ZEdjHuZcHxEFFKGh569RsJNr2V27XGhsbH9FXgWUEmKXRN7c5wQfq2VPjt31xP9VsYnVUyU8HcVevm/<0;1>/*,[abcdef01]xpub6AA2N8RALRYgLD6jT1iXYCEDkndTeZndMtWPbtNX6sY5dPiLtf2T88ahdxrGXMUPoNadgR86sFhBXWQVgifPzDYbY9ZtwK4gqzx4y5Da1DW/<0;1>/*,[aabb0011/10/4893]xpub6AyxexvxizZJffF153evmfqHcE9MV88fCNCAtP3jQjXJHwrAKri71Tq9jWUkPxj9pja4u6AkCPHY7atgxzSEa2HtDwJfrRWKK4fsfQg4o77/<0;1>/*),older(26352))))#s0zsa6uc");
|
||||
assert_eq!(LianaDescriptor::new(policy).to_string(), "wsh(or_d(multi(3,[abcdef01]xpub6Eze7yAT3Y1wGrnzedCNVYDXUqa9NmHVWck5emBaTbXtURbe1NWZbK9bsz1TiVE7Cz341PMTfYgFw1KdLWdzcM1UMFTcdQfCYhhXZ2HJvTW/<0;1>/*,[aabb0011/10/4893]xpub6Bw79HbNSeS2xXw1sngPE3ehnk1U3iSPCgLYzC9LpN8m9nDuaKLZvkg8QXxL5pDmEmQtYscmUD8B9MkAAZbh6vxPzNXMaLfGQ9Sb3z85qhR/<0;1>/*,[abcdef01]xpub67zuTXF9Ln4731avKTBSawoVVNRuMfmRvkL7kLUaLBRqma9ZqdHBJg9qx8cPUm3oNQMiXT4TmGovXNoQPuwg17RFcVJ8YrnbcooN7pxVJqC/<0;1>/*),and_v(v:multi(2,[abcdef01]xpub69cP4Y7S9TWcbSNxmk6CEDBsoaqr3ZEdjHuZcHxEFFKGh569RsJNr2V27XGhsbH9FXgWUEmKXRN7c5wQfq2VPjt31xP9VsYnVUyU8HcVevm/<0;1>/*,[abcdef01]xpub6AA2N8RALRYgLD6jT1iXYCEDkndTeZndMtWPbtNX6sY5dPiLtf2T88ahdxrGXMUPoNadgR86sFhBXWQVgifPzDYbY9ZtwK4gqzx4y5Da1DW/<0;1>/*,[aabb0011/10/4893]xpub6AyxexvxizZJffF153evmfqHcE9MV88fCNCAtP3jQjXJHwrAKri71Tq9jWUkPxj9pja4u6AkCPHY7atgxzSEa2HtDwJfrRWKK4fsfQg4o77/<0;1>/*),older(26352))))#s0zsa6uc");
|
||||
|
||||
// We prevent footguns with timelocks by requiring a u16. Note how the following wouldn't
|
||||
// compile:
|
||||
@ -436,7 +436,7 @@ mod tests {
|
||||
let heir_key = PathInfo::Single(descriptor::DescriptorPublicKey::from_str("[abcdef01]xpub661MyMwAqRbcFfxf71L4Dx4w5TmyNXrBicTEAM7vLzumxangwATWWgdJPb6xH1JHcJH9S3jNZx3fCnkkB1WyqrqGgavj1rehHcbythmruvZ/24/32/<0;1>/*").unwrap());
|
||||
let timelock = 57600;
|
||||
let policy = LianaPolicy::new(owner_key.clone(), heir_key, timelock).unwrap();
|
||||
assert_eq!(MultipathDescriptor::new(policy).to_string(), "wsh(or_d(pk([aabb0011/10/4893]xpub661MyMwAqRbcFG59fiikD8UV762quhruT8K8bdjqy6N2o3LG7yohoCdLg1m2HAY1W6rfBrtauHkBhbfA4AQ3iazaJj5wVPhwgaRCHBW2DBg/<0;1>/*),and_v(v:pkh([abcdef01]xpub661MyMwAqRbcFfxf71L4Dx4w5TmyNXrBicTEAM7vLzumxangwATWWgdJPb6xH1JHcJH9S3jNZx3fCnkkB1WyqrqGgavj1rehHcbythmruvZ/24/32/<0;1>/*),older(57600))))#ak4cm093");
|
||||
assert_eq!(LianaDescriptor::new(policy).to_string(), "wsh(or_d(pk([aabb0011/10/4893]xpub661MyMwAqRbcFG59fiikD8UV762quhruT8K8bdjqy6N2o3LG7yohoCdLg1m2HAY1W6rfBrtauHkBhbfA4AQ3iazaJj5wVPhwgaRCHBW2DBg/<0;1>/*),and_v(v:pkh([abcdef01]xpub661MyMwAqRbcFfxf71L4Dx4w5TmyNXrBicTEAM7vLzumxangwATWWgdJPb6xH1JHcJH9S3jNZx3fCnkkB1WyqrqGgavj1rehHcbythmruvZ/24/32/<0;1>/*),older(57600))))#ak4cm093");
|
||||
|
||||
// We can't pass a raw key, an xpub that is not deriveable, only hardened derivable,
|
||||
// without both the change and receive derivation paths, or with more than 2 different
|
||||
@ -514,7 +514,7 @@ mod tests {
|
||||
#[test]
|
||||
fn inheritance_descriptor_derivation() {
|
||||
let secp = secp256k1::Secp256k1::verification_only();
|
||||
let desc = MultipathDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(10000),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))#2qj59a9y").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(10000),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))#2qj59a9y").unwrap();
|
||||
let der_desc = desc.receive_descriptor().derive(11.into(), &secp);
|
||||
assert_eq!(
|
||||
"bc1q26gtczlz03u6juf5cxppapk4sr4fyz53s3g4zs2cgactcahqv6yqc2t8e6",
|
||||
@ -530,21 +530,21 @@ mod tests {
|
||||
#[test]
|
||||
fn inheritance_descriptor_tl_value() {
|
||||
// Must always contain at least one timelocked path.
|
||||
MultipathDescriptor::from_str("wsh(or_i(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap_err();
|
||||
LianaDescriptor::from_str("wsh(or_i(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap_err();
|
||||
|
||||
let desc = MultipathDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(1),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(1),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap();
|
||||
assert_eq!(desc.timelock_value(), 1);
|
||||
|
||||
let desc = MultipathDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(42000),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(42000),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap();
|
||||
assert_eq!(desc.timelock_value(), 42000);
|
||||
|
||||
let desc = MultipathDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(65535),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(andor(pk([abcdef01]tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/<0;1>/*),older(65535),pk([abcdef01]tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/<0;1>/*)))").unwrap();
|
||||
assert_eq!(desc.timelock_value(), 0xffff);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inheritance_descriptor_sat_size() {
|
||||
let desc = MultipathDescriptor::from_str("wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/<0;1>/*),and_v(v:pkh([abcdef01]tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/<0;1>/*),older(2))))#ravw7jw5").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/<0;1>/*),and_v(v:pkh([abcdef01]tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/<0;1>/*),older(2))))#ravw7jw5").unwrap();
|
||||
assert_eq!(desc.max_sat_vbytes(), (1 + 69 + 1 + 34 + 73 + 3) / 4); // See the stack details below.
|
||||
|
||||
// Maximum input size is (txid + vout + scriptsig + nSequence + max_sat).
|
||||
@ -633,7 +633,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn roundtrip(desc_str: &str) {
|
||||
let desc = MultipathDescriptor::from_str(desc_str).unwrap();
|
||||
let desc = LianaDescriptor::from_str(desc_str).unwrap();
|
||||
assert_eq!(desc.to_string(), desc_str);
|
||||
}
|
||||
|
||||
@ -656,7 +656,7 @@ mod tests {
|
||||
#[test]
|
||||
fn partial_spend_info() {
|
||||
// A simple descriptor with 1 keys as primary path and 1 recovery key.
|
||||
let desc = MultipathDescriptor::from_str("wsh(or_d(pk([f5acc2fd]tpubD6NzVbkrYhZ4YgUx2ZLNt2rLYAMTdYysCRzKoLu2BeSHKvzqPaBDvf17GeBPnExUVPkuBpx4kniP964e2MxyzzazcXLptxLXModSVCVEV1T/<0;1>/*),and_v(v:pkh([8a64f2a9]tpubD6NzVbkrYhZ4WmzFjvQrp7sDa4ECUxTi9oby8K4FZkd3XCBtEdKwUiQyYJaxiJo5y42gyDWEczrFpozEjeLxMPxjf2WtkfcbpUdfvNnozWF/<0;1>/*),older(10))))#d72le4dr").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(or_d(pk([f5acc2fd]tpubD6NzVbkrYhZ4YgUx2ZLNt2rLYAMTdYysCRzKoLu2BeSHKvzqPaBDvf17GeBPnExUVPkuBpx4kniP964e2MxyzzazcXLptxLXModSVCVEV1T/<0;1>/*),and_v(v:pkh([8a64f2a9]tpubD6NzVbkrYhZ4WmzFjvQrp7sDa4ECUxTi9oby8K4FZkd3XCBtEdKwUiQyYJaxiJo5y42gyDWEczrFpozEjeLxMPxjf2WtkfcbpUdfvNnozWF/<0;1>/*),older(10))))#d72le4dr").unwrap();
|
||||
let desc_info = desc.policy();
|
||||
let prim_key_origin = (
|
||||
bip32::Fingerprint::from_str("f5acc2fd").unwrap(),
|
||||
@ -816,7 +816,7 @@ mod tests {
|
||||
.contains("Analyzed PSBT is inconsistent across inputs."));
|
||||
|
||||
// If we analyze a descriptor with a multisig we'll get the right threshold.
|
||||
let desc = MultipathDescriptor::from_str("wsh(or_d(multi(2,[f5acc2fd]tpubD6NzVbkrYhZ4YgUx2ZLNt2rLYAMTdYysCRzKoLu2BeSHKvzqPaBDvf17GeBPnExUVPkuBpx4kniP964e2MxyzzazcXLptxLXModSVCVEV1T/<0;1>/*,[00112233]xpub6FC8vmQGGfSuQGfKG5L73fZ7WjXit8TzfJYDKwTtHkhrbAhU5Kma41oenVq6aMnpgULJRXpQuxnVysyfdpRhVgD6vYe7XLbFDhmvYmDrAVq/<0;1>/*,[aabbccdd]xpub68XtbpvDM19d39wEKdvadHkZ4FGKf4tnryKzAacttp8BLX3uHj7eK8shRnFBhZ2UL83S9dwXe42Qm6eG6BkR1jy8XwUSNBcHKtET7j4V5FB/<0;1>/*),and_v(v:pkh([8a64f2a9]tpubD6NzVbkrYhZ4WmzFjvQrp7sDa4ECUxTi9oby8K4FZkd3XCBtEdKwUiQyYJaxiJo5y42gyDWEczrFpozEjeLxMPxjf2WtkfcbpUdfvNnozWF/<0;1>/*),older(10))))#2kgxuax5").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(or_d(multi(2,[f5acc2fd]tpubD6NzVbkrYhZ4YgUx2ZLNt2rLYAMTdYysCRzKoLu2BeSHKvzqPaBDvf17GeBPnExUVPkuBpx4kniP964e2MxyzzazcXLptxLXModSVCVEV1T/<0;1>/*,[00112233]xpub6FC8vmQGGfSuQGfKG5L73fZ7WjXit8TzfJYDKwTtHkhrbAhU5Kma41oenVq6aMnpgULJRXpQuxnVysyfdpRhVgD6vYe7XLbFDhmvYmDrAVq/<0;1>/*,[aabbccdd]xpub68XtbpvDM19d39wEKdvadHkZ4FGKf4tnryKzAacttp8BLX3uHj7eK8shRnFBhZ2UL83S9dwXe42Qm6eG6BkR1jy8XwUSNBcHKtET7j4V5FB/<0;1>/*),and_v(v:pkh([8a64f2a9]tpubD6NzVbkrYhZ4WmzFjvQrp7sDa4ECUxTi9oby8K4FZkd3XCBtEdKwUiQyYJaxiJo5y42gyDWEczrFpozEjeLxMPxjf2WtkfcbpUdfvNnozWF/<0;1>/*),older(10))))#2kgxuax5").unwrap();
|
||||
let info = desc.partial_spend_info(&psbt).unwrap();
|
||||
assert!(psbt
|
||||
.inputs
|
||||
@ -833,7 +833,7 @@ mod tests {
|
||||
);
|
||||
assert!(info.recovery_path.is_none());
|
||||
|
||||
let desc = MultipathDescriptor::from_str("wsh(or_d(multi(2,[636adf3f/48'/1'/0'/2']tpubDEE9FvWbG4kg4gxDNrALgrWLiHwNMXNs8hk6nXNPw4VHKot16xd2251vwi2M6nsyQTkak5FJNHVHkCcuzmvpSbWHdumX3DxpDm89iTfSBaL/<0;1>/*,[ffd63c8d/48'/1'/0'/2']tpubDExA3EC3iAsPxPhFn4j6gMiVup6V2eH3qKyk69RcTc9TTNRfFYVPad8bJD5FCHVQxyBT4izKsvr7Btd2R4xmQ1hZkvsqGBaeE82J71uTK4N/<0;1>/*),and_v(v:multi(2,[636adf3f/48'/1'/1'/2']tpubDDvF2khuoBBj8vcSjQfa7iKaxsQZE7YjJ7cJL8A8eaneadMPKbHSpoSr4JD1F5LUvWD82HCxdtSppGfrMUmiNbFxrA2EHEVLnrdCFNFe75D/<0;1>/*,[ffd63c8d/48'/1'/1'/2']tpubDFMs44FD4kFt3M7Z317cFh5tdKEGN8tyQRY6Q5gcSha4NtxZfGmTVRMbsD1bWN469LstXU4aVSARDxrvxFCUjHeegfEY2cLSazMBkNCmDPD/<0;1>/*),older(2))))#xcf6jr2r").unwrap();
|
||||
let desc = LianaDescriptor::from_str("wsh(or_d(multi(2,[636adf3f/48'/1'/0'/2']tpubDEE9FvWbG4kg4gxDNrALgrWLiHwNMXNs8hk6nXNPw4VHKot16xd2251vwi2M6nsyQTkak5FJNHVHkCcuzmvpSbWHdumX3DxpDm89iTfSBaL/<0;1>/*,[ffd63c8d/48'/1'/0'/2']tpubDExA3EC3iAsPxPhFn4j6gMiVup6V2eH3qKyk69RcTc9TTNRfFYVPad8bJD5FCHVQxyBT4izKsvr7Btd2R4xmQ1hZkvsqGBaeE82J71uTK4N/<0;1>/*),and_v(v:multi(2,[636adf3f/48'/1'/1'/2']tpubDDvF2khuoBBj8vcSjQfa7iKaxsQZE7YjJ7cJL8A8eaneadMPKbHSpoSr4JD1F5LUvWD82HCxdtSppGfrMUmiNbFxrA2EHEVLnrdCFNFe75D/<0;1>/*,[ffd63c8d/48'/1'/1'/2']tpubDFMs44FD4kFt3M7Z317cFh5tdKEGN8tyQRY6Q5gcSha4NtxZfGmTVRMbsD1bWN469LstXU4aVSARDxrvxFCUjHeegfEY2cLSazMBkNCmDPD/<0;1>/*),older(2))))#xcf6jr2r").unwrap();
|
||||
let info = desc.policy();
|
||||
assert_eq!(info.primary_path, PathInfo::Multi(
|
||||
2,
|
||||
|
||||
@ -464,7 +464,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
config::{BitcoinConfig, BitcoindConfig},
|
||||
descriptors::MultipathDescriptor,
|
||||
descriptors::LianaDescriptor,
|
||||
testutils::*,
|
||||
};
|
||||
|
||||
@ -686,7 +686,7 @@ mod tests {
|
||||
|
||||
// Create a dummy config with this bitcoind
|
||||
let desc_str = "wsh(andor(pk([aabbccdd]xpub68JJTXc1MWK8KLW4HGLXZBJknja7kDUJuFHnM424LbziEXsfkh1WQCiEjjHw4zLqSUm4rvhgyGkkuRowE9tCJSgt3TQB5J3SKAbZ2SdcKST/<0;1>/*),older(10000),pk([aabbccdd]xpub68JJTXc1MWK8PEQozKsRatrUHXKFNkD1Cb1BuQU9Xr5moCv87anqGyXLyUd4KpnDyZgo3gz4aN1r3NiaoweFW8UutBsBbgKHzaD5HkTkifK/<0;1>/*)))#3xh8xmhn";
|
||||
let desc = MultipathDescriptor::from_str(desc_str).unwrap();
|
||||
let desc = LianaDescriptor::from_str(desc_str).unwrap();
|
||||
let receive_desc = desc.receive_descriptor().clone();
|
||||
let change_desc = desc.change_descriptor().clone();
|
||||
let config = Config {
|
||||
|
||||
@ -424,7 +424,7 @@ mod tests {
|
||||
});
|
||||
let recov_keys = descriptors::PathInfo::Single(recov_key);
|
||||
let policy = descriptors::LianaPolicy::new(prim_keys, recov_keys, 42).unwrap();
|
||||
let desc = descriptors::MultipathDescriptor::new(policy);
|
||||
let desc = descriptors::LianaDescriptor::new(policy);
|
||||
|
||||
// Create a dummy PSBT spending a coin from this descriptor with a single input and single
|
||||
// (external) output. We'll be modifying it as we go.
|
||||
|
||||
@ -91,7 +91,7 @@ impl BitcoinInterface for DummyBitcoind {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn start_rescan(&self, _: &descriptors::MultipathDescriptor, _: u32) -> Result<(), String> {
|
||||
fn start_rescan(&self, _: &descriptors::LianaDescriptor, _: u32) -> Result<(), String> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -402,7 +402,7 @@ impl DummyLiana {
|
||||
let owner_key = descriptors::PathInfo::Single(descriptor::DescriptorPublicKey::from_str("[aabbccdd]xpub68JJTXc1MWK8KLW4HGLXZBJknja7kDUJuFHnM424LbziEXsfkh1WQCiEjjHw4zLqSUm4rvhgyGkkuRowE9tCJSgt3TQB5J3SKAbZ2SdcKST/<0;1>/*").unwrap());
|
||||
let heir_key = descriptors::PathInfo::Single(descriptor::DescriptorPublicKey::from_str("[aabbccdd]xpub68JJTXc1MWK8PEQozKsRatrUHXKFNkD1Cb1BuQU9Xr5moCv87anqGyXLyUd4KpnDyZgo3gz4aN1r3NiaoweFW8UutBsBbgKHzaD5HkTkifK/<0;1>/*").unwrap());
|
||||
let policy = descriptors::LianaPolicy::new(owner_key, heir_key, 10_000).unwrap();
|
||||
let desc = descriptors::MultipathDescriptor::new(policy);
|
||||
let desc = descriptors::LianaDescriptor::new(policy);
|
||||
let config = Config {
|
||||
bitcoin_config,
|
||||
bitcoind_config: None,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user