spec/bitcoin/script/opcodes_spec.rb in bitcoin-ruby-0.0.5 vs spec/bitcoin/script/opcodes_spec.rb in bitcoin-ruby-0.0.6
- old
+ new
@@ -356,22 +356,48 @@
[
[[1, 0, 0, 0, 3], [1,0,0,0,1]],
[[1, 0], [1,1]],
].each{|stack, expected|
op(:pick, stack).should == expected
+ @script.invalid?.should == false
}
+
+ [
+ [[0], [0]],
+ [[-1], [-1]],
+ ].each{|stack, expected|
+ op(:pick, stack).should == expected
+ @script.invalid?.should == true
+ }
end
it "should do op_roll" do
[
[[1, 0, 0, 0, 3], [0,0,0,1]],
[[1, 0], [1]],
].each{|stack, expected|
op(:roll, stack).should == expected
+ @script.invalid?.should == false
}
+
+ [
+ [[0], [0]],
+ [[-1], [-1]],
+ ].each{|stack, expected|
+ op(:roll, stack).should == expected
+ @script.invalid?.should == true
+ }
end
+ it "should do op_2rot" do
+ op(:"2rot", [-1,0,1,2,3,4,5,6]).should == [-1, 0, 3, 4, 5, 6, 1, 2]
+ @script.invalid?.should == false
+
+ op(:"2rot", [2,3,4,5,6]).should == [2, 3, 4, 5, 6]
+ @script.invalid?.should == true
+ end
+
it "should do op_rot" do
op(:rot, [22, 21, 20]).should == [21, 20, 22]
op(:rot, [21, 20]).should == [21, 20]
end
@@ -441,10 +467,13 @@
"1 OP_DUP OP_IF OP_ENDIF",
"1 OP_IF 1 OP_ENDIF",
"1 OP_DUP OP_IF OP_ELSE OP_ENDIF",
"1 OP_IF 1 OP_ELSE OP_ENDIF",
"0 OP_IF OP_ELSE 1 OP_ENDIF",
+ "beef OP_IF 1 OP_ELSE 0 OP_ENDIF",
+ "0 OP_NOTIF 1 OP_ELSE 0 OP_ENDIF",
+ "beef OP_NOTIF 0 OP_ELSE 1 OP_ENDIF",
].each{|script|
Bitcoin::Script.from_string(script).run.should == true
}
end
@@ -485,10 +514,15 @@
hash = signature_data
Bitcoin.verify_signature( hash, sig, pub.unpack("H*")[0] )
}
@script.op_checksig(verify_callback).should == [1]
+ @script.stack = [signature + hash_type, intger_pubkey=1]
+ verify_callback = proc{|pub,sig,hash_type|
+ pub.is_a?(String)
+ }
+ @script.op_checksig(verify_callback).should == [1]
@script.stack = [signature + hash_type, pubkey]
verify_callback = proc{|pub,sig,hash_type|
hash = "foo" + signature_data
Bitcoin.verify_signature( hash, sig, pub.unpack("H*")[0] )
@@ -521,12 +555,12 @@
end
def run_script(string, hash)
script = Bitcoin::Script.from_string(string)
script.run do |pk, sig, hash_type|
- k = Bitcoin::Key.new nil, pk.unpack("H*")[0]
- k.verify(hash, sig) rescue false
+ k = Bitcoin::Key.new(nil, pk.unpack("H*")[0]) rescue false
+ k && k.verify(hash, sig) rescue false
end == true
end
it "should do OP_CHECKMULTISIG" do
k1 = Bitcoin::Key.new; k1.generate
@@ -591,10 +625,16 @@
run_script(script, "foobar").should == false
script = "0 #{sig1} f0f0f0f0 #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
run_script(script, "foobar").should == false
+ script = "0 #{sig1} f0f0f0f0 #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG OP_NOT"
+ run_script(script, "foobar").should == true
+
+ script = "1 1 1 1 1 OP_CHECKMULTISIG OP_NOT"
+ run_script(script, "foobar").should == true
+
# mainnet tx output: 514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58
script = "0 #{sig1} 1 0 #{k1.pub} OP_SWAP OP_1ADD OP_CHECKMULTISIG"
run_script(script, "foobar").should == true
Bitcoin::Script.from_string(script).get_addresses.should == []
Bitcoin::Script.from_string(script).is_multisig?.should == false
@@ -630,10 +670,16 @@
run_script(script.to_string, "foobar").should == false
address = "3CkxTG25waxsmd13FFgRChPuGYba3ar36B"
script = Bitcoin::Script.new(Bitcoin::Script.to_address_script(address))
script.type.should == :p2sh
+
+ inner_script = Bitcoin::Script.from_string("0 OP_NOT").raw.unpack("H*")[0]
+ script_hash = Bitcoin.hash160(inner_script)
+ script = Bitcoin::Script.from_string("#{inner_script} OP_HASH160 #{script_hash} OP_EQUAL")
+ script.is_p2sh?.should == true
+ run_script(script.to_string, "foobar").should == true
end
it "should skip OP_EVAL" do
Bitcoin::Script.from_string("1 OP_EVAL").to_string.should == "1 OP_NOP1"
Bitcoin::Script.from_string("1 OP_EVAL").run.should == true
@@ -679,12 +725,24 @@
"ffffff7f OP_NEGATE OP_DUP OP_ADD feffffff80 OP_EQUAL",
"8b 11 OP_GREATERTHANOREQUAL OP_NOT",
"0 OP_0NOTEQUAL 0 OP_EQUAL",
"2 82 OP_ADD 0 OP_EQUAL",
].each{|script|
- Bitcoin::Script.from_string(script).run.should == true
+ parsed_script = Bitcoin::Script.from_string(script)
+ result = parsed_script.run
+ #p [script, parsed_script, parsed_script.debug result]
+ result.should == true
}
+
+ [
+ "ffffff7f ffffff7f OP_ADD ffffff7f OP_ADD OP_TRUE"
+ ].each{|script|
+ parsed_script = Bitcoin::Script.from_string(script)
+ result = parsed_script.run
+ #p [script, parsed_script, parsed_script.debug result]
+ result.should == false
+ }
end
it "should do OP_VER" do
s = Bitcoin::Script.from_string("OP_VER"); s.run; s.invalid?.should == true
s = Bitcoin::Script.from_string("1 OP_IF OP_VER 1 OP_ELSE 0 OP_ENDIF"); s.run.should == false; s.invalid?.should == true
@@ -696,7 +754,20 @@
s = Bitcoin::Script.from_string(Bitcoin::Script::OPCODES[opcode] + " 1"); s.run.should == false; s.invalid?.should == true
s = Bitcoin::Script.from_string("1 OP_IF #{Bitcoin::Script::OPCODES[opcode]} 1 OP_ELSE 1 OP_ENDIF"); s.run.should == false; s.invalid?.should == true
s = Bitcoin::Script.from_string("1 OP_IF 1 OP_ELSE #{Bitcoin::Script::OPCODES[opcode]} 1 OP_ENDIF"); s.run.should == false; s.invalid?.should == true
}
end
+
+ it "check before casting and mark bad cases invalid" do
+ s = Bitcoin::Script.from_string("OP_NOT") # tries to pop off an element from the empty stack here.
+ s.run.should == false
+ s.invalid?.should == true
+ end
+
+ it "should do OP_CHECKSIGVERIFY and OP_CHECKMULTISIGVERIFY" do
+ tx1 = Bitcoin::P::Tx.new("0100000001a3fe4396b575690095bfc088d864aa971c99f65e2d893b48e0b26b1b60a28754000000006a47304402201ddfc8e3f825add9f42c0ce76dc5709cf76871e7ee6c97aae11d7db7f829b3f202201c3043515bfcf3d77845c8740ce4ccb4bda3f431da64f2596ee0ea2dfb727a5c01210328a5915165382c9b119d10d313c5781d98a7de79225f3c58e7fa115660ba90e0ffffffff0270f305000000000017a914ca164de1946bf0146ed1f32413df0efb0e1c730f87005d8806000000001976a91437c1d63690e00845663f3de661fef981c08e8de588ac00000000".htb)
+ tx2 = Bitcoin::P::Tx.new("0100000001a1c5263304aa47f8e4e8a8dbca33e525667f7f0d84390c5a92d49eccbe5b970f00000000fde50152483045022100fbc7ccd87ad2384a4d8823d3cf36d839bb6acca3d80a9ed9c51c784b7bdf1e430220305fcb1660219fcc340935000aa92dd02684b763177b8a3c1be094c919af323701473044022008f66d2e31175cdefbd7461afb5f9946e5dcb8173d1a2d3ef837f1c810695d160220250354de77b4a919b87910aa203ecec54bd1006d2dad2fcac06a54f39a9d39a101514d4f0176519c6375522103b124c48bbff7ebe16e7bd2b2f2b561aa53791da678a73d2777cc1ca4619ab6f72103ad6bb76e00d124f07a22680e39debd4dc4bdb1aa4b893720dd05af3c50560fdd52af67529c63552103b124c48bbff7ebe16e7bd2b2f2b561aa53791da678a73d2777cc1ca4619ab6f721025098a1d5a338592bf1e015468ec5a8fafc1fc9217feb5cb33597f3613a2165e9210360cfabc01d52eaaeb3976a5de05ff0cfa76d0af42d3d7e1b4c233ee8a00655ed2103f571540c81fd9dbf9622ca00cfe95762143f2eab6b65150365bb34ac533160432102bc2b4be1bca32b9d97e2d6fb255504f4bc96e01aaca6e29bfa3f8bea65d8865855af672103ad6bb76e00d124f07a22680e39debd4dc4bdb1aa4b893720dd05af3c50560fddada820a4d933888318a23c28fb5fc67aca8530524e2074b1d185dbf5b4db4ddb0642848868685174519c6351670068000000000170f30500000000001976a914bce2fe0e49630a996cb9fe611e6b9b7d1e4dc21188acb4ff6153".htb)
+ tx2.verify_input_signature(0, tx1).should == true
+ end
+
end