Class: Bitcoin::SigHashGenerator::SegwitSigHashGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin/sighash_generator.rb

Overview

V0 witness sighash generator. see: github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

Instance Method Summary collapse

Instance Method Details

#generate(tx, input_index, hash_type, opts) ⇒ Object

Raises:

  • (ArgumentError)


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/bitcoin/sighash_generator.rb', line 63

def generate(tx, input_index, hash_type, opts)
  amount = opts[:amount]
  raise ArgumentError, 'segwit sighash requires amount.' unless amount
  output_script = opts[:script_code]
  skip_separator_index = opts[:skip_separator_index]
  hash_prevouts = Bitcoin.double_sha256(tx.inputs.map{|i|i.out_point.to_payload}.join)
  hash_sequence = Bitcoin.double_sha256(tx.inputs.map{|i|[i.sequence].pack('V')}.join)
  outpoint = tx.inputs[input_index].out_point.to_payload
  amount = [amount].pack('Q')
  nsequence = [tx.inputs[input_index].sequence].pack('V')
  hash_outputs = Bitcoin.double_sha256(tx.outputs.map{|o|o.to_payload}.join)
  if output_script.p2wsh?
    warn('The output_script must be a witness script, not the P2WSH itself.')
  end
  script_code = output_script.to_script_code(skip_separator_index)

  case (hash_type & 0x1f)
  when SIGHASH_TYPE[:single]
    hash_outputs = input_index >= tx.outputs.size ? "\x00".ljust(32, "\x00") : Bitcoin.double_sha256(tx.outputs[input_index].to_payload)
    hash_sequence = "\x00".ljust(32, "\x00")
  when SIGHASH_TYPE[:none]
    hash_sequence = hash_outputs = "\x00".ljust(32, "\x00")
  end

  unless (hash_type & SIGHASH_TYPE[:anyonecanpay]) == 0
    hash_prevouts = hash_sequence ="\x00".ljust(32, "\x00")
  end

  buf = [ [tx.version].pack('V'), hash_prevouts, hash_sequence, outpoint,
          script_code ,amount, nsequence, hash_outputs, [tx.lock_time, hash_type].pack('VV')].join
  Bitcoin.double_sha256(buf)
end