Module: Bitcoin::Multisig
- Includes:
- Opcodes
- Defined in:
- lib/bitcoin/script/multisig.rb
Overview
utility for multisig
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
-
.add_sig_to_multisig_script_sig(sig_to_add, script_sig, hash_type = ) ⇒ Object
take a multisig script sig (or p2sh multisig script sig) and add another signature to it after the OP_0.
- .add_sig_to_multisig_script_witness(sig_to_add, script_witness, hash_type = ) ⇒ Object
- .prefix ⇒ Object
-
.sort_p2sh_multisig_signatures(script_sig, sig_hash) ⇒ String
Sort signatures in the given
script_sig
according to the order of pubkeys in the redeem script. -
.sort_witness_multisig_signatures(script_witness, sig_hash) ⇒ Object
Sort signatures in the given
script_witness
according to the order of pubkeys in the redeem script. -
.to_multisig_script_sig(*sigs) ⇒ String
generate input script sig spending a multisig output script.
-
.to_p2sh_multisig_script_sig(redeem_script, *sigs) ⇒ String
generate input script sig spending a p2sh-multisig output script.
Methods included from Opcodes
defined?, name_to_opcode, op_success?, opcode_to_name, opcode_to_small_int, small_int_to_opcode
Class Method Details
.add_sig_to_multisig_script_sig(sig_to_add, script_sig, hash_type = ) ⇒ Object
take a multisig script sig (or p2sh multisig script sig) and add another signature to it after the OP_0. Used to sign a tx by multiple parties. Signatures must be in the same order as the pubkeys in the output script being redeemed.
25 26 27 28 29 |
# File 'lib/bitcoin/script/multisig.rb', line 25 def self.add_sig_to_multisig_script_sig(sig_to_add, script_sig, hash_type = SIGHASH_TYPE[:all]) signature = sig_to_add + [hash_type].pack("C*") offset = script_sig.empty? ? 0 : 1 script_sig.insert(offset, Bitcoin::Script.pack_pushdata(signature)) end |
.add_sig_to_multisig_script_witness(sig_to_add, script_witness, hash_type = ) ⇒ Object
65 66 67 68 |
# File 'lib/bitcoin/script/multisig.rb', line 65 def self.add_sig_to_multisig_script_witness(sig_to_add, script_witness, hash_type = SIGHASH_TYPE[:all]) signature = sig_to_add + [hash_type].pack("C*") script_witness.stack << signature end |
.prefix ⇒ Object
7 8 9 |
# File 'lib/bitcoin/script/multisig.rb', line 7 def self.prefix [OP_0].pack("C*") end |
.sort_p2sh_multisig_signatures(script_sig, sig_hash) ⇒ String
Sort signatures in the given script_sig
according to the order of pubkeys in the redeem script. Also needs the sig_hash
to match signatures to pubkeys.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/bitcoin/script/multisig.rb', line 46 def self.sort_p2sh_multisig_signatures(script_sig, sig_hash) script = Bitcoin::Script.parse_from_payload(script_sig) redeem_script = Bitcoin::Script.parse_from_payload(script.chunks[-1].pushed_data) pubkeys = redeem_script.get_multisig_pubkeys # find the pubkey for each signature by trying to verify it sigs = Hash[script.chunks[1...-1].map.with_index do |sig, idx| sig = sig.pushed_data pubkey = pubkeys.map do |key| Bitcoin::Key.new(pubkey: key.bth).verify(sig, sig_hash) ? key : nil end.compact.first raise "Key for signature ##{idx} not found in redeem script!" unless pubkey [pubkey, sig] end] prefix + pubkeys.map { |k| sigs[k] ? Bitcoin::Script.pack_pushdata(sigs[k]) : nil }.join + Bitcoin::Script.pack_pushdata(script.chunks[-1].pushed_data) end |
.sort_witness_multisig_signatures(script_witness, sig_hash) ⇒ Object
Sort signatures in the given script_witness
according to the order of pubkeys in the redeem script. Also needs the sig_hash
to match signatures to pubkeys.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/bitcoin/script/multisig.rb', line 74 def self.sort_witness_multisig_signatures(script_witness, sig_hash) redeem_script = Bitcoin::Script.parse_from_payload(script_witness.stack[-1]) pubkeys = redeem_script.get_multisig_pubkeys sigs = Hash[script_witness.stack[1...-1].map.with_index do |sig, idx| pubkey = pubkeys.map do |key| Bitcoin::Key.new(pubkey: key.bth).verify(sig, sig_hash) ? key : nil end.compact.first raise "Key for signature ##{idx} not found in redeem script!" unless pubkey [pubkey, sig] end] script_witness.stack.clear script_witness.stack << '' pubkeys.each do |pubkey| script_witness.stack << sigs[pubkey] if sigs[pubkey] end script_witness.stack << redeem_script.to_payload end |
.to_multisig_script_sig(*sigs) ⇒ String
generate input script sig spending a multisig output script. returns a raw binary script sig of the form:
OP_0 <sig> [<sig> ...]
16 17 18 19 |
# File 'lib/bitcoin/script/multisig.rb', line 16 def self.to_multisig_script_sig(*sigs) hash_type = sigs.last.is_a?(Numeric) ? sigs.pop : SIGHASH_TYPE[:all] sigs.reverse.inject(prefix) { |joined, sig| add_sig_to_multisig_script_sig(sig, joined, hash_type) } end |
.to_p2sh_multisig_script_sig(redeem_script, *sigs) ⇒ String
generate input script sig spending a p2sh-multisig output script. returns a raw binary script sig of the form:
OP_0 <sig> [<sig> ...] <redeem_script>
37 38 39 |
# File 'lib/bitcoin/script/multisig.rb', line 37 def self.to_p2sh_multisig_script_sig(redeem_script, *sigs) to_multisig_script_sig(*sigs.flatten) + Bitcoin::Script.pack_pushdata(redeem_script) end |