Module: Bitcoin::Descriptor
- Includes:
- Opcodes
- Defined in:
- lib/bitcoin/descriptor.rb,
lib/bitcoin/descriptor/pk.rb,
lib/bitcoin/descriptor/sh.rb,
lib/bitcoin/descriptor/tr.rb,
lib/bitcoin/descriptor/pkh.rb,
lib/bitcoin/descriptor/raw.rb,
lib/bitcoin/descriptor/wsh.rb,
lib/bitcoin/descriptor/addr.rb,
lib/bitcoin/descriptor/wpkh.rb,
lib/bitcoin/descriptor/combo.rb,
lib/bitcoin/descriptor/multi.rb,
lib/bitcoin/descriptor/musig.rb,
lib/bitcoin/descriptor/raw_tr.rb,
lib/bitcoin/descriptor/multi_a.rb,
lib/bitcoin/descriptor/checksum.rb,
lib/bitcoin/descriptor/expression.rb,
lib/bitcoin/descriptor/sorted_multi.rb,
lib/bitcoin/descriptor/key_expression.rb,
lib/bitcoin/descriptor/sorted_multi_a.rb,
lib/bitcoin/descriptor/script_expression.rb
Defined Under Namespace
Modules: Checksum Classes: Addr, Combo, Expression, KeyExpression, MuSig, Multi, MultiA, Pk, Pkh, Raw, RawTr, ScriptExpression, Sh, SortedMulti, SortedMultiA, Tr, Wpkh, Wsh
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
Class Method Summary collapse
-
.addr(addr) ⇒ Bitcoin::Descriptor::Addr
Generate addr() descriptor.
-
.combo(key) ⇒ Bitcoin::Descriptor::Combo
Generate combo() descriptor.
-
.multi(threshold, *keys) ⇒ Bitcoin::Descriptor::Multi
Generate multi() descriptor.
-
.multi_a(threshold, *keys) ⇒ Bitcoin::Descriptor::MultiA
Generate multi_a() descriptor.
-
.musig(*keys, path: nil) ⇒ Bitcoin::Descriptor::MuSig
Generate musig() descriptor.
-
.parse(string, top_level = true) ⇒ Bitcoin::Descriptor::Expression
Parse descriptor string.
- .parse_nested_string(string) ⇒ Object
-
.pk(key) ⇒ Bitcoin::Descriptor::Pk
Generate pk() descriptor.
-
.pkh(key) ⇒ Bitcoin::Descriptor::Pkh
Generate pkh() descriptor.
-
.raw(hex) ⇒ Bitcoin::Descriptor::Raw
Generate raw() descriptor.
-
.rawtr(key) ⇒ Bitcoin::Descriptor::RawTr
Generate rawtr() descriptor.
-
.sh(exp) ⇒ Bitcoin::Descriptor::Sh
Generate sh() descriptor.
-
.sortedmulti(threshold, *keys) ⇒ Bitcoin::Descriptor::SortedMulti
Generate sortedmulti() descriptor.
-
.sortedmulti_a(threshold, *keys) ⇒ Bitcoin::Descriptor::SortedMulti
Generate sortedmulti_a() descriptor.
- .split_two(content) ⇒ Object
-
.tr(key, tree = nil) ⇒ Bitcoin::Descriptor::Tr
Generate tr() descriptor.
-
.validate_checksum!(descriptor) ⇒ Object
Validate descriptor checksum.
-
.wpkh(key) ⇒ Bitcoin::Descriptor::Wpkh
Generate wpkh() descriptor.
-
.wsh(exp) ⇒ Bitcoin::Descriptor::Wsh
Generate wsh() descriptor.
Methods included from Opcodes
defined?, name_to_opcode, op_success?, opcode_to_name, opcode_to_small_int, small_int_to_opcode
Class Method Details
.addr(addr) ⇒ Bitcoin::Descriptor::Addr
Generate addr() descriptor.
97 98 99 |
# File 'lib/bitcoin/descriptor.rb', line 97 def addr(addr) Addr.new(addr) end |
.combo(key) ⇒ Bitcoin::Descriptor::Combo
Generate combo() descriptor. If the key is compressed, it also includes ‘wpkh(KEY)` and `sh(wpkh(KEY))`.
67 68 69 |
# File 'lib/bitcoin/descriptor.rb', line 67 def combo(key) Combo.new(key) end |
.multi(threshold, *keys) ⇒ Bitcoin::Descriptor::Multi
Generate multi() descriptor.
75 76 77 |
# File 'lib/bitcoin/descriptor.rb', line 75 def multi(threshold, *keys) Multi.new(threshold, keys) end |
.multi_a(threshold, *keys) ⇒ Bitcoin::Descriptor::MultiA
Generate multi_a() descriptor.
120 121 122 |
# File 'lib/bitcoin/descriptor.rb', line 120 def multi_a(threshold, *keys) MultiA.new(threshold, keys) end |
.musig(*keys, path: nil) ⇒ Bitcoin::Descriptor::MuSig
Generate musig() descriptor.
136 137 138 |
# File 'lib/bitcoin/descriptor.rb', line 136 def musig(*keys, path: nil) MuSig.new(keys, path) end |
.parse(string, top_level = true) ⇒ Bitcoin::Descriptor::Expression
Parse descriptor string.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/bitcoin/descriptor.rb', line 143 def parse(string, top_level = true) validate_checksum!(string) content, _ = string.split('#') exp, args_str, path = content.match(/(\w+)\((.+)\)(.*)/).captures # split "tag(10, 20)/0/1" raise ArgumentError, 'Invalid format.' if exp != 'musig' && !path.empty? case exp when 'pk' if args_str.include?('(') pk(parse(args_str)) else pk(args_str) end when 'pkh' pkh(args_str) when 'wpkh' wpkh(args_str) when 'sh' sh(parse(args_str, false)) when 'wsh' wsh(parse(args_str, false)) when 'combo' combo(args_str) when 'multi', 'sortedmulti', 'multi_a', 'sortedmulti_a' args = args_str.split(',') threshold = args[0].to_i keys = args[1..-1] case exp when 'multi' multi(threshold, *keys) when 'sortedmulti' sortedmulti(threshold, *keys) when 'multi_a' raise ArgumentError, "Can only have multi_a/sortedmulti_a inside tr()." if top_level multi_a(threshold, *keys) when 'sortedmulti_a' raise ArgumentError, "Can only have multi_a/sortedmulti_a inside tr()." if top_level sortedmulti_a(threshold, *keys) end when 'raw' raw(args_str) when 'addr' addr(args_str) when 'tr' key, tree = split_two(args_str) key = parse(key) if key.include?('(') if tree.nil? tr(key) elsif tree.start_with?('{') tr(key, parse_nested_string(tree)) else tr(key, parse(tree, false)) end when 'rawtr' if args_str.include?('(') rawtr(parse(args_str, false)) else rawtr(args_str) end when 'musig' keys = args_str.split(',') path.empty? ? musig(*keys) : musig(*keys, path: path) else raise ArgumentError, "Parse failed: #{string}" end end |
.parse_nested_string(string) ⇒ Object
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/bitcoin/descriptor.rb', line 225 def parse_nested_string(string) return nil if string.nil? stack = [] current = [] buffer = "" string.each_char do |c| case c when '{' stack << current current = [] when '}' unless buffer.empty? current << parse(buffer, false) buffer = "" end nested = current current = stack.pop current << nested when ',' unless buffer.empty? current << parse(buffer, false) buffer = "" end else buffer << c end end current << parse(buffer, false) unless buffer.empty? current.first end |
.pk(key) ⇒ Bitcoin::Descriptor::Pk
Generate pk() descriptor.
31 32 33 |
# File 'lib/bitcoin/descriptor.rb', line 31 def pk(key) Pk.new(key) end |
.pkh(key) ⇒ Bitcoin::Descriptor::Pkh
Generate pkh() descriptor.
38 39 40 |
# File 'lib/bitcoin/descriptor.rb', line 38 def pkh(key) Pkh.new(key) end |
.raw(hex) ⇒ Bitcoin::Descriptor::Raw
Generate raw() descriptor.
90 91 92 |
# File 'lib/bitcoin/descriptor.rb', line 90 def raw(hex) Raw.new(hex) end |
.rawtr(key) ⇒ Bitcoin::Descriptor::RawTr
Generate rawtr() descriptor.
112 113 114 |
# File 'lib/bitcoin/descriptor.rb', line 112 def rawtr(key) RawTr.new(key) end |
.sh(exp) ⇒ Bitcoin::Descriptor::Sh
Generate sh() descriptor.
52 53 54 |
# File 'lib/bitcoin/descriptor.rb', line 52 def sh(exp) Sh.new(exp) end |
.sortedmulti(threshold, *keys) ⇒ Bitcoin::Descriptor::SortedMulti
Generate sortedmulti() descriptor.
83 84 85 |
# File 'lib/bitcoin/descriptor.rb', line 83 def sortedmulti(threshold, *keys) SortedMulti.new(threshold, keys) end |
.sortedmulti_a(threshold, *keys) ⇒ Bitcoin::Descriptor::SortedMulti
Generate sortedmulti_a() descriptor.
128 129 130 |
# File 'lib/bitcoin/descriptor.rb', line 128 def sortedmulti_a(threshold, *keys) SortedMultiA.new(threshold, keys) end |
.split_two(content) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/bitcoin/descriptor.rb', line 256 def split_two(content) paren_depth = 0 split_pos = content.chars.find_index do |char| case char when '(' then paren_depth += 1; false when ')' then paren_depth -= 1; false when ',' then paren_depth == 0 else false end end if split_pos [content[0...split_pos], content[split_pos+1..-1]] else [content, nil] end end |
.tr(key, tree = nil) ⇒ Bitcoin::Descriptor::Tr
Generate tr() descriptor.
105 106 107 |
# File 'lib/bitcoin/descriptor.rb', line 105 def tr(key, tree = nil) Tr.new(key, tree) end |
.validate_checksum!(descriptor) ⇒ Object
Validate descriptor checksum.
212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/bitcoin/descriptor.rb', line 212 def validate_checksum!(descriptor) return unless descriptor.include?("#") content, *checksums = descriptor.split("#") raise ArgumentError, "Multiple '#' symbols." if checksums.length > 1 checksum = checksums.first len = checksum.nil? ? 0 : checksum.length raise ArgumentError, "Expected 8 character checksum, not #{len} characters." unless len == 8 _, calc_checksum = Checksum.descsum_create(content).split('#') unless calc_checksum == checksum raise ArgumentError, "Provided checksum '#{checksum}' does not match computed checksum '#{calc_checksum}'." end end |
.wpkh(key) ⇒ Bitcoin::Descriptor::Wpkh
Generate wpkh() descriptor.
45 46 47 |
# File 'lib/bitcoin/descriptor.rb', line 45 def wpkh(key) Wpkh.new(key) end |
.wsh(exp) ⇒ Bitcoin::Descriptor::Wsh
Generate wsh() descriptor.
59 60 61 |
# File 'lib/bitcoin/descriptor.rb', line 59 def wsh(exp) Wsh.new(exp) end |