lib/bitcoin/script.rb in bitcoin-ruby-0.0.3 vs lib/bitcoin/script.rb in bitcoin-ruby-0.0.4

- old
+ new

@@ -1033,19 +1033,21 @@ # see https://github.com/bitcoin/bitcoin/blob/master/src/script.cpp#L931 # # TODO: validate signature order # TODO: take global opcode count def op_checkmultisig(check_callback) + return invalid if @stack.size < 1 n_pubkeys = pop_int return invalid unless (0..20).include?(n_pubkeys) - return invalid unless @stack.last(n_pubkeys).all?{|e| e.is_a?(String) && e != '' } - #return invalid if ((@op_count ||= 0) += n_pubkeys) > 201 + #return invalid if (nOpCount += n_pubkeys) > 201 + return invalid if @stack.size < n_pubkeys pubkeys = pop_string(n_pubkeys) + return invalid if @stack.size < 1 n_sigs = pop_int - return invalid unless (0..n_pubkeys).include?(n_sigs) - return invalid unless @stack.last(n_sigs).all?{|e| e.is_a?(String) && e != '' } + return invalid if n_sigs < 0 || n_sigs > n_pubkeys + return invalid if @stack.size < n_sigs sigs = drop_sigs = pop_string(n_sigs) @stack.pop if @stack[-1] && cast_to_bignum(@stack[-1]) == 0 # remove OP_0 from stack if inner_p2sh? @@ -1053,17 +1055,23 @@ drop_sigs = nil else script_code, drop_sigs = nil, nil end - valid_sigs = 0 - sigs.each{|sig| pubkeys.each{|pubkey| - next if sig == "" - signature, hash_type = parse_sig(sig) - valid_sigs += 1 if check_callback.call(pubkey, signature, hash_type, drop_sigs, script_code) - }} + success = true + while success && n_sigs > 0 + sig, pub = sigs.pop, pubkeys.pop + signature, hash_type = parse_sig(sig) + if check_callback.call(pub, signature, hash_type, drop_sigs, script_code) + n_sigs -= 1 + else + sigs << sig + end + n_pubkeys -= 1 + success = false if n_sigs > n_pubkeys + end - @stack << ((valid_sigs >= n_sigs) ? 1 : (invalid; 0)) + @stack << (success ? 1 : (invalid; 0)) 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