--- /dev/null
+package vm
+
+import (
+ "testing"
+
+ "github.com/bytom/testutil"
+)
+
+func TestCheckSig(t *testing.T) {
+ cases := []struct {
+ prog string
+ ok, err bool
+ }{
+ {
+ // This one's OK
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 CHECKSIG",
+ true, false,
+ },
+ {
+ // This one has a wrong-length signature
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc2 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 CHECKSIG",
+ false, false,
+ },
+ {
+ // This one has a wrong-length message
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 CHECKSIG",
+ false, true,
+ },
+ {
+ // This one has a wrong-length pubkey
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584 CHECKSIG",
+ false, false,
+ },
+ {
+ // This one has a wrong byte in the signature
+ "0x00ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 CHECKSIG",
+ false, false,
+ },
+ {
+ // This one has a wrong byte in the message
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0002030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 CHECKSIG",
+ false, false,
+ },
+ {
+ // This one has a wrong byte in the pubkey
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0x00ca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 CHECKSIG",
+ false, false,
+ },
+ {
+ "0x010203 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0x040506 1 1 CHECKMULTISIG",
+ false, false,
+ },
+ {
+ "0x010203 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 0x040506 1 1 CHECKMULTISIG",
+ false, true,
+ },
+ {
+ "0x26ced30b1942b89ef5332a9f22f1a61e5a6a3f8a5bc33b2fc58b1daf78c81bf1d5c8add19cea050adeb37da3a7bf8f813c6a6922b42934a6441fa6bb1c7fc208 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 0xdbca6fb13badb7cfdf76510070ffad15b85f9934224a9e11202f5e8f86b584a6 1 1 CHECKMULTISIG",
+ true, false,
+ },
+ }
+
+ for i, c := range cases {
+ prog, err := Assemble(c.prog)
+ if err != nil {
+ t.Fatalf("case %d: %s", i, err)
+ }
+ vm := &virtualMachine{
+ program: prog,
+ runLimit: 50000,
+ }
+ err = vm.run()
+ if c.err {
+ if err == nil {
+ t.Errorf("case %d: expected error, got ok result", i)
+ }
+ } else if c.ok {
+ if err != nil {
+ t.Errorf("case %d: expected ok result, got error %s", i, err)
+ }
+ } else if !vm.falseResult() {
+ t.Errorf("case %d: expected false VM result, got error %s", i, err)
+ }
+ }
+}
+
+func TestCryptoOps(t *testing.T) {
+ OP_SM3 := Op(0xb0)
+ ops[OP_SM3] = opInfo{OP_SM3, "SM3", opSm3}
+
+ type testStruct struct {
+ op Op
+ startVM *virtualMachine
+ wantErr error
+ wantVM *virtualMachine
+ }
+ cases := []testStruct{{
+ op: OP_SHA256,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{{1}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49905,
+ dataStack: [][]byte{{
+ 75, 245, 18, 47, 52, 69, 84, 197, 59, 222, 46, 187, 140, 210, 183, 227,
+ 209, 96, 10, 214, 49, 195, 133, 165, 215, 204, 226, 60, 119, 133, 69, 154,
+ }},
+ },
+ }, {
+ op: OP_SHA256,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{make([]byte, 65)},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49968,
+ dataStack: [][]byte{{
+ 152, 206, 66, 222, 239, 81, 212, 2, 105, 213, 66, 245, 49, 75, 239, 44,
+ 116, 104, 212, 1, 173, 93, 133, 22, 139, 250, 180, 192, 16, 143, 117, 247,
+ }},
+ },
+ }, {
+ op: OP_SHA3,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{{1}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49905,
+ dataStack: [][]byte{{
+ 39, 103, 241, 92, 138, 242, 242, 199, 34, 93, 82, 115, 253, 214, 131, 237,
+ 199, 20, 17, 10, 152, 125, 16, 84, 105, 124, 52, 138, 237, 78, 108, 199,
+ }},
+ },
+ }, {
+ op: OP_SHA3,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{make([]byte, 65)},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49968,
+ dataStack: [][]byte{{
+ 65, 106, 167, 181, 192, 224, 101, 48, 102, 167, 198, 77, 189, 208, 0, 157,
+ 190, 132, 56, 97, 81, 254, 3, 159, 217, 66, 250, 162, 219, 97, 114, 235,
+ }},
+ },
+ }, {
+ op: OP_HASH160,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{{1}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49916,
+ dataStack: [][]byte{{
+ 242, 145, 186, 80, 21, 223, 52, 140, 128, 133, 63, 165, 187, 15, 121, 70, 245, 201, 225, 179,
+ }},
+ },
+ }, {
+ op: OP_HASH160,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{make([]byte, 65)},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49916,
+ dataStack: [][]byte{{
+ 171, 60, 102, 205, 10, 63, 18, 180, 244, 250, 235, 84, 138, 85, 22, 7, 148, 250, 215, 6,
+ }},
+ },
+ }, {
+ op: OP_SM3,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{{1}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49905,
+ dataStack: [][]byte{{
+ 121, 155, 113, 154, 192, 49, 252, 137, 198, 216, 146, 90, 72, 125, 173, 7,
+ 48, 143, 131, 123, 122, 183, 187, 199, 206, 189, 58, 65, 24, 253, 47, 56,
+ }},
+ },
+ }, {
+ op: OP_SM3,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{make([]byte, 65)},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49968,
+ dataStack: [][]byte{{
+ 177, 247, 110, 45, 29, 65, 214, 241, 187, 59, 9, 192, 155, 130, 25, 218,
+ 251, 173, 112, 13, 242, 72, 34, 32, 200, 146, 190, 65, 68, 90, 34, 255,
+ }},
+ },
+ }, {
+ op: OP_CHECKSIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851" +
+ "fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ },
+ },
+ wantVM: &virtualMachine{
+ deferredCost: -143,
+ runLimit: 48976,
+ dataStack: [][]byte{{1}},
+ },
+ }, {
+ op: OP_CHECKSIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851" +
+ "fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("badda7a7a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ },
+ },
+ wantVM: &virtualMachine{
+ deferredCost: -144,
+ runLimit: 48976,
+ dataStack: [][]byte{{}},
+ },
+ }, {
+ op: OP_CHECKSIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851" +
+ "fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("bad220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ },
+ },
+ wantVM: &virtualMachine{
+ deferredCost: -144,
+ runLimit: 48976,
+ dataStack: [][]byte{{}},
+ },
+ }, {
+ op: OP_CHECKSIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("badabdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851" +
+ "fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ },
+ },
+ wantVM: &virtualMachine{
+ deferredCost: -144,
+ runLimit: 48976,
+ dataStack: [][]byte{{}},
+ },
+ }, {
+ op: OP_CHECKSIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851" +
+ "fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("badbad"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ },
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_CHECKSIG,
+ startVM: &virtualMachine{
+ runLimit: 0,
+ },
+ wantErr: ErrRunLimitExceeded,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {1},
+ {1},
+ },
+ },
+ wantVM: &virtualMachine{
+ deferredCost: -161,
+ runLimit: 48976,
+ dataStack: [][]byte{{1}},
+ },
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("badabdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {1},
+ {1},
+ },
+ },
+ wantVM: &virtualMachine{
+ deferredCost: -162,
+ runLimit: 48976,
+ dataStack: [][]byte{{}},
+ },
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{},
+ },
+ wantErr: ErrDataStackUnderflow,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ {1},
+ {1},
+ },
+ },
+ wantErr: ErrDataStackUnderflow,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ {1},
+ {1},
+ },
+ },
+ wantErr: ErrDataStackUnderflow,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ {1},
+ {1},
+ },
+ },
+ wantErr: ErrDataStackUnderflow,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("badbad"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {1},
+ {1},
+ },
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {1},
+ {0},
+ },
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {0},
+ {1},
+ },
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {2},
+ {1},
+ },
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_CHECKMULTISIG,
+ startVM: &virtualMachine{
+ runLimit: 0,
+ dataStack: [][]byte{
+ mustDecodeHex("af5abdf4bbb34f4a089efc298234f84fd909def662a8df03b4d7d40372728851fbd3bf59920af5a7c361a4851967714271d1727e3be417a60053c30969d8860c"),
+ mustDecodeHex("916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"),
+ mustDecodeHex("ab3220d065dc875c6a5b4ecc39809b5f24eb0a605e9eef5190457edbf1e3b866"),
+ {1},
+ {1},
+ },
+ },
+ wantErr: ErrRunLimitExceeded,
+ }, {
+ op: OP_TXSIGHASH,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ context: &Context{
+ TxSigHash: func() []byte {
+ return []byte{
+ 0x2f, 0x00, 0x3c, 0xdd, 0x64, 0x42, 0x7b, 0x5e,
+ 0xed, 0xd6, 0xcc, 0xb5, 0x85, 0x47, 0x02, 0x0b,
+ 0x02, 0xde, 0xf2, 0x2d, 0xc5, 0x99, 0x7e, 0x9d,
+ 0xa9, 0xac, 0x40, 0x49, 0xc3, 0x4a, 0x58, 0xd8,
+ }
+ },
+ },
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49704,
+ dataStack: [][]byte{{
+ 47, 0, 60, 221, 100, 66, 123, 94,
+ 237, 214, 204, 181, 133, 71, 2, 11,
+ 2, 222, 242, 45, 197, 153, 126, 157,
+ 169, 172, 64, 73, 195, 74, 88, 216,
+ }},
+ },
+ }, {
+ op: OP_TXSIGHASH,
+ startVM: &virtualMachine{
+ runLimit: 0,
+ context: &Context{},
+ },
+ wantErr: ErrRunLimitExceeded,
+ }}
+
+ hashOps := []Op{OP_SHA256, OP_SHA3, OP_SM3}
+ for _, op := range hashOps {
+ cases = append(cases, testStruct{
+ op: op,
+ startVM: &virtualMachine{
+ runLimit: 0,
+ dataStack: [][]byte{{1}},
+ },
+ wantErr: ErrRunLimitExceeded,
+ })
+ }
+
+ for i, c := range cases {
+ t.Logf("case %d", i)
+
+ err := ops[c.op].fn(c.startVM)
+ gotVM := c.startVM
+
+ if err != c.wantErr {
+ t.Errorf("case %d, op %s: got err = %v want %v", i, ops[c.op].name, err, c.wantErr)
+ continue
+ }
+ if c.wantErr != nil {
+ continue
+ }
+
+ // Hack: the context objects will otherwise compare unequal
+ // sometimes (because of the function pointer within?) and we
+ // don't care
+ c.wantVM.context = gotVM.context
+
+ if !testutil.DeepEqual(gotVM, c.wantVM) {
+ t.Errorf("case %d, op %s: unexpected vm result\n\tgot: %+v\n\twant: %+v\n", i, ops[c.op].name, gotVM, c.wantVM)
+ }
+ }
+}