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]