Skip to content

Instantly share code, notes, and snippets.

@secdev02
Created September 24, 2024 15:22
Show Gist options
  • Save secdev02/a6ccfe23a6098205ac7d960839207197 to your computer and use it in GitHub Desktop.
Save secdev02/a6ccfe23a6098205ac7d960839207197 to your computer and use it in GitHub Desktop.
Generate a P2SH-P2WSH address, create a tx spending from it.
require 'btcruby'
require 'bitcoin'
require 'active_support'
require 'active_support/core_ext'
require 'ffi'
# Creation of Witness Script: here a 2-of-2 multisig as an example
@public_key = "02530c548d402670b13ad8887ff99c294e67fc18097d236d57880c69261b42def7"
@user_key = BTC::Key.new(public_key:BTC.from_hex(@public_key))
@escrow_key = BTC::Key.new(public_key:BTC.from_hex("024fffe85607b555cf7697e4be0d3d34dc1868baa57c235d926e447e926c08d287"))
witness_script = BTC::Script.new << BTC::Script::OP_2 << @user_key.compressed_public_key << @escrow_key.compressed_public_key << BTC::Script::OP_2
witness_script << BTC::Script::OP_CHECKMULTISIG
@witness_script = witness_script.data
redeem_script = BTC::Script.new
redeem_script<< BTC::Script::OP_0
redeem_script<< BTC.sha256(@witness_script)
# Computation of P2SH-P2WPKH address
p2sh_p2wsh_address = BTC::ScriptHashAddress.new(redeem_script:redeem_script).to_s # exemple: 34c48TmtAUSpPZS5X1X8USNAUSWvZau6zn
# Transaction spending from P2SH-P2WPKH address
include Bitcoin::Builder
include Bitcoin::Protocol
include Bitcoin::Secp256k1
@destination_address = "1Bwyn5f5EvUPazh3H2rns6ENjTUYnK9ben"
user_key = Bitcoin.open_key("25940ed...f7b2d9") # <- privkey in hex
escrow_key = Bitcoin.open_key("4b5b5e...975c")
prev_out="4922998c3a2f741a64c85f2bce7367485ff25495dfd349e3ae60e5265ed6381d"
prev_out_index = 0
value = 100000
fee = 15000
witness_script = Bitcoin::Script.new(@witness_script)
@redeem_script = redeem_script.data
spend_tx = build_tx do |t|
t.lock_time 0
t.input do |i|
i.prev_out prev_out, prev_out_index, @redeem_script, value
i.sequence "ffffffff".htb
end
t.output do |o|
o.value value-fee
o.script {|s| s.recipient @destination_address }
end
end
tx = Tx.new(spend_tx.to_payload) # yet unsigned tx
tx.in[0].script_sig = Bitcoin::Script.new(Bitcoin::Script.pack_pushdata(@redeem_script)).to_payload
tx.in[0].script_witness.stack << ''
sig_hash = tx.signature_hash_for_witness_input(0, @redeem_script, value, witness_script.to_payload, Tx::SIGHASH_TYPE[:all])
sig0 = Bitcoin::Secp256k1.sign(sig_hash, user_key.private_key.to_hex.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
tx.in[0].script_witness.stack << sig0
sig1 = Bitcoin::Secp256k1.sign(sig_hash, escrow_key.private_key.to_hex.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
tx.in[0].script_witness.stack << sig1
tx.in[0].script_witness.stack << witness_script.to_payload
tx.to_witness_payload.bth
# tx id: 718b84ed26a1178efc61b6b500d775df6392fb91816c2e7a48b9d018d66159c4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment