lib/bitcoin/script.rb in bitcoin-ruby-0.0.18 vs lib/bitcoin/script.rb in bitcoin-ruby-0.0.19

- old
+ new

@@ -159,13 +159,17 @@ }.freeze attr_reader :raw, :chunks, :debug, :stack # create a new script. +bytes+ is typically input_script + output_script + def initialize(input_script, previous_output_script=nil) @raw_byte_sizes = [input_script.bytesize, previous_output_script ? previous_output_script.bytesize : 0] @input_script, @previous_output_script = input_script, previous_output_script + @parse_invalid = nil + @inner_p2sh = nil + @script_codeseparator_index = nil @raw = if @previous_output_script @input_script + [ Bitcoin::Script::OP_CODESEPARATOR ].pack("C") + @previous_output_script else @input_script @@ -256,11 +260,11 @@ def to_string(chunks=nil) string = "" (chunks || @chunks).each.with_index{|i,idx| string << " " unless idx == 0 string << case i - when Fixnum + when Bitcoin::Integer if opcode = OPCODES_PARSE_BINARY[i] opcode else "(opcode-#{i})" end @@ -274,13 +278,14 @@ } string end def to_binary(chunks=nil) + (chunks || @chunks).map{|chunk| case chunk - when Fixnum; [chunk].pack("C*") + when Bitcoin::Integer; [chunk].pack("C*") when String; self.class.pack_pushdata(chunk) end }.join end alias :to_payload :to_binary @@ -315,11 +320,11 @@ end # Adds opcode (OP_0, OP_1, ... OP_CHECKSIG etc.) # Returns self. def append_opcode(opcode) - raise "Opcode should be a Fixnum" if !opcode.is_a?(Fixnum) + raise "Opcode should be an integer" if !opcode.is_a?(Bitcoin::Integer) if opcode >= OP_0 && opcode <= 0xff @chunks << opcode else raise "Opcode should be within [0x00, 0xff]" end @@ -415,11 +420,11 @@ data = [i].pack("H*") pack_pushdata(data) end end - buf << if i.is_a?(Fixnum) + buf << if i.is_a?(Bitcoin::Integer) i < 256 ? [i].pack("C") : [OpenSSL::BN.new(i.to_s,10).to_hex].pack("H*") else i end if i } @@ -450,11 +455,11 @@ @debug << @stack.map{|i| i.unpack("H*") rescue i} @do_exec = @exec_stack.count(false) == 0 ? true : false #p [@stack, @do_exec] case chunk - when Fixnum + when Bitcoin::Integer if DISABLED_OPCODES.include?(chunk) @script_invalid = true @debug << "DISABLED_#{OPCODES[chunk]}" break end @@ -548,11 +553,12 @@ script end # is this a :script_hash (pay-to-script-hash/p2sh) script? def is_pay_to_script_hash? - return false if @inner_p2sh + @inner_p2sh ||= false + return false if @inner_p2sh if @previous_output_script chunks = Bitcoin::Script.new(@previous_output_script).chunks chunks.size == 3 && chunks[-3] == OP_HASH160 && chunks[-2].is_a?(String) && chunks[-2].bytesize == 20 && @@ -588,11 +594,11 @@ @chunks[2].is_a?(String) && @chunks[2].bytesize == 20 end # is this a multisig script def is_multisig? - return false if @chunks.size < 4 || !@chunks[-2].is_a?(Fixnum) + return false if @chunks.size < 4 || !@chunks[-2].is_a?(Bitcoin::Integer) @chunks[-1] == OP_CHECKMULTISIG and get_multisig_pubkeys.all?{|c| c.is_a?(String) } end # is this an op_return script def is_op_return? @@ -614,16 +620,16 @@ is_witness? && @chunks[0] == 0 && @chunks[1].bytesize == 32 end # Verify the script is only pushing data onto the stack def is_push_only?(script_data=nil) - check_pushes(push_only=true, canonical_only=false, (script_data||@input_script)) + check_pushes(true, false, (script_data||@input_script)) end # Make sure opcodes used to push data match their intended length ranges def pushes_are_canonical?(script_data=nil) - check_pushes(push_only=false, canonical_only=true, (script_data||@raw)) + check_pushes(false, true, (script_data||@raw)) end def check_pushes(push_only=true, canonical_only=false, buf) program = buf.unpack("C*") until program.empty? @@ -928,11 +934,11 @@ if chunk == OP_CHECKSIG || chunk == OP_CHECKSIGVERIFY count += 1 elsif chunk == OP_CHECKMULTISIG || chunk == OP_CHECKMULTISIGVERIFY # Accurate mode counts exact number of pubkeys required (not signatures, but pubkeys!). Only used in P2SH scripts. # Inaccurate mode counts every multisig as 20 signatures. - if is_accurate && last_opcode && last_opcode.is_a?(Fixnum) && last_opcode >= OP_1 && last_opcode <= OP_16 + if is_accurate && last_opcode && last_opcode.is_a?(Bitcoin::Integer) && last_opcode >= OP_1 && last_opcode <= OP_16 count += ::Bitcoin::Script.decode_OP_N(last_opcode) else count += 20 end end @@ -954,11 +960,11 @@ return 0 if @chunks.size == 0 data = nil @chunks.each do |chunk| case chunk - when Fixnum + when Bitcoin::Integer data = "" return 0 if chunk > OP_16 when String data = chunk end @@ -972,11 +978,11 @@ # Returns nil for other opcodes. def self.decode_OP_N(opcode) if opcode == OP_0 return 0 end - if opcode.is_a?(Fixnum) && opcode >= OP_1 && opcode <= OP_16 + if opcode.is_a?(Bitcoin::Integer) && opcode >= OP_1 && opcode <= OP_16 return opcode - (OP_1 - 1); else nil end end @@ -1529,14 +1535,9 @@ # Same as OP_CHECKMULTISIG, but OP_VERIFY is executed afterward. def op_checkmultisigverify(check_callback, opts={}) op_checkmultisig(check_callback, opts) op_verify - end - - # op_eval: https://en.bitcoin.it/wiki/BIP_0012 - # the BIP was never accepted and must be handled as old OP_NOP1 - def op_nop1 end OPCODES_METHOD = Hash[*instance_methods.grep(/^op_/).map{|m| [ (OPCODES.find{|k,v| v == m.to_s.upcase }.first rescue nil), m ] }.flatten]