== bitcoin core === Two Different Size Limits: * *MAX_SCRIPT_ELEMENT_SIZE* (in interpreter.cpp line 1882) - This is a consensus rule that limits individual stack elements to 520 bytes. This is what's currently blocking your SLH-DSA signature. * *MAX_STANDARD_P2MR_STACK_ITEM_SIZE* (in policy.h) - This is a policy rule that limits P2MR stack items to 80 bytes (or 8000 bytes with your change) for standardness. == P2MR changes to rust-bitcoin # 1. p2mr module The p2mr branch of rust-bitcoin includes a new module: `p2mr`. Source code for this new module can be found [here](https://github.com/jbride/rust-bitcoin/blob/p2mr/bitcoin/src/p2mr/mod.rs). Highlights of this _p2mr_ module as follows: ## 1.1. p2mrBuilder This is struct inherits from the rust-bitcoin _TaprootBuilder_. It has an important modification in that it disables keypath spend. Similar to its Taproot parent, p2mrBuilder provides functionality to add leaves to a TapTree. One its TapTree has been fully populated with all leaves, an instance of _p2mrSpendInfo_ can be retrieved from p2mrBuilder. ``` pub struct p2mrBuilder { inner: TaprootBuilder } impl p2mrBuilder { /// Creates a new p2mr builder. pub fn new() -> Self { Self { inner: TaprootBuilder::new() } } /// Adds a leaf to the p2mr builder. pub fn add_leaf_with_ver( self, depth: u8, script: ScriptBuf, leaf_version: LeafVersion, ) -> Result { match self.inner.add_leaf_with_ver(depth, script, leaf_version) { Ok(builder) => Ok(Self { inner: builder }), Err(_) => Err(p2mrError::LeafAdditionError) } } /// Finalizes the p2mr builder. pub fn finalize(self) -> Result { let node_info: NodeInfo = self.inner.try_into_node_info().unwrap(); Ok(p2mrSpendInfo { merkle_root: Some(node_info.node_hash()), //script_map: self.inner.script_map().clone(), }) } /// Converts the p2mr builder into a Taproot builder. pub fn into_inner(self) -> TaprootBuilder { self.inner } } ``` ## 1.2. p2mrSpendInfo Provides merkle_root of a completed p2mr TapTree ``` /// A struct for p2mr spend information. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct p2mrSpendInfo { /// The merkle root of the script path. pub merkle_root: Option } ``` ## 1.3. p2mrScriptBuf Allows for creation of a p2mr scriptPubKey UTXO using only the merkle root of a script tree only. ``` /// A wrapper around ScriptBuf for p2mr (Pay to Quantum Resistant Hash) scripts. pub struct p2mrScriptBuf { inner: ScriptBuf } impl p2mrScriptBuf { /// Creates a new p2mr script from a ScriptBuf. pub fn new(inner: ScriptBuf) -> Self { Self { inner } } /// Generates p2mr scriptPubKey output /// Only accepts the merkle_root (of type TapNodeHash) /// since keypath spend is disabled in p2mr pub fn new_p2mr(merkle_root: TapNodeHash) -> Self { // https://github.com/cryptoquick/bips/blob/p2mr/bip-0360.mediawiki#scriptpubkey let merkle_root_hash_bytes: [u8; 32] = merkle_root.to_byte_array(); let script = Builder::new() .push_opcode(OP_PUSHNUM_3) // automatically pre-fixes with OP_PUSHBYTES_32 (as per size of hash) .push_slice(&merkle_root_hash_bytes) .into_script(); p2mrScriptBuf::new(script) } /// Returns the script as a reference. pub fn as_script(&self) -> &Script { self.inner.as_script() } } ``` ## 1.4. p2mr Control Block Closely related to P2TR control block. Difference being that _internal public key_ is not included. ``` /// A control block for p2mr (Pay to Quantum Resistant Hash) script path spending. /// This is a simplified version of Taproot's control block that excludes key-related fields. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct p2mrControlBlock { /// The version of the leaf. pub leaf_version: LeafVersion, /// The merkle branch of the leaf. pub merkle_branch: TaprootMerkleBranch, } ``` # 2. Witness Program New p2mr related functions that allow for creation of a new V3 _witness program_ given a merkle_root only. Found in bitcoin/src/blockdata/script/witness_program.rs ``` /// Creates a [`WitnessProgram`] from a 32 byte merkle root. fn new_p2mr(program: [u8; 32]) -> Self { WitnessProgram { version: WitnessVersion::V3, program: ArrayVec::from_slice(&program) } } /// Creates a pay to quantum resistant hash address from a merkle root. pub fn p2mr(merkle_root: Option) -> Self { let merkle_root = merkle_root.unwrap(); WitnessProgram::new_p2mr(merkle_root.to_byte_array()) } ``` # 3. Address New _p2mr_ function that allows for creation of a new _p2mr_ Address given a merkle_root only. Found in bitcoin/src/address/mod.rs ``` /// Creates a pay to quantum resistant hash address from a merkle root. pub fn p2mr(merkle_root: Option, hrp: impl Into) -> Address { let program = WitnessProgram::p2mr(merkle_root); Address::from_witness_program(program, hrp) } ```