
== 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<Self, p2mrError> {
        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<p2mrSpendInfo, p2mrError> {
        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<TapNodeHash>

}
```

## 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<TapNodeHash>) -> 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<TapNodeHash>, hrp: impl Into<KnownHrp>) -> Address {
    let program = WitnessProgram::p2mr(merkle_root);
    Address::from_witness_program(program, hrp)
}
```
