Class: Bitcoin::Taproot::SimpleBuilder
- Inherits:
-
Object
- Object
- Bitcoin::Taproot::SimpleBuilder
- Includes:
- Opcodes
- Defined in:
- lib/bitcoin/taproot/simple_builder.rb
Overview
Utility class to construct Taproot outputs from internal key and script tree.keyPathSpending SimpleBuilder builds a script tree that places all lock scripts, in the order they are added, as leaf nodes. It is not possible to specify the depth of the locking script or to insert any intermediate nodes.
Direct Known Subclasses
Constant Summary
Constants included from Opcodes
Opcodes::DUPLICATE_KEY, Opcodes::NAME_MAP, Opcodes::OPCODES_MAP, Opcodes::OP_0, Opcodes::OP_0NOTEQUAL, Opcodes::OP_1, Opcodes::OP_10, Opcodes::OP_11, Opcodes::OP_12, Opcodes::OP_13, Opcodes::OP_14, Opcodes::OP_15, Opcodes::OP_16, Opcodes::OP_1ADD, Opcodes::OP_1NEGATE, Opcodes::OP_1SUB, Opcodes::OP_2, Opcodes::OP_2DIV, Opcodes::OP_2DROP, Opcodes::OP_2DUP, Opcodes::OP_2MUL, Opcodes::OP_2OVER, Opcodes::OP_2ROT, Opcodes::OP_2SWAP, Opcodes::OP_3, Opcodes::OP_3DUP, Opcodes::OP_4, Opcodes::OP_5, Opcodes::OP_6, Opcodes::OP_7, Opcodes::OP_8, Opcodes::OP_9, Opcodes::OP_ABS, Opcodes::OP_ADD, Opcodes::OP_AND, Opcodes::OP_BOOLAND, Opcodes::OP_BOOLOR, Opcodes::OP_CAT, Opcodes::OP_CHECKMULTISIG, Opcodes::OP_CHECKMULTISIGVERIFY, Opcodes::OP_CHECKSIG, Opcodes::OP_CHECKSIGADD, Opcodes::OP_CHECKSIGVERIFY, Opcodes::OP_CODESEPARATOR, Opcodes::OP_DEPTH, Opcodes::OP_DIV, Opcodes::OP_DROP, Opcodes::OP_DUP, Opcodes::OP_ELSE, Opcodes::OP_ENDIF, Opcodes::OP_EQUAL, Opcodes::OP_EQUALVERIFY, Opcodes::OP_FROMALTSTACK, Opcodes::OP_GREATERTHAN, Opcodes::OP_GREATERTHANOREQUAL, Opcodes::OP_HASH160, Opcodes::OP_HASH256, Opcodes::OP_IF, Opcodes::OP_IFDUP, Opcodes::OP_INVALIDOPCODE, Opcodes::OP_INVERT, Opcodes::OP_LEFT, Opcodes::OP_LESSTHAN, Opcodes::OP_LESSTHANOREQUAL, Opcodes::OP_LSHIFT, Opcodes::OP_MAX, Opcodes::OP_MIN, Opcodes::OP_MOD, Opcodes::OP_MUL, Opcodes::OP_NEGATE, Opcodes::OP_NIP, Opcodes::OP_NOP, Opcodes::OP_NOP1, Opcodes::OP_NOP10, Opcodes::OP_NOP2, Opcodes::OP_NOP3, Opcodes::OP_NOP4, Opcodes::OP_NOP5, Opcodes::OP_NOP6, Opcodes::OP_NOP7, Opcodes::OP_NOP8, Opcodes::OP_NOP9, Opcodes::OP_NOT, Opcodes::OP_NOTIF, Opcodes::OP_NUMEQUAL, Opcodes::OP_NUMEQUALVERIFY, Opcodes::OP_NUMNOTEQUAL, Opcodes::OP_OR, Opcodes::OP_OVER, Opcodes::OP_PICK, Opcodes::OP_PUBKEY, Opcodes::OP_PUBKEYHASH, Opcodes::OP_PUSHDATA1, Opcodes::OP_PUSHDATA2, Opcodes::OP_PUSHDATA4, Opcodes::OP_RESERVED, Opcodes::OP_RESERVED1, Opcodes::OP_RESERVED2, Opcodes::OP_RETURN, Opcodes::OP_RIGHT, Opcodes::OP_RIPEMD160, Opcodes::OP_ROLL, Opcodes::OP_ROT, Opcodes::OP_RSHIFT, Opcodes::OP_SHA1, Opcodes::OP_SHA256, Opcodes::OP_SIZE, Opcodes::OP_SUB, Opcodes::OP_SUBSTR, Opcodes::OP_SUCCESSES, Opcodes::OP_SWAP, Opcodes::OP_TOALTSTACK, Opcodes::OP_TUCK, Opcodes::OP_VER, Opcodes::OP_VERIF, Opcodes::OP_VERIFY, Opcodes::OP_VERNOTIF, Opcodes::OP_WITHIN, Opcodes::OP_XOR
Instance Attribute Summary collapse
-
#branches ⇒ Object
readonly
List of branch that has two child leaves.
-
#internal_key ⇒ Object
readonly
String with hex format.
Instance Method Summary collapse
-
#add_branch(leaf1, leaf2 = nil) ⇒ Object
Add a pair of leaf nodes as a branch.
-
#add_leaf(leaf) ⇒ Object
Add a leaf node to the end of the current branch.
-
#build ⇒ Bitcoin::Script
Build P2TR script.
-
#control_block(leaf) ⇒ Bitcoin::Taproot::ControlBlock
Generate control block needed to unlock with script-path.
-
#inclusion_proof(leaf) ⇒ Array[String]
Generate inclusion proof for
leaf
. -
#initialize(internal_key, leaves = []) ⇒ Bitcoin::Taproot::SimpleBuilder
constructor
Initialize builder.
-
#tweak_private_key(key) ⇒ Bitcoin::Key
Compute the secret key for a tweaked public key.
-
#tweak_public_key ⇒ Bitcoin::Key
Compute the tweaked public key.
Methods included from Opcodes
defined?, name_to_opcode, op_success?, opcode_to_name, opcode_to_small_int, small_int_to_opcode
Constructor Details
#initialize(internal_key, leaves = []) ⇒ Bitcoin::Taproot::SimpleBuilder
Initialize builder.
18 19 20 21 22 23 24 25 26 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 18 def initialize(internal_key, leaves = []) raise ArgumentError, "Internal public key must be string." unless internal_key.is_a?(String) raise Error, "Internal public key must be #{X_ONLY_PUBKEY_SIZE} bytes" unless internal_key.htb.bytesize == X_ONLY_PUBKEY_SIZE raise Error, 'leaf must be Bitcoin::Taproot::LeafNode object' if leaves.find{ |leaf| !leaf.is_a?(Bitcoin::Taproot::LeafNode)} @leaves = leaves @branches = leaves.each_slice(2).map.to_a @internal_key = internal_key end |
Instance Attribute Details
#branches ⇒ Object (readonly)
List of branch that has two child leaves
11 12 13 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 11 def branches @branches end |
#internal_key ⇒ Object (readonly)
String with hex format
10 11 12 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 10 def internal_key @internal_key end |
Instance Method Details
#add_branch(leaf1, leaf2 = nil) ⇒ Object
Add a pair of leaf nodes as a branch. If there is only one, add a branch with only one child.
44 45 46 47 48 49 50 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 44 def add_branch(leaf1, leaf2 = nil) raise Error, 'leaf1 must be Bitcoin::Taproot::LeafNode object' unless leaf1.is_a?(Bitcoin::Taproot::LeafNode) raise Error, 'leaf2 must be Bitcoin::Taproot::LeafNode object' if leaf2 && !leaf2.is_a?(Bitcoin::Taproot::LeafNode) branches << (leaf2.nil? ? [leaf1] : [leaf1, leaf2]) self end |
#add_leaf(leaf) ⇒ Object
Add a leaf node to the end of the current branch.
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 30 def add_leaf(leaf) raise Error, 'leaf must be Bitcoin::Taproot::LeafNode object' unless leaf.is_a?(Bitcoin::Taproot::LeafNode) if branches.last&.size == 1 branches.last << leaf else branches << [leaf] end self end |
#build ⇒ Bitcoin::Script
Build P2TR script.
54 55 56 57 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 54 def build q = tweak_public_key Bitcoin::Script.new << OP_1 << q.xonly_pubkey end |
#control_block(leaf) ⇒ Bitcoin::Taproot::ControlBlock
Generate control block needed to unlock with script-path.
77 78 79 80 81 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 77 def control_block(leaf) path = inclusion_proof(leaf) parity = tweak_public_key.to_point.has_even_y? ? 0 : 1 ControlBlock.new(parity, leaf.leaf_ver, internal_key, path.map(&:bth)) end |
#inclusion_proof(leaf) ⇒ Array[String]
Generate inclusion proof for leaf
.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 87 def inclusion_proof(leaf) proofs = [] target_branch = branches.find{|b| b.include?(leaf)} raise Error 'Specified leaf does not exist' unless target_branch # flatten each branch proofs << hash_value(target_branch.find{|b| b != leaf}) if target_branch.size == 2 parent_hash = combine_hash(target_branch) parents = branches.map {|pair| combine_hash(pair)} until parents.size == 1 parents = parents.each_slice(2).map do |pair| combined = combine_hash(pair) unless pair.size == 1 if hash_value(pair[0]) == parent_hash proofs << hash_value(pair[1]) parent_hash = combined elsif hash_value(pair[1]) == parent_hash proofs << hash_value(pair[0]) parent_hash = combined end end combined end end proofs end |
#tweak_private_key(key) ⇒ Bitcoin::Key
Compute the secret key for a tweaked public key.
68 69 70 71 72 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 68 def tweak_private_key(key) raise Error, 'Requires private key' unless key.priv_key Taproot.tweak_private_key(key, merkle_root) end |
#tweak_public_key ⇒ Bitcoin::Key
Compute the tweaked public key.
61 62 63 |
# File 'lib/bitcoin/taproot/simple_builder.rb', line 61 def tweak_public_key Taproot.tweak_public_key(Bitcoin::Key.from_xonly_pubkey(internal_key), merkle_root) end |