Skip to content

Instantly share code, notes, and snippets.

@pierrenoizat
Last active November 15, 2020 09:51
Show Gist options
  • Save pierrenoizat/6880a12a599fa03a2099e3b38e8664e0 to your computer and use it in GitHub Desktop.
Save pierrenoizat/6880a12a599fa03a2099e3b38e8664e0 to your computer and use it in GitHub Desktop.
require 'bitcoin'
require 'money-tree'
require 'bip44'
require 'bech32'
include Bitcoin
include Bitcoin::Builder
include Bitcoin::Protocol
include Bitcoin::Util
include Bitcoin::Secp256k1
include Bech32
base_factor = 100000000
mnemonic = "beyond .. satoshi" # enter your own passphrase here
seed = BipMnemonic.to_seed(mnemonic: mnemonic)
@btc_wallet = Bip44::Wallet.from_seed(seed, "m/44'/0")
@btc_node = @btc_wallet.sub_wallet "m/0/1"
alice_public_key = Key.new(nil,@btc_node.public_key).pub
@btc_node = @btc_wallet.sub_wallet "m/0/2"
bob_public_key = Key.new(nil,@btc_node.public_key).pub_compressed
@btc_node = @btc_wallet.sub_wallet "m/0/3"
escrow_public_key = Key.new(nil,@btc_node.public_key).pub_compressed
# Creation of Witness Script: here a 2-of-2 multisig as an example
witness_script_string = "2 #{bob_public_key} #{escrow_public_key} 2 OP_CHECKMULTISIG"
witness_script = Script.from_string(witness_script_string).to_payload
# Calculation of Native P2WSH Address:
script_pubkey = Script.to_witness_p2sh_script(sha256(witness_script.bth))
native_p2wsh_address = SegwitAddr.new
native_p2wsh_address.hrp = 'bc' # hrp = human-readable part
native_p2wsh_address.script_pubkey = script_pubkey.bth
puts "\n Native P2WSH Address: #{native_p2wsh_address.addr} \n\n"
# Native P2WSH Address: bc1qxfet744v05jfc3ks7gf4pguyjjfqcfvtsjvxkwa7emgvv4990arq3rwz2v
# Transaction funding Native P2WSH Address:
@btc_node = @btc_wallet.sub_wallet "m/0/1"
puts Key.new(nil,@btc_node.public_key).addr # standard (legacy) uncompressed address
destination_address = "bc1qxfet744v05jfc3ks7gf4pguyjjfqcfvtsjvxkwa7emgvv4990arq3rwz2v"
utxo_txid = "2a0b545e58fa1d799fedf90488663f8b7cd74ef827fd65b202f37a394f28fb7e"
utxo_index = 1
amount = 0.00072387 * base_factor
fee = 0.0001 * base_factor
sent_amount = amount - fee
script_pubkey = Script.to_hash160_script(hash160(alice_public_key)) # to spend a standard utxo
tx = build_tx do |t|
t.input do |i|
i.prev_out utxo_txid
i.prev_out_index utxo_index
end
t.output do |o|
o.value sent_amount
o.script {|s| s.recipient destination_address }
end
end
tx.to_payload.bth # unsigned tx
sig_hash = tx.signature_hash_for_input(0, script_pubkey)
sig = Secp256k1.sign(sig_hash, @btc_node.private_key.htb)
tx.in[0].script_sig = Script.to_signature_pubkey_script(sig, alice_public_key.htb)
puts tx.to_payload.unpack('H*')[0] # signed tx (in hex)
puts tx.hash
# Transaction spending from P2WSH
utxo_txid = "cc432fa044a0ceeb48905be54bcd813ab5ac2e4b41c4a50493fedc8053831c0b"
utxo_index = 1
amount = 0.00074434 * base_factor
fee = 0.0001 * base_factor
sent_amount = amount - fee
destination_address = "12qeTKzrK7wm1V8rCjYEysAdtD5D3PxfPV"
script_pubkey = Script.to_witness_p2sh_script(sha256(witness_script.bth))
spend_tx = build_tx do |t|
t.lock_time 0
t.input do |i|
i.prev_out utxo_txid, utxo_index, script_pubkey, amount
i.sequence "ffffffff".htb
end
t.output do |o|
o.value sent_amount
o.script {|s| s.recipient destination_address }
end
end
tx = Tx.new(spend_tx.to_payload) # initial (unsigned) transaction
sig_hash = tx.signature_hash_for_witness_input(0, script_pubkey, amount, witness_script, Tx::SIGHASH_TYPE[:all])
@btc_node = @btc_wallet.sub_wallet "m/0/2"
bob_sig = Secp256k1.sign(sig_hash, @btc_node.private_key.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
@btc_node = @btc_wallet.sub_wallet "m/0/3"
escrow_sig = Secp256k1.sign(sig_hash, @btc_node.private_key.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
tx.in[0].script_witness.stack << '' # init stack
tx.in[0].script_witness.stack << bob_sig
tx.in[0].script_witness.stack << escrow_sig
tx.in[0].script_witness.stack << witness_script
tx.to_witness_payload.bth
# sample tx id = "e097a3bad35d7e27adc9e770ea178bfb44e4a83d86421d3a69fb671844d878e9"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment