class Bitcoin::SigHashGenerator::SchnorrSigHashGenerator
v1 witness sighash generator see: github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
Public Instance Methods
generate(tx, input_index, hash_type, opts)
click to toggle source
generate signature hash for taproot and tapscript @param [Hash] opts some data using signature. This class requires following key params:
-
sig_version: sig version. :taproot or :tapscript
-
prevouts: array of all prevout
-
annex: annex value with binary format if annex exist.
-
leaf_hash: leaf hash with binary format if sig_version is :tapscript, it required
-
last_code_separator_pos: the position of last code separator
@return [String] signature hash with binary format.
# File lib/bitcoin/sighash_generator.rb, line 107 def generate(tx, input_index, hash_type, opts) raise ArgumentError, 'Invalid sig_version was specified.' unless [:taproot, :tapscript].include?(opts[:sig_version]) ext_flag = opts[:sig_version] == :taproot ? 0 : 1 key_version = 0 output_ype = hash_type == SIGHASH_TYPE[:default] ? SIGHASH_TYPE[:all] : (hash_type & 0x03) input_type = hash_type & 0x80 epoc = '00'.htb buf = epoc # EPOC buf << [hash_type, tx.version, tx.lock_time].pack('CVV') unless input_type == SIGHASH_TYPE[:anyonecanpay] buf << Bitcoin.sha256(tx.in.map{|i|i.out_point.to_payload}.join) # sha_prevouts buf << Bitcoin.sha256(opts[:prevouts].map(&:value).pack('Q*'))# sha_amounts buf << Bitcoin.sha256(opts[:prevouts].map{|o|o.script_pubkey.to_payload(true)}.join) # sha_scriptpubkeys buf << Bitcoin.sha256(tx.in.map(&:sequence).pack('V*')) # sha_sequences end buf << Bitcoin.sha256(tx.out.map(&:to_payload).join) if output_ype == SIGHASH_TYPE[:all] spend_type = (ext_flag << 1) + (opts[:annex] ? 1 : 0) buf << [spend_type].pack('C') if input_type == SIGHASH_TYPE[:anyonecanpay] buf << tx.in[input_index].out_point.to_payload buf << opts[:prevouts][input_index].to_payload buf << [tx.in[input_index].sequence].pack('V') else buf << [input_index].pack('V') end buf << Bitcoin.sha256(Bitcoin.pack_var_string(opts[:annex])) if opts[:annex] if output_ype == SIGHASH_TYPE[:single] raise ArgumentError, "Tx does not have #{input_index} th output." if input_index >= tx.out.size buf << Bitcoin.sha256(tx.out[input_index].to_payload) end if opts[:sig_version] == :tapscript buf << opts[:leaf_hash] buf << [key_version, opts[:last_code_separator_pos]].pack("CV") end Bitcoin.tagged_hash('TapSighash', buf) end