mirror of
https://github.com/bitcoin/bips.git
synced 2026-03-02 15:43:53 +00:00
Review comments and assistance by: Armin Sabouri <armins88@gmail.com> D++ <82842780+dplusplus1024@users.noreply.github.com> Jameson Lopp <jameson.lopp@gmail.com> jbride <jbride2001@yahoo.com> Joey Yandle <xoloki@gmail.com> Jon Atack <jon@atack.com> Jonas Nick <jonasd.nick@gmail.com> Kyle Crews <kylecrews@Kyles-Mac-Studio.local> Mark "Murch" Erhardt <murch@murch.one> notmike-5 <notmike-5@users.noreply.github.com> Vojtěch Strnad <43024885+vostrnad@users.noreply.github.com> Co-authored-by: Ethan Heilman <ethan.r.heilman@gmail.com> Co-authored-by: Isabel Foxen Duke <110147802+Isabelfoxenduke@users.noreply.github.com>
175 lines
5.1 KiB
Plaintext
175 lines
5.1 KiB
Plaintext
|
|
== 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)
|
|
}
|
|
```
|