lib/bitcoin/builder.rb in bitcoin-ruby-0.0.14 vs lib/bitcoin/builder.rb in bitcoin-ruby-0.0.15
- old
+ new
@@ -235,11 +235,11 @@
@tx.in[i].sig_hash = @sig_hash
# add the address the sig_hash needs to be signed with as a convenience for the signing device
@tx.in[i].sig_address = Script.new(@prev_script).get_address if @prev_script
end
- def get_script_sig(inc)
+ def get_script_sig(inc, hash_type)
if inc.has_multiple_keys?
# multiple keys given, generate signature for each one
sigs = inc.sign(@sig_hash)
if redeem_script = inc.instance_eval { @redeem_script }
# when a redeem_script was specified, assume we spend a p2sh multisig script
@@ -249,11 +249,11 @@
script_sig = Script.to_multisig_script_sig(*sigs)
end
else
# only one key given, generate signature and script_sig
sig = inc.sign(@sig_hash)
- script_sig = Script.to_signature_pubkey_script(sig, [inc.key.pub].pack("H*"))
+ script_sig = Script.to_signature_pubkey_script(sig, [inc.key.pub].pack("H*"), hash_type)
end
return script_sig
end
# Sign input number +i+ with data from given +inc+ object (a TxInBuilder).
@@ -266,31 +266,48 @@
# get the signature script; use +redeem_script+ if given
# (indicates spending a p2sh output), otherwise use the prev_script
sig_script = inc.instance_eval { @redeem_script }
sig_script ||= @prev_script
+ hash_type = if inc.prev_out_forkid
+ Script::SIGHASH_TYPE[:all] | Script::SIGHASH_TYPE[:forkid]
+ else
+ Script::SIGHASH_TYPE[:all]
+ end
+
# when a sig_script was found, generate the sig_hash to be signed
if sig_script
script = Script.new(sig_script)
if script.is_witness_v0_keyhash?
@sig_hash = @tx.signature_hash_for_witness_input(i, sig_script, inc.value)
else
- @sig_hash = @tx.signature_hash_for_input(i, sig_script)
+ @sig_hash = if inc.prev_out_forkid
+ @tx.signature_hash_for_input(
+ i,
+ sig_script,
+ hash_type,
+ inc.value,
+ inc.prev_out_forkid)
+ else
+ @tx.signature_hash_for_input(i, sig_script)
+ end
end
end
# when there is a sig_hash and one or more signature_keys were specified
if sig_hash_and_all_keys_exist?(inc, sig_script)
# add the script_sig to the txin
if script.is_witness_v0_keyhash? # for p2wpkh
@tx.in[i].script_witness.stack << inc.sign(@sig_hash) + [Script::SIGHASH_TYPE[:all]].pack("C")
@tx.in[i].script_witness.stack << inc.key.pub.htb
else
- @tx.in[i].script_sig = get_script_sig(inc)
+ @tx.in[i].script_sig = get_script_sig(inc, hash_type)
end
# double-check that the script_sig is valid to spend the given prev_script
- raise "Signature error" if @prev_script && !@tx.verify_input_signature(i, @prev_script)
+ if @prev_script && !inc.prev_out_forkid && !@tx.verify_input_signature(i, @prev_script)
+ raise "Signature error"
+ end
elsif inc.has_multiple_keys?
raise "Keys missing for multisig signing"
else
# no sig_hash, add an empty script_sig.
add_empty_script_sig_to_input(i)
@@ -327,11 +344,11 @@
# i.redeem_script prev_out.redeem_script
# end
#
# If you want to spend a multisig output, just provide an array of keys to #signature_key.
class TxInBuilder
- attr_reader :prev_tx, :prev_script, :redeem_script, :key, :coinbase_data, :prev_out_value
+ attr_reader :prev_tx, :prev_script, :redeem_script, :key, :coinbase_data, :prev_out_value, :prev_out_forkid
def initialize
@txin = P::TxIn.new
@prev_out_hash = "\x00" * 32
@prev_out_index = 0
@@ -339,10 +356,11 @@
# Previous transaction that contains the output we want to use.
# You can either pass the transaction, or just the tx hash.
# If you pass only the hash, you need to pass the previous outputs
# +script+ separately if you want the txin to be signed.
- def prev_out tx, idx = nil, script = nil, prev_value = nil
+ def prev_out tx, idx = nil, script = nil, prev_value = nil, prev_forkid = nil
+ @prev_out_forkid = prev_forkid
if tx.is_a?(Bitcoin::P::Tx)
@prev_tx = tx
@prev_out_hash = tx.binary_hash
@prev_out_script = tx.out[idx].pk_script if idx
else