lib/bitcoin/script.rb in bitcoin-ruby-0.0.10 vs lib/bitcoin/script.rb in bitcoin-ruby-0.0.11
- old
+ new
@@ -295,10 +295,21 @@
end
}
to_binary(buf)
end
+ # Returns a script that deleted the script before the index specified by separator_index.
+ def subscript_codeseparator(separator_index)
+ buf = []
+ process_separator_index = 0
+ (chunks || @chunks).each{|chunk|
+ buf << chunk if process_separator_index == separator_index
+ process_separator_index += 1 if chunk == OP_CODESEPARATOR and process_separator_index < separator_index
+ }
+ to_binary(buf)
+ 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)
if opcode >= OP_0 && opcode <= 0xff
@@ -538,11 +549,11 @@
end
alias :is_p2sh? :is_pay_to_script_hash?
# check if script is in one of the recognized standard formats
def is_standard?
- is_pubkey? || is_hash160? || is_multisig? || is_p2sh? || is_op_return?
+ is_pubkey? || is_hash160? || is_multisig? || is_p2sh? || is_op_return? || is_witness_v0_keyhash? || is_witness_v0_scripthash?
end
# is this a pubkey script
def is_pubkey?
return false if @chunks.size != 2
@@ -567,10 +578,25 @@
# is this an op_return script
def is_op_return?
@chunks[0] == OP_RETURN && @chunks.size <= 2
end
+ # is this a witness script(witness_v0_keyhash or witness_v0_scripthash)
+ def is_witness?
+ is_witness_v0_keyhash? || is_witness_v0_scripthash?
+ end
+
+ # is this a witness pubkey script
+ def is_witness_v0_keyhash?
+ @chunks.length == 2 &&@chunks[0] == 0 && @chunks[1].is_a?(String) && @chunks[1].bytesize == 20
+ end
+
+ # is this a witness script hash
+ def is_witness_v0_scripthash?
+ @chunks.length == 2 &&@chunks[0] == 0 && @chunks[1].is_a?(String) && @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))
end
@@ -610,23 +636,25 @@
return false if canonical_only && len <= 0xffff
program.shift(len)
end
end
true
- rescue => ex
+ rescue
# catch parsing errors
false
end
# get type of this tx
def type
- if is_hash160?; :hash160
- elsif is_pubkey?; :pubkey
- elsif is_multisig?; :multisig
- elsif is_p2sh?; :p2sh
- elsif is_op_return?;:op_return
- else; :unknown
+ if is_hash160?; :hash160
+ elsif is_pubkey?; :pubkey
+ elsif is_multisig?; :multisig
+ elsif is_p2sh?; :p2sh
+ elsif is_op_return?; :op_return
+ elsif is_witness_v0_keyhash?; :witness_v0_keyhash
+ elsif is_witness_v0_scripthash?;:witness_v0_scripthash
+ else; :unknown
end
end
# get the public key for this pubkey script
def get_pubkey
@@ -642,10 +670,12 @@
# get the hash160 for this hash160 or pubkey script
def get_hash160
return @chunks[2..-3][0].unpack("H*")[0] if is_hash160?
return @chunks[-2].unpack("H*")[0] if is_p2sh?
return Bitcoin.hash160(get_pubkey) if is_pubkey?
+ return @chunks[1].unpack("H*")[0] if is_witness_v0_keyhash?
+ return @chunks[1].unpack("H*")[0] if is_witness_v0_scripthash?
end
# get the hash160 address for this hash160 script
def get_hash160_address
Bitcoin.hash160_to_address(get_hash160)
@@ -711,10 +741,26 @@
return nil unless p2sh
# HASH160 length hash EQUAL
[ ["a9", "14", p2sh, "87"].join ].pack("H*")
end
+ # generate p2wpkh tx for given +address+. returns a raw binary script of the form:
+ # 0 <hash160>
+ def self.to_witness_hash160_script(hash160)
+ return nil unless hash160
+ # witness ver length hash160
+ [ ["00", "14", hash160].join ].pack("H*")
+ end
+
+ # generate p2wsh output script for given +p2sh+ sha256. returns a raw binary script of the form:
+ # 0 <p2sh>
+ def self.to_witness_p2sh_script(p2sh)
+ return nil unless p2sh
+ # witness ver length sha256
+ [ [ "00", "20", p2sh].join].pack("H*")
+ end
+
# generate hash160 or p2sh output script, depending on the type of the given +address+.
# see #to_hash160_script and #to_p2sh_script.
def self.to_address_script(address)
hash160 = Bitcoin.hash160_from_address(address)
case Bitcoin.address_type(address)
@@ -828,9 +874,13 @@
end
def get_keys_provided
return false unless is_multisig?
@chunks[-2] - 80
+ end
+
+ def codeseparator_count
+ @chunks.select{|c|c == Bitcoin::Script::OP_CODESEPARATOR}.length
end
# This matches CScript::GetSigOpCount(bool fAccurate)
# Note: this does not cover P2SH script which is to be unserialized
# and checked explicitly when validating blocks.