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