Skip to content

Commit

Permalink
primitives: add taproot ControlBlock and Parity structures
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Oct 5, 2023
1 parent 64a77f3 commit 873ebc8
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 57 deletions.
8 changes: 4 additions & 4 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

// Version 0.10.10:
// TODO: Ensure all serde uses both string and binary version
// TODO: Complete taproot consensus structure implementation (ControlBlock)
// TODO: Complete consensus encoding for taproot data
// TODO: Complete block data type implementation
// TODO: Move consensus-level timelocks and sequence locks from other libraries
// Version 1.0:
Expand Down Expand Up @@ -77,9 +77,9 @@ pub use script::{OpCode, RedeemScript, ScriptBytes, ScriptPubkey, SigScript};
pub use segwit::{SegwitError, Witness, WitnessProgram, WitnessScript, WitnessVer, Wtxid};
pub use sigtypes::{Bip340Sig, LegacySig, SigError, SighashFlag, SighashType};
pub use taproot::{
FutureLeafVer, InternalPk, IntoTapHash, InvalidLeafVer, LeafScript, LeafVer, TapBranchHash,
TapCode, TapLeafHash, TapMerklePath, TapNodeHash, TapScript, TAPROOT_ANNEX_PREFIX,
TAPROOT_LEAF_MASK, TAPROOT_LEAF_TAPSCRIPT,
ControlBlock, FutureLeafVer, InternalPk, IntoTapHash, InvalidLeafVer, LeafScript, LeafVer,
Parity, TapBranchHash, TapCode, TapLeafHash, TapMerklePath, TapNodeHash, TapScript,
TAPROOT_ANNEX_PREFIX, TAPROOT_LEAF_MASK, TAPROOT_LEAF_TAPSCRIPT,
};
pub use tx::{
LockTime, Outpoint, OutpointParseError, Sats, SeqNo, Tx, TxIn, TxOut, TxParseError, TxVer,
Expand Down
14 changes: 5 additions & 9 deletions primitives/src/stl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@
use strict_types::{CompileError, LibBuilder, TypeLib};

use crate::{
Bip340Sig, BlockHeader, ByteStr, Chain, FutureLeafVer, InternalPk, LeafScript, LeafVer,
LegacySig, OpCode, RedeemScript, TapBranchHash, TapCode, TapLeafHash, TapMerklePath,
TapNodeHash, TapScript, Tx, VBytes, VarInt, WeightUnits, WitnessProgram, WitnessScript,
WitnessVer, Wtxid, LIB_NAME_BITCOIN,
Bip340Sig, BlockHeader, ByteStr, Chain, ControlBlock, FutureLeafVer, LeafScript, LegacySig,
OpCode, RedeemScript, TapCode, TapLeafHash, TapNodeHash, TapScript, Tx, VBytes, VarInt,
WeightUnits, WitnessProgram, WitnessScript, WitnessVer, Wtxid, LIB_NAME_BITCOIN,
};

#[deprecated(since = "0.10.8", note = "use LIB_ID_BP_TX instead")]
Expand All @@ -35,7 +34,7 @@ pub const LIB_ID_BITCOIN: &str =
pub const LIB_ID_BP_TX: &str =
"urn:ubideco:stl:6GgF7biXPVNcus2FfQj2pQuRzau11rXApMQLfCZhojgi#money-pardon-parody";
pub const LIB_ID_BP_CONSENSUS: &str =
"urn:ubideco:stl:DrkRxZuxVjPSc5CtPmXhxQ14wyfVDz787WEfdrgqgffB#gray-prepare-proton";
"urn:ubideco:stl:A6tfQFthqmb39wR5sWvrfgf3oiAyazm8rh7ff35ruioi#russian-emerald-extra";

#[deprecated(since = "0.10.8", note = "use _bp_tx_stl instead")]
fn _bitcoin_stl() -> Result<TypeLib, CompileError> { _bp_tx_stl() }
Expand All @@ -59,15 +58,12 @@ fn _bp_consensus_stl() -> Result<TypeLib, CompileError> {
.transpile::<WitnessProgram>()
.transpile::<WitnessVer>()
.transpile::<TapNodeHash>()
.transpile::<TapBranchHash>()
.transpile::<TapLeafHash>()
.transpile::<InternalPk>()
.transpile::<TapMerklePath>()
.transpile::<LeafVer>()
.transpile::<FutureLeafVer>()
.transpile::<LeafScript>()
.transpile::<TapCode>()
.transpile::<TapScript>()
.transpile::<ControlBlock>()
.transpile::<BlockHeader>()
.transpile::<Tx>()
.transpile::<VarInt>()
Expand Down
79 changes: 79 additions & 0 deletions primitives/src/taproot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

use std::borrow::Borrow;
use std::fmt::{self, Formatter, LowerHex, UpperHex};
use std::ops::BitXor;
use std::{cmp, io};

use amplify::confinement::{Confined, U32};
Expand Down Expand Up @@ -457,3 +458,81 @@ impl ScriptPubkey {
self.len() == 34 && self[0] == WitnessVer::V1.op_code() as u8 && self[1] == OP_PUSHBYTES_32
}
}

/// invalid parity value {0} - must be 0 or 1
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Error)]
#[display(doc_comments)]
pub struct InvalidParityValue(pub u8);

