Skip to content
Open
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
16 changes: 2 additions & 14 deletions bip-0360/ref-impl/common/tests/data/p2mr_construction.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
},
{
"id": "p2mr_different_version_leaves",
"objective": "Tests P2MR with two script leaves of different versions. TO-DO: currently ignores given leaf version and over-rides. Probably better to throw error",
"objective": "Tests P2MR with two script leaves of different versions. BIP-360 requires all leaves to use leaf version 0xc0; a non-standard version must throw an error.",
"given": {
"scriptTree": [
{
Expand All @@ -75,20 +75,8 @@
}
]
},
"intermediary": {
"leafHashes": [
"8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7",
"f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a"
],
"merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef"
},
"expected": {
"scriptPubKey": "52206c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef",
"bip350Address": "bc1zdskuzp4ts94h87ws0c7drmev3sf9dagewj8qsylyahfyqhf800hsam4d6e",
"scriptPathControlBlocks": [
"c1f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a",
"c18ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
]
"error": "BIP-360 requires leaf version 0xc0; leaf 1 has version 250"
}
},
{
Expand Down
3 changes: 2 additions & 1 deletion bip-0360/ref-impl/rust/src/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub struct TestVector {
pub id: String,
pub objective: String,
pub given: TestVectorGiven,
#[serde(default)]
pub intermediary: TestVectorIntermediary,
pub expected: TestVectorExpected,
}
Expand All @@ -132,7 +133,7 @@ pub struct TestVectorGiven {
pub control_block: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct TestVectorIntermediary {

#[serde(default)]
Expand Down
3 changes: 3 additions & 0 deletions bip-0360/ref-impl/rust/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ pub enum P2MRError {
// We can add more specific error variants here as needed
#[error("Invalid script tree structure: {0}")]
InvalidScriptTree(String),

#[error("BIP-360 requires leaf version 0xc0; leaf {0} has version {1}")]
InvalidLeafVersion(u8, u8),
}
28 changes: 20 additions & 8 deletions bip-0360/ref-impl/rust/tests/p2mr_construction.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashSet;
use bitcoin::{Network, ScriptBuf};
use bitcoin::taproot::{LeafVersion, TapTree, ScriptLeaves, TapLeafHash, TaprootMerkleBranch, TapNodeHash};
use bitcoin::p2mr::{P2mrBuilder, P2mrControlBlock, P2mrSpendInfo};
use bitcoin::p2mr::{P2mrBuilder, P2mrControlBlock, P2mrSpendInfo, P2MR_LEAF_VERSION};
use bitcoin::hashes::Hash;

use hex;
Expand Down Expand Up @@ -72,7 +72,9 @@ fn test_p2mr_different_version_leaves() {

let test_vectors = &*TEST_VECTORS;
let test_vector = test_vectors.test_vector_map.get(P2MR_DIFFERENT_VERSION_LEAVES_TEST).unwrap();
process_test_vector_p2mr(test_vector).unwrap();
let test_result = process_test_vector_p2mr(test_vector);
assert!(matches!(test_result.unwrap_err().downcast_ref::<P2MRError>(),
Some(P2MRError::InvalidLeafVersion(_, _))));
}

#[test]
Expand Down Expand Up @@ -137,29 +139,37 @@ fn process_test_vector_p2mr(test_vector: &TestVector) -> anyhow::Result<()> {
let mut p2mr_builder: P2mrBuilder = P2mrBuilder::new();

let mut control_block_data: Vec<(ScriptBuf, LeafVersion)> = Vec::new();
let mut traversal_result: anyhow::Result<()> = Ok(());

// 1) traverse test vector script tree and add leaves to P2MR builder
if let Some(script_tree) = tv_script_tree {

script_tree.traverse_with_right_subtree_first(0, Direction::Root,&mut |node, depth, direction| {

if traversal_result.is_err() { return; }

if let TVScriptTree::Leaf(tv_leaf) = node {

let tv_leaf_script_bytes = hex::decode(&tv_leaf.script).unwrap();

// NOTE: IOT to execute script_info.control_block(..), will add these to a vector
let tv_leaf_script_buf = ScriptBuf::from_bytes(tv_leaf_script_bytes.clone());
let tv_leaf_version = LeafVersion::from_consensus(tv_leaf.leaf_version).unwrap();

if tv_leaf.leaf_version != P2MR_LEAF_VERSION {
traversal_result = Err(P2MRError::InvalidLeafVersion(tv_leaf.id, tv_leaf.leaf_version).into());
return;
}

control_block_data.push((tv_leaf_script_buf.clone(), tv_leaf_version));

let mut modified_depth = depth + 1;
if direction == Direction::Root {
modified_depth = depth;
}
debug!("traverse_with_depth: leaf_count: {}, depth: {}, modified_depth: {}, direction: {}, tv_leaf_script: {}",
debug!("traverse_with_depth: leaf_count: {}, depth: {}, modified_depth: {}, direction: {}, tv_leaf_script: {}",
tv_leaf_count, depth, modified_depth, direction, tv_leaf.script);

// NOTE: Some of the the test vectors in this project specify leaves with non-standard versions (ie: 250 / 0xfa)

p2mr_builder = p2mr_builder.clone().add_leaf_with_ver(depth, tv_leaf_script_buf.clone(), tv_leaf_version)
.unwrap_or_else(|e| {
panic!("Failed to add leaf: {:?}", e);
Expand All @@ -177,6 +187,8 @@ fn process_test_vector_p2mr(test_vector: &TestVector) -> anyhow::Result<()> {
return Err(P2MRError::MissingScriptTreeLeaf.into());
}

traversal_result?;

let spend_info: P2mrSpendInfo = p2mr_builder.clone()
.finalize()
.unwrap_or_else(|e| {
Expand Down