github.com/lbryio/lbcd@v0.22.119/txscript/opcode_test.go (about) 1 // Copyright (c) 2013-2017 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package txscript 6 7 import ( 8 "bytes" 9 "fmt" 10 "strconv" 11 "strings" 12 "testing" 13 ) 14 15 // TestOpcodeDisabled tests the opcodeDisabled function manually because all 16 // disabled opcodes result in a script execution failure when executed normally, 17 // so the function is not called under normal circumstances. 18 func TestOpcodeDisabled(t *testing.T) { 19 t.Parallel() 20 21 tests := []byte{OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT, OP_INVERT, 22 OP_AND, OP_OR, OP_2MUL, OP_2DIV, OP_MUL, OP_DIV, OP_MOD, 23 OP_LSHIFT, OP_RSHIFT, 24 } 25 for _, opcodeVal := range tests { 26 op := &opcodeArray[opcodeVal] 27 err := opcodeDisabled(op, nil, nil) 28 if !IsErrorCode(err, ErrDisabledOpcode) { 29 t.Errorf("opcodeDisabled: unexpected error - got %v, "+ 30 "want %v", err, ErrDisabledOpcode) 31 continue 32 } 33 } 34 } 35 36 // TestOpcodeDisasm tests the print function for all opcodes in both the oneline 37 // and full modes to ensure it provides the expected disassembly. 38 func TestOpcodeDisasm(t *testing.T) { 39 t.Parallel() 40 41 // First, test the oneline disassembly. 42 43 // The expected strings for the data push opcodes are replaced in the 44 // test loops below since they involve repeating bytes. Also, the 45 // OP_NOP# and OP_UNKNOWN# are replaced below too, since it's easier 46 // than manually listing them here. 47 oneBytes := []byte{0x01} 48 oneStr := "01" 49 expectedStrings := [256]string{0x00: "0", 0x4f: "-1", 50 0x50: "OP_RESERVED", 0x61: "OP_NOP", 0x62: "OP_VER", 51 0x63: "OP_IF", 0x64: "OP_NOTIF", 0x65: "OP_VERIF", 52 0x66: "OP_VERNOTIF", 0x67: "OP_ELSE", 0x68: "OP_ENDIF", 53 0x69: "OP_VERIFY", 0x6a: "OP_RETURN", 0x6b: "OP_TOALTSTACK", 54 0x6c: "OP_FROMALTSTACK", 0x6d: "OP_2DROP", 0x6e: "OP_2DUP", 55 0x6f: "OP_3DUP", 0x70: "OP_2OVER", 0x71: "OP_2ROT", 56 0x72: "OP_2SWAP", 0x73: "OP_IFDUP", 0x74: "OP_DEPTH", 57 0x75: "OP_DROP", 0x76: "OP_DUP", 0x77: "OP_NIP", 58 0x78: "OP_OVER", 0x79: "OP_PICK", 0x7a: "OP_ROLL", 59 0x7b: "OP_ROT", 0x7c: "OP_SWAP", 0x7d: "OP_TUCK", 60 0x7e: "OP_CAT", 0x7f: "OP_SUBSTR", 0x80: "OP_LEFT", 61 0x81: "OP_RIGHT", 0x82: "OP_SIZE", 0x83: "OP_INVERT", 62 0x84: "OP_AND", 0x85: "OP_OR", 0x86: "OP_XOR", 63 0x87: "OP_EQUAL", 0x88: "OP_EQUALVERIFY", 0x89: "OP_RESERVED1", 64 0x8a: "OP_RESERVED2", 0x8b: "OP_1ADD", 0x8c: "OP_1SUB", 65 0x8d: "OP_2MUL", 0x8e: "OP_2DIV", 0x8f: "OP_NEGATE", 66 0x90: "OP_ABS", 0x91: "OP_NOT", 0x92: "OP_0NOTEQUAL", 67 0x93: "OP_ADD", 0x94: "OP_SUB", 0x95: "OP_MUL", 0x96: "OP_DIV", 68 0x97: "OP_MOD", 0x98: "OP_LSHIFT", 0x99: "OP_RSHIFT", 69 0x9a: "OP_BOOLAND", 0x9b: "OP_BOOLOR", 0x9c: "OP_NUMEQUAL", 70 0x9d: "OP_NUMEQUALVERIFY", 0x9e: "OP_NUMNOTEQUAL", 71 0x9f: "OP_LESSTHAN", 0xa0: "OP_GREATERTHAN", 72 0xa1: "OP_LESSTHANOREQUAL", 0xa2: "OP_GREATERTHANOREQUAL", 73 0xa3: "OP_MIN", 0xa4: "OP_MAX", 0xa5: "OP_WITHIN", 74 0xa6: "OP_RIPEMD160", 0xa7: "OP_SHA1", 0xa8: "OP_SHA256", 75 0xa9: "OP_HASH160", 0xaa: "OP_HASH256", 0xab: "OP_CODESEPARATOR", 76 0xac: "OP_CHECKSIG", 0xad: "OP_CHECKSIGVERIFY", 77 0xae: "OP_CHECKMULTISIG", 0xaf: "OP_CHECKMULTISIGVERIFY", 78 0xfa: "OP_SMALLINTEGER", 0xfb: "OP_PUBKEYS", 79 0xfd: "OP_PUBKEYHASH", 0xfe: "OP_PUBKEY", 80 0xff: "OP_INVALIDOPCODE", 81 } 82 for opcodeVal, expectedStr := range expectedStrings { 83 var data []byte 84 switch { 85 // OP_DATA_1 through OP_DATA_65 display the pushed data. 86 case opcodeVal >= 0x01 && opcodeVal < 0x4c: 87 data = bytes.Repeat(oneBytes, opcodeVal) 88 expectedStr = strings.Repeat(oneStr, opcodeVal) 89 90 // OP_PUSHDATA1. 91 case opcodeVal == 0x4c: 92 data = bytes.Repeat(oneBytes, 1) 93 expectedStr = strings.Repeat(oneStr, 1) 94 95 // OP_PUSHDATA2. 96 case opcodeVal == 0x4d: 97 data = bytes.Repeat(oneBytes, 2) 98 expectedStr = strings.Repeat(oneStr, 2) 99 100 // OP_PUSHDATA4. 101 case opcodeVal == 0x4e: 102 data = bytes.Repeat(oneBytes, 3) 103 expectedStr = strings.Repeat(oneStr, 3) 104 105 // OP_1 through OP_16 display the numbers themselves. 106 case opcodeVal >= 0x51 && opcodeVal <= 0x60: 107 val := byte(opcodeVal - (0x51 - 1)) 108 data = []byte{val} 109 expectedStr = strconv.Itoa(int(val)) 110 111 // OP_NOP1 through OP_NOP10. 112 case opcodeVal >= 0xb0 && opcodeVal <= 0xb9: 113 switch opcodeVal { 114 case 0xb1: 115 // OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY 116 expectedStr = "OP_CHECKLOCKTIMEVERIFY" 117 case 0xb2: 118 // OP_NOP3 is an alias of OP_CHECKSEQUENCEVERIFY 119 expectedStr = "OP_CHECKSEQUENCEVERIFY" 120 case OP_CLAIMNAME: 121 expectedStr = "OP_CLAIMNAME" 122 case OP_SUPPORTCLAIM: 123 expectedStr = "OP_SUPPORTCLAIM" 124 case OP_UPDATECLAIM: 125 expectedStr = "OP_UPDATECLAIM" 126 default: 127 val := byte(opcodeVal - (0xb0 - 1)) 128 expectedStr = "OP_NOP" + strconv.Itoa(int(val)) 129 } 130 131 // OP_UNKNOWN#. 132 case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc: 133 expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) 134 } 135 136 var buf strings.Builder 137 disasmOpcode(&buf, &opcodeArray[opcodeVal], data, true) 138 gotStr := buf.String() 139 if gotStr != expectedStr { 140 t.Errorf("pop.print (opcode %x): Unexpected disasm "+ 141 "string - got %v, want %v", opcodeVal, gotStr, 142 expectedStr) 143 continue 144 } 145 } 146 147 // Now, replace the relevant fields and test the full disassembly. 148 expectedStrings[0x00] = "OP_0" 149 expectedStrings[0x4f] = "OP_1NEGATE" 150 for opcodeVal, expectedStr := range expectedStrings { 151 var data []byte 152 switch { 153 // OP_DATA_1 through OP_DATA_65 display the opcode followed by 154 // the pushed data. 155 case opcodeVal >= 0x01 && opcodeVal < 0x4c: 156 data = bytes.Repeat(oneBytes, opcodeVal) 157 expectedStr = fmt.Sprintf("OP_DATA_%d 0x%s", opcodeVal, 158 strings.Repeat(oneStr, opcodeVal)) 159 160 // OP_PUSHDATA1. 161 case opcodeVal == 0x4c: 162 data = bytes.Repeat(oneBytes, 1) 163 expectedStr = fmt.Sprintf("OP_PUSHDATA1 0x%02x 0x%s", 164 len(data), strings.Repeat(oneStr, 1)) 165 166 // OP_PUSHDATA2. 167 case opcodeVal == 0x4d: 168 data = bytes.Repeat(oneBytes, 2) 169 expectedStr = fmt.Sprintf("OP_PUSHDATA2 0x%04x 0x%s", 170 len(data), strings.Repeat(oneStr, 2)) 171 172 // OP_PUSHDATA4. 173 case opcodeVal == 0x4e: 174 data = bytes.Repeat(oneBytes, 3) 175 expectedStr = fmt.Sprintf("OP_PUSHDATA4 0x%08x 0x%s", 176 len(data), strings.Repeat(oneStr, 3)) 177 178 // OP_1 through OP_16. 179 case opcodeVal >= 0x51 && opcodeVal <= 0x60: 180 val := byte(opcodeVal - (0x51 - 1)) 181 data = []byte{val} 182 expectedStr = "OP_" + strconv.Itoa(int(val)) 183 184 // OP_NOP1 through OP_NOP10. 185 case opcodeVal >= 0xb0 && opcodeVal <= 0xb9: 186 switch opcodeVal { 187 case 0xb1: 188 // OP_NOP2 is an alias of OP_CHECKLOCKTIMEVERIFY 189 expectedStr = "OP_CHECKLOCKTIMEVERIFY" 190 case 0xb2: 191 // OP_NOP3 is an alias of OP_CHECKSEQUENCEVERIFY 192 expectedStr = "OP_CHECKSEQUENCEVERIFY" 193 case OP_CLAIMNAME: 194 expectedStr = "OP_CLAIMNAME" 195 case OP_SUPPORTCLAIM: 196 expectedStr = "OP_SUPPORTCLAIM" 197 case OP_UPDATECLAIM: 198 expectedStr = "OP_UPDATECLAIM" 199 default: 200 val := byte(opcodeVal - (0xb0 - 1)) 201 expectedStr = "OP_NOP" + strconv.Itoa(int(val)) 202 } 203 204 // OP_UNKNOWN#. 205 case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc: 206 expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) 207 } 208 209 var buf strings.Builder 210 disasmOpcode(&buf, &opcodeArray[opcodeVal], data, false) 211 gotStr := buf.String() 212 if gotStr != expectedStr { 213 t.Errorf("pop.print (opcode %x): Unexpected disasm "+ 214 "string - got %v, want %v", opcodeVal, gotStr, 215 expectedStr) 216 continue 217 } 218 } 219 }