/// Represents the parity passed between FFI function calls.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[display(lowercase)]
#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
#[strict_type(lib = LIB_NAME_BITCOIN, tags = repr, into_u8, try_from_u8)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
#[repr(u8)]
pub enum Parity {
/// Even parity.
#[strict_type(dumb)]
Even = 0,
/// Odd parity.
Odd = 1,
}

impl Parity {
/// Converts parity into an integer (byte) value.
///
/// This returns `0` for even parity and `1` for odd parity.
pub fn to_consensus_u8(self) -> u8 { self as u8 }

/// Constructs a [`Parity`] from a byte.
///
/// The only allowed values are `0` meaning even parity and `1` meaning odd.
/// Other values result in error being returned.
pub fn from_consensus_u8(parity: u8) -> Result<Parity, InvalidParityValue> {
match parity {
0 => Ok(Parity::Even),
1 => Ok(Parity::Odd),
invalid => Err(InvalidParityValue(invalid)),
}
}
}

/// Returns even parity if the operands are equal, odd otherwise.
impl BitXor for Parity {
type Output = Parity;

fn bitxor(self, rhs: Parity) -> Self::Output {
// This works because Parity has only two values (i.e. only 1 bit of
// information).
if self == rhs {
Parity::Even // 1^1==0 and 0^0==0
} else {
Parity::Odd // 1^0==1 and 0^1==1
}
}
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
#[strict_type(lib = LIB_NAME_BITCOIN)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct ControlBlock {
/// The tapleaf version.
pub leaf_version: LeafVer,
/// The parity of the output key (NOT THE INTERNAL KEY WHICH IS ALWAYS
/// XONLY).
pub output_key_parity: Parity,
/// The internal key.
pub internal_key: InternalPk,
/// The merkle proof of a script associated with this leaf.
pub merkle_branch: TapMerklePath,
}
90 changes: 47 additions & 43 deletions stl/[email protected]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-----BEGIN STRICT TYPE LIB-----
Id: urn:ubideco:stl:DrkRxZuxVjPSc5CtPmXhxQ14wyfVDz787WEfdrgqgffB
Id: urn:ubideco:stl:A6tfQFthqmb39wR5sWvrfgf3oiAyazm8rh7ff35ruioi
Name: Bitcoin
Dependencies:
urn:ubideco:stl:9KALDYR8Nyjq4FdMW6kYoL7vdkWnqPqNuFnmE9qHpNjZ
Expand All @@ -12,48 +12,52 @@ AQAHAABAIAALQmxvY2tIZWFkZXIGBgd2ZXJzaW9uAABEDXByZXZCbG9ja0hhc2gB
136XKN8Qx+HJT3+gvLwHRRJSZMs+SsX4k0LE/8jKtLcKbWVya2xlUm9vdAAHAABA
IAAEdGltZQAABARiaXRzAAAEBW5vbmNlAAAEB0J5dGVTdHIFAQAIAABAAAAAAAAA
AAD/////AAAAAAVDaGFpbgMEB2JpdGNvaW4AB3JlZ3Rlc3SACHRlc3RuZXQzgwZz
aWduZXSEDUZ1dHVyZUxlYWZWZXIFAQAAAQpJbnRlcm5hbFBrBQEABwAAQCAACkxl
YWZTY3JpcHQGAgd2ZXJzaW9uAbYzCakYv7aSDW7IWKQkhyNGWmk/ckMHv/8d1zpz
gU7JBnNjcmlwdAElq/W5EhQXuqM51F97FXWncUvhenUYXdAxNXrUyS3phgdMZWFm
VmVyBQEAAAEJTGVnYWN5U2lnBgIDc2lnAAgAAEAAAAAAAAAAAP8AAAAAAAAADHNp
Z2hhc2hfdHlwZQHbF2Q+dwkTJ+gEmSSB1dxgFSMIlVM55Yszn9RMT3JIKghMb2Nr
VGltZQUBAAAEBk9wQ29kZQMSCnB1c2hCeXRlczAAC3B1c2hCeXRlczMyIAlwdXNo
RGF0YTFMCXB1c2hEYXRhMk0JcHVzaERhdGE0TghyZXNlcnZlZFAIcHVzaE51bTFR
BnJldHVybmoDZHVwdgVlcXVhbIcLZXF1YWxWZXJpZnmICXJpcGVtZDE2MKYEc2hh
MacGc2hhMjU2qAdoYXNoMTYwqQdoYXNoMjU2qghjaGVja1NpZ6wOY2hlY2tTaWdW
ZXJpZnmtCE91dHBvaW50BgIEdHhpZAGjgkLzy9fR0KES2o3hYC9W1PhvDsTEdsXA
aFlMSwRlVgR2b3V0ASHjPkPFqlzyKSdTozjBZ+07Y5xN2c69qY80aRe6yUN1DFJl
ZGVlbVNjcmlwdAUBASWr9bkSFBe6oznUX3sVdadxS+F6dRhd0DE1etTJLemGBFNh
dHMFAQAACAtTY3JpcHRCeXRlcwUBAAgAAEAAAAAAAAAAAP////8AAAAADFNjcmlw
dFB1YmtleQUBASWr9bkSFBe6oznUX3sVdadxS+F6dRhd0DE1etTJLemGBVNlcU5v
BQEAAAQJU2lnU2NyaXB0BQEBJav1uRIUF7qjOdRfexV1p3FL4Xp1GF3QMTV61Mkt
6YYLU2lnaGFzaEZsYWcDAwNhbGwBBG5vbmUCBnNpbmdsZQMLU2lnaGFzaFR5cGUG
AgRmbGFnAf8+an/Ix4VDTvyO53SzALGb7Jhxopoe8QCL7xDrKNU0DGFueW9uZUNh
blBheQJ7hIA8nvriESWnfCw5vHDS/ej5Q64N/Zz05oLtx2bKcGGGItF7rvBmAt/n
dcmA4LNrbrroCQ2AdfdRO+xLk/ZNDVRhcEJyYW5jaEhhc2gFAQAHAABAIAAHVGFw
Q29kZQMGC3B1c2hCeXRlczMyIAlwdXNoRGF0YTFMCXB1c2hEYXRhMk0JcHVzaERh
dGE0TghyZXNlcnZlZFAGcmV0dXJuagtUYXBMZWFmSGFzaAUBAAcAAEAgAA1UYXBN
ZXJrbGVQYXRoBQEACAGv68Wd2P1QRx2YXcJBKC6rqYxIivJkY8F2flEGIsKS2AAA
AAAAAAAA/wAAAAAAAAALVGFwTm9kZUhhc2gFAQAHAABAIAAJVGFwU2NyaXB0BQEB
Jav1uRIUF7qjOdRfexV1p3FL4Xp1GF3QMTV61Mkt6YYCVHgGBAd2ZXJzaW9uAah8
xnlkZ+VX10TlyWI64AzLldkaDS8D33TAdRJPvseeBmlucHV0cwAIARlHLRfYYgen
DyExqVihaKVuKtZTP5xmTBl32lz5/mKGAAAAAAAAAAD/////AAAAAAdvdXRwdXRz
AAgBkDtkcHmEjxsmUyrkzsamiUSgU1i48IHLJrO7+C2eO/MAAAAAAAAAAP////8A
AAAACGxvY2tUaW1lATXaHRU5IG673dykwz2HMerym6fadN89yIIgHE4WtbkcBFR4
SW4GBApwcmV2T3V0cHV0AehqQM1cJfm94oT/aaURMqdBKyFVvQ5WEsG/44SVYMUG
CXNpZ1NjcmlwdAE4dQSxS3wORm1HnhdHfSR0JH/4A2TsPUuq9zog90F0awhzZXF1
ZW5jZQEBGW2FKcj22kRNFU6NnIy9ng+NiQJaO7CRIcY9UrAehwd3aXRuZXNzAXN3
Q3A2kyBJzSiVCKpxfOOCnbJFLlXoTtT8LjzNLgCdBVR4T3V0BgIFdmFsdWUBl/XX
BkKuKjOSJTuoTh3OxJPjvz7TcbGHc4Y1TsyIgmsMc2NyaXB0UHVia2V5Ab78Hvxm
pRn9ZFJqOhOHQOfxEC0Lvv86wUZO8/dAdnRcBVR4VmVyBQEAAEQEVHhpZAUBAAcA
AEAgAAZWQnl0ZXMFAQAABAZWYXJJbnQFAQAACARWb3V0BQEAAAQLV2VpZ2h0VW5p
dHMFAQAABAdXaXRuZXNzBQEACAAIAABAAAAAAAAAAAD/////AAAAAAAAAAAAAAAA
/////wAAAAAOV2l0bmVzc1Byb2dyYW0GAgd2ZXJzaW9uAdHs2nZn5ELtTRJppmcD
NuX+9DevXs4raa66DEZWxPqtB3Byb2dyYW0ACAAAQAIAAAAAAAAAKAAAAAAAAAAN
V2l0bmVzc1NjcmlwdAUBASWr9bkSFBe6oznUX3sVdadxS+F6dRhd0DE1etTJLemG
CldpdG5lc3NWZXIDEQJ2MAACdjFRAnYyUgJ2M1MCdjRUAnY1VQJ2NlYCdjdXAnY4
WAJ2OVkDdjEwWgN2MTFbA3YxMlwDdjEzXQN2MTReA3YxNV8DdjE2YAVXdHhpZAUB
AAcAAEAgAA==
aWduZXSEDENvbnRyb2xCbG9jawYEC2xlYWZWZXJzaW9uAbYzCakYv7aSDW7IWKQk
hyNGWmk/ckMHv/8d1zpzgU7JD291dHB1dEtleVBhcml0eQGPyiYjolVEI5WPpnqn
bUNqFd5k6xCz9PmZFCIvlRFmiAtpbnRlcm5hbEtleQHf+AA8gf5H/FQjsdLG4g8N
36pmvczzfXQTyR9l2gA8iAxtZXJrbGVCcmFuY2gB7gMeZlFQaLZ0GVxRd/QKg8QA
UlvBpDAUGABpT73wc6QNRnV0dXJlTGVhZlZlcgUBAAABCkludGVybmFsUGsFAQAH
AABAIAAKTGVhZlNjcmlwdAYCB3ZlcnNpb24BtjMJqRi/tpINbshYpCSHI0ZaaT9y
Qwe//x3XOnOBTskGc2NyaXB0ASWr9bkSFBe6oznUX3sVdadxS+F6dRhd0DE1etTJ
LemGB0xlYWZWZXIFAQAAAQlMZWdhY3lTaWcGAgNzaWcACAAAQAAAAAAAAAAA/wAA
AAAAAAAMc2lnaGFzaF90eXBlAdsXZD53CRMn6ASZJIHV3GAVIwiVUznlizOf1ExP
ckgqCExvY2tUaW1lBQEAAAQGT3BDb2RlAxIKcHVzaEJ5dGVzMAALcHVzaEJ5dGVz
MzIgCXB1c2hEYXRhMUwJcHVzaERhdGEyTQlwdXNoRGF0YTROCHJlc2VydmVkUAhw
dXNoTnVtMVEGcmV0dXJuagNkdXB2BWVxdWFshwtlcXVhbFZlcmlmeYgJcmlwZW1k
MTYwpgRzaGExpwZzaGEyNTaoB2hhc2gxNjCpB2hhc2gyNTaqCGNoZWNrU2lnrA5j
aGVja1NpZ1Zlcmlmea0IT3V0cG9pbnQGAgR0eGlkAaOCQvPL19HQoRLajeFgL1bU
+G8OxMR2xcBoWUxLBGVWBHZvdXQBIeM+Q8WqXPIpJ1OjOMFn7TtjnE3Zzr2pjzRp
F7rJQ3UGUGFyaXR5AwIEZXZlbgADb2RkAQxSZWRlZW1TY3JpcHQFAQElq/W5EhQX
uqM51F97FXWncUvhenUYXdAxNXrUyS3phgRTYXRzBQEAAAgLU2NyaXB0Qnl0ZXMF
AQAIAABAAAAAAAAAAAD/////AAAAAAxTY3JpcHRQdWJrZXkFAQElq/W5EhQXuqM5
1F97FXWncUvhenUYXdAxNXrUyS3phgVTZXFObwUBAAAECVNpZ1NjcmlwdAUBASWr
9bkSFBe6oznUX3sVdadxS+F6dRhd0DE1etTJLemGC1NpZ2hhc2hGbGFnAwMDYWxs
AQRub25lAgZzaW5nbGUDC1NpZ2hhc2hUeXBlBgIEZmxhZwH/Pmp/yMeFQ078jud0
swCxm+yYcaKaHvEAi+8Q6yjVNAxhbnlvbmVDYW5QYXkCe4SAPJ764hElp3wsObxw
0v3o+UOuDf2c9OaC7cdmynBhhiLRe67wZgLf53XJgOCza2666AkNgHX3UTvsS5P2
TQ1UYXBCcmFuY2hIYXNoBQEABwAAQCAAB1RhcENvZGUDBgtwdXNoQnl0ZXMzMiAJ
cHVzaERhdGExTAlwdXNoRGF0YTJNCXB1c2hEYXRhNE4IcmVzZXJ2ZWRQBnJldHVy
bmoLVGFwTGVhZkhhc2gFAQAHAABAIAANVGFwTWVya2xlUGF0aAUBAAgBr+vFndj9
UEcdmF3CQSguq6mMSIryZGPBdn5RBiLCktgAAAAAAAAAAIAAAAAAAAAAC1RhcE5v
ZGVIYXNoBQEABwAAQCAACVRhcFNjcmlwdAUBASWr9bkSFBe6oznUX3sVdadxS+F6
dRhd0DE1etTJLemGAlR4BgQHdmVyc2lvbgGofMZ5ZGflV9dE5cliOuAMy5XZGg0v
A990wHUST77HngZpbnB1dHMACAEZRy0X2GIHpw8hMalYoWilbirWUz+cZkwZd9pc
+f5ihgAAAAAAAAAA/////wAAAAAHb3V0cHV0cwAIAZA7ZHB5hI8bJlMq5M7GpolE
oFNYuPCByyazu/gtnjvzAAAAAAAAAAD/////AAAAAAhsb2NrVGltZQE12h0VOSBu
u93cpMM9hzHq8pun2nTfPciCIBxOFrW5HARUeEluBgQKcHJldk91dHB1dAHoakDN
XCX5veKE/2mlETKnQSshVb0OVhLBv+OElWDFBglzaWdTY3JpcHQBOHUEsUt8DkZt
R54XR30kdCR/+ANk7D1Lqvc6IPdBdGsIc2VxdWVuY2UBARlthSnI9tpETRVOjZyM
vZ4PjYkCWjuwkSHGPVKwHocHd2l0bmVzcwFzd0NwNpMgSc0olQiqcXzjgp2yRS5V
6E7U/C48zS4AnQVUeE91dAYCBXZhbHVlAZf11wZCriozkiU7qE4dzsST478+03Gx
h3OGNU7MiIJrDHNjcmlwdFB1YmtleQG+/B78ZqUZ/WRSajoTh0Dn8RAtC77/OsFG
TvP3QHZ0XAVUeFZlcgUBAABEBFR4aWQFAQAHAABAIAAGVkJ5dGVzBQEAAAQGVmFy
SW50BQEAAAgEVm91dAUBAAAEC1dlaWdodFVuaXRzBQEAAAQHV2l0bmVzcwUBAAgA
CAAAQAAAAAAAAAAA/////wAAAAAAAAAAAAAAAP////8AAAAADldpdG5lc3NQcm9n
cmFtBgIHdmVyc2lvbgHR7Np2Z+RC7U0SaaZnAzbl/vQ3r17OK2muugxGVsT6rQdw
cm9ncmFtAAgAAEACAAAAAAAAACgAAAAAAAAADVdpdG5lc3NTY3JpcHQFAQElq/W5
EhQXuqM51F97FXWncUvhenUYXdAxNXrUyS3phgpXaXRuZXNzVmVyAxECdjAAAnYx
UQJ2MlICdjNTAnY0VAJ2NVUCdjZWAnY3VwJ2OFgCdjlZA3YxMFoDdjExWwN2MTJc
A3YxM10DdjE0XgN2MTVfA3YxNmAFV3R4aWQFAQAHAABAIAA=

-----END STRICT TYPE LIB-----

Binary file modified stl/[email protected]
Binary file not shown.
10 changes: 9 additions & 1 deletion stl/[email protected]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{-
Id: urn:ubideco:stl:DrkRxZuxVjPSc5CtPmXhxQ14wyfVDz787WEfdrgqgffB#gray-prepare-proton
Id: urn:ubideco:stl:A6tfQFthqmb39wR5sWvrfgf3oiAyazm8rh7ff35ruioi#russian-emerald-extra
Name: Bitcoin
Version: 0.1.0
Description: Consensus library for bitcoin protocol
Expand Down Expand Up @@ -32,6 +32,11 @@ data ByteStr :: [Byte ^ ..0xffffffff]
-- urn:ubideco:semid:6aRP3odHaTGySvSWHjreC8HsbX5ss9LxkQqwcjaoxhpv#aspirin-brown-alpine
data Chain :: bitcoin:0 | regtest:128 | testnet3:131 | signet:132

-- urn:ubideco:semid:C7rC7icVsoUF43k8QpzxWSx6BAbT8uyY2PWGjsQuf2kd#mega-optic-type
data ControlBlock :: leafVersion LeafVer
, outputKeyParity Parity
, internalKey InternalPk
, merkleBranch TapMerklePath
-- urn:ubideco:semid:CvDS9EgqtBkWLvADynNeR7VGwVAy14EXViKnLaBkqtac#student-formula-circus
data FutureLeafVer :: U8
-- urn:ubideco:semid:G5HFVaWwWNYSzqk548JgGZ8WKy6dQ2ftVgkJvHjgRudZ#horse-major-vienna
Expand All @@ -53,6 +58,9 @@ data OpCode :: pushBytes0:0 | pushBytes32:32 | pushData1:76 | pushData

-- urn:ubideco:semid:FWt2MSo8A4nsYgYbuBqMRNLiKgtzvLBgUn774iKzTcuf#pocket-pegasus-frank
data Outpoint :: txid Txid, vout Vout
-- urn:ubideco:semid:AgJ5n58hrH761B4MV7giZ1FhMipaDrUmnFYCLno74HDy#method-editor-echo
data Parity :: even:0 | odd:1

-- urn:ubideco:semid:85m9Qv56neQKaqiPSZ8G8NPWz5DDeJeeXhBwnUpcZGug#delta-jumbo-clone
data RedeemScript :: ScriptBytes
-- urn:ubideco:semid:BEBz6h7AGjYSDRCxVHnjYkkkxzBsjN3EvyNiD4ZrzmRL#pyramid-spray-star
Expand Down

0 comments on commit 873ebc8

Please sign in to comment.