github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/vm/ops.go (about) 1 package vm 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 "reflect" 8 9 "github.com/bytom/bytom/errors" 10 "github.com/bytom/bytom/math/checked" 11 ) 12 13 type Op uint8 14 15 func (op Op) String() string { 16 return ops[op].name 17 } 18 19 type Instruction struct { 20 Op Op 21 Len uint32 22 Data []byte 23 } 24 25 const ( 26 OP_FALSE Op = 0x00 27 OP_0 Op = 0x00 // synonym 28 29 OP_1 Op = 0x51 30 OP_TRUE Op = 0x51 // synonym 31 32 OP_2 Op = 0x52 33 OP_3 Op = 0x53 34 OP_4 Op = 0x54 35 OP_5 Op = 0x55 36 OP_6 Op = 0x56 37 OP_7 Op = 0x57 38 OP_8 Op = 0x58 39 OP_9 Op = 0x59 40 OP_10 Op = 0x5a 41 OP_11 Op = 0x5b 42 OP_12 Op = 0x5c 43 OP_13 Op = 0x5d 44 OP_14 Op = 0x5e 45 OP_15 Op = 0x5f 46 OP_16 Op = 0x60 47 48 OP_DATA_1 Op = 0x01 49 OP_DATA_2 Op = 0x02 50 OP_DATA_3 Op = 0x03 51 OP_DATA_4 Op = 0x04 52 OP_DATA_5 Op = 0x05 53 OP_DATA_6 Op = 0x06 54 OP_DATA_7 Op = 0x07 55 OP_DATA_8 Op = 0x08 56 OP_DATA_9 Op = 0x09 57 OP_DATA_10 Op = 0x0a 58 OP_DATA_11 Op = 0x0b 59 OP_DATA_12 Op = 0x0c 60 OP_DATA_13 Op = 0x0d 61 OP_DATA_14 Op = 0x0e 62 OP_DATA_15 Op = 0x0f 63 OP_DATA_16 Op = 0x10 64 OP_DATA_17 Op = 0x11 65 OP_DATA_18 Op = 0x12 66 OP_DATA_19 Op = 0x13 67 OP_DATA_20 Op = 0x14 68 OP_DATA_21 Op = 0x15 69 OP_DATA_22 Op = 0x16 70 OP_DATA_23 Op = 0x17 71 OP_DATA_24 Op = 0x18 72 OP_DATA_25 Op = 0x19 73 OP_DATA_26 Op = 0x1a 74 OP_DATA_27 Op = 0x1b 75 OP_DATA_28 Op = 0x1c 76 OP_DATA_29 Op = 0x1d 77 OP_DATA_30 Op = 0x1e 78 OP_DATA_31 Op = 0x1f 79 OP_DATA_32 Op = 0x20 80 OP_DATA_33 Op = 0x21 81 OP_DATA_34 Op = 0x22 82 OP_DATA_35 Op = 0x23 83 OP_DATA_36 Op = 0x24 84 OP_DATA_37 Op = 0x25 85 OP_DATA_38 Op = 0x26 86 OP_DATA_39 Op = 0x27 87 OP_DATA_40 Op = 0x28 88 OP_DATA_41 Op = 0x29 89 OP_DATA_42 Op = 0x2a 90 OP_DATA_43 Op = 0x2b 91 OP_DATA_44 Op = 0x2c 92 OP_DATA_45 Op = 0x2d 93 OP_DATA_46 Op = 0x2e 94 OP_DATA_47 Op = 0x2f 95 OP_DATA_48 Op = 0x30 96 OP_DATA_49 Op = 0x31 97 OP_DATA_50 Op = 0x32 98 OP_DATA_51 Op = 0x33 99 OP_DATA_52 Op = 0x34 100 OP_DATA_53 Op = 0x35 101 OP_DATA_54 Op = 0x36 102 OP_DATA_55 Op = 0x37 103 OP_DATA_56 Op = 0x38 104 OP_DATA_57 Op = 0x39 105 OP_DATA_58 Op = 0x3a 106 OP_DATA_59 Op = 0x3b 107 OP_DATA_60 Op = 0x3c 108 OP_DATA_61 Op = 0x3d 109 OP_DATA_62 Op = 0x3e 110 OP_DATA_63 Op = 0x3f 111 OP_DATA_64 Op = 0x40 112 OP_DATA_65 Op = 0x41 113 OP_DATA_66 Op = 0x42 114 OP_DATA_67 Op = 0x43 115 OP_DATA_68 Op = 0x44 116 OP_DATA_69 Op = 0x45 117 OP_DATA_70 Op = 0x46 118 OP_DATA_71 Op = 0x47 119 OP_DATA_72 Op = 0x48 120 OP_DATA_73 Op = 0x49 121 OP_DATA_74 Op = 0x4a 122 OP_DATA_75 Op = 0x4b 123 124 OP_PUSHDATA1 Op = 0x4c 125 OP_PUSHDATA2 Op = 0x4d 126 OP_PUSHDATA4 Op = 0x4e 127 OP_NOP Op = 0x61 128 129 OP_JUMP Op = 0x63 130 OP_JUMPIF Op = 0x64 131 OP_VERIFY Op = 0x69 132 OP_FAIL Op = 0x6a 133 OP_CHECKPREDICATE Op = 0xc0 134 135 OP_TOALTSTACK Op = 0x6b 136 OP_FROMALTSTACK Op = 0x6c 137 OP_2DROP Op = 0x6d 138 OP_2DUP Op = 0x6e 139 OP_3DUP Op = 0x6f 140 OP_2OVER Op = 0x70 141 OP_2ROT Op = 0x71 142 OP_2SWAP Op = 0x72 143 OP_IFDUP Op = 0x73 144 OP_DEPTH Op = 0x74 145 OP_DROP Op = 0x75 146 OP_DUP Op = 0x76 147 OP_NIP Op = 0x77 148 OP_OVER Op = 0x78 149 OP_PICK Op = 0x79 150 OP_ROLL Op = 0x7a 151 OP_ROT Op = 0x7b 152 OP_SWAP Op = 0x7c 153 OP_TUCK Op = 0x7d 154 155 OP_CAT Op = 0x7e 156 OP_SUBSTR Op = 0x7f 157 OP_LEFT Op = 0x80 158 OP_RIGHT Op = 0x81 159 OP_SIZE Op = 0x82 160 OP_CATPUSHDATA Op = 0x89 161 162 OP_INVERT Op = 0x83 163 OP_AND Op = 0x84 164 OP_OR Op = 0x85 165 OP_XOR Op = 0x86 166 OP_EQUAL Op = 0x87 167 OP_EQUALVERIFY Op = 0x88 168 169 OP_1ADD Op = 0x8b 170 OP_1SUB Op = 0x8c 171 OP_2MUL Op = 0x8d 172 OP_2DIV Op = 0x8e 173 OP_NOT Op = 0x91 174 OP_0NOTEQUAL Op = 0x92 175 OP_ADD Op = 0x93 176 OP_SUB Op = 0x94 177 OP_MUL Op = 0x95 178 OP_DIV Op = 0x96 179 OP_MOD Op = 0x97 180 OP_LSHIFT Op = 0x98 181 OP_RSHIFT Op = 0x99 182 OP_BOOLAND Op = 0x9a 183 OP_BOOLOR Op = 0x9b 184 OP_NUMEQUAL Op = 0x9c 185 OP_NUMEQUALVERIFY Op = 0x9d 186 OP_NUMNOTEQUAL Op = 0x9e 187 OP_LESSTHAN Op = 0x9f 188 OP_GREATERTHAN Op = 0xa0 189 OP_LESSTHANOREQUAL Op = 0xa1 190 OP_GREATERTHANOREQUAL Op = 0xa2 191 OP_MIN Op = 0xa3 192 OP_MAX Op = 0xa4 193 OP_WITHIN Op = 0xa5 194 195 OP_SHA256 Op = 0xa8 196 OP_SHA3 Op = 0xaa 197 OP_HASH160 Op = 0xab 198 OP_CHECKSIG Op = 0xac 199 OP_CHECKMULTISIG Op = 0xad 200 OP_TXSIGHASH Op = 0xae 201 202 OP_CHECKOUTPUT Op = 0xc1 203 OP_ASSET Op = 0xc2 204 OP_AMOUNT Op = 0xc3 205 OP_PROGRAM Op = 0xc4 206 OP_INDEX Op = 0xc9 207 OP_ENTRYID Op = 0xca 208 OP_OUTPUTID Op = 0xcb 209 OP_BLOCKHEIGHT Op = 0xcd 210 ) 211 212 type opInfo struct { 213 op Op 214 name string 215 fn func(*virtualMachine) error 216 } 217 218 var ( 219 ops = [256]opInfo{ 220 // data pushing 221 OP_FALSE: {OP_FALSE, "FALSE", opFalse}, 222 223 // sic: the PUSHDATA ops all share an implementation 224 OP_PUSHDATA1: {OP_PUSHDATA1, "PUSHDATA1", opPushdata}, 225 OP_PUSHDATA2: {OP_PUSHDATA2, "PUSHDATA2", opPushdata}, 226 OP_PUSHDATA4: {OP_PUSHDATA4, "PUSHDATA4", opPushdata}, 227 228 OP_NOP: {OP_NOP, "NOP", opNop}, 229 230 // control flow 231 OP_JUMP: {OP_JUMP, "JUMP", opJump}, 232 OP_JUMPIF: {OP_JUMPIF, "JUMPIF", opJumpIf}, 233 234 OP_VERIFY: {OP_VERIFY, "VERIFY", opVerify}, 235 OP_FAIL: {OP_FAIL, "FAIL", opFail}, 236 237 OP_TOALTSTACK: {OP_TOALTSTACK, "TOALTSTACK", opToAltStack}, 238 OP_FROMALTSTACK: {OP_FROMALTSTACK, "FROMALTSTACK", opFromAltStack}, 239 OP_2DROP: {OP_2DROP, "2DROP", op2Drop}, 240 OP_2DUP: {OP_2DUP, "2DUP", op2Dup}, 241 OP_3DUP: {OP_3DUP, "3DUP", op3Dup}, 242 OP_2OVER: {OP_2OVER, "2OVER", op2Over}, 243 OP_2ROT: {OP_2ROT, "2ROT", op2Rot}, 244 OP_2SWAP: {OP_2SWAP, "2SWAP", op2Swap}, 245 OP_IFDUP: {OP_IFDUP, "IFDUP", opIfDup}, 246 OP_DEPTH: {OP_DEPTH, "DEPTH", opDepth}, 247 OP_DROP: {OP_DROP, "DROP", opDrop}, 248 OP_DUP: {OP_DUP, "DUP", opDup}, 249 OP_NIP: {OP_NIP, "NIP", opNip}, 250 OP_OVER: {OP_OVER, "OVER", opOver}, 251 OP_PICK: {OP_PICK, "PICK", opPick}, 252 OP_ROLL: {OP_ROLL, "ROLL", opRoll}, 253 OP_ROT: {OP_ROT, "ROT", opRot}, 254 OP_SWAP: {OP_SWAP, "SWAP", opSwap}, 255 OP_TUCK: {OP_TUCK, "TUCK", opTuck}, 256 257 OP_CAT: {OP_CAT, "CAT", opCat}, 258 OP_SUBSTR: {OP_SUBSTR, "SUBSTR", opSubstr}, 259 OP_LEFT: {OP_LEFT, "LEFT", opLeft}, 260 OP_RIGHT: {OP_RIGHT, "RIGHT", opRight}, 261 OP_SIZE: {OP_SIZE, "SIZE", opSize}, 262 OP_CATPUSHDATA: {OP_CATPUSHDATA, "CATPUSHDATA", opCatpushdata}, 263 264 OP_INVERT: {OP_INVERT, "INVERT", opInvert}, 265 OP_AND: {OP_AND, "AND", opAnd}, 266 OP_OR: {OP_OR, "OR", opOr}, 267 OP_XOR: {OP_XOR, "XOR", opXor}, 268 OP_EQUAL: {OP_EQUAL, "EQUAL", opEqual}, 269 OP_EQUALVERIFY: {OP_EQUALVERIFY, "EQUALVERIFY", opEqualVerify}, 270 271 OP_1ADD: {OP_1ADD, "1ADD", op1Add}, 272 OP_1SUB: {OP_1SUB, "1SUB", op1Sub}, 273 OP_2MUL: {OP_2MUL, "2MUL", op2Mul}, 274 OP_2DIV: {OP_2DIV, "2DIV", op2Div}, 275 OP_NOT: {OP_NOT, "NOT", opNot}, 276 OP_0NOTEQUAL: {OP_0NOTEQUAL, "0NOTEQUAL", op0NotEqual}, 277 OP_ADD: {OP_ADD, "ADD", opAdd}, 278 OP_SUB: {OP_SUB, "SUB", opSub}, 279 OP_MUL: {OP_MUL, "MUL", opMul}, 280 OP_DIV: {OP_DIV, "DIV", opDiv}, 281 OP_MOD: {OP_MOD, "MOD", opMod}, 282 OP_LSHIFT: {OP_LSHIFT, "LSHIFT", opLshift}, 283 OP_RSHIFT: {OP_RSHIFT, "RSHIFT", opRshift}, 284 OP_BOOLAND: {OP_BOOLAND, "BOOLAND", opBoolAnd}, 285 OP_BOOLOR: {OP_BOOLOR, "BOOLOR", opBoolOr}, 286 OP_NUMEQUAL: {OP_NUMEQUAL, "NUMEQUAL", opNumEqual}, 287 OP_NUMEQUALVERIFY: {OP_NUMEQUALVERIFY, "NUMEQUALVERIFY", opNumEqualVerify}, 288 OP_NUMNOTEQUAL: {OP_NUMNOTEQUAL, "NUMNOTEQUAL", opNumNotEqual}, 289 OP_LESSTHAN: {OP_LESSTHAN, "LESSTHAN", opLessThan}, 290 OP_GREATERTHAN: {OP_GREATERTHAN, "GREATERTHAN", opGreaterThan}, 291 OP_LESSTHANOREQUAL: {OP_LESSTHANOREQUAL, "LESSTHANOREQUAL", opLessThanOrEqual}, 292 OP_GREATERTHANOREQUAL: {OP_GREATERTHANOREQUAL, "GREATERTHANOREQUAL", opGreaterThanOrEqual}, 293 OP_MIN: {OP_MIN, "MIN", opMin}, 294 OP_MAX: {OP_MAX, "MAX", opMax}, 295 OP_WITHIN: {OP_WITHIN, "WITHIN", opWithin}, 296 297 OP_SHA256: {OP_SHA256, "SHA256", opSha256}, 298 OP_SHA3: {OP_SHA3, "SHA3", opSha3}, 299 OP_HASH160: {OP_HASH160, "HASH160", opHash160}, 300 OP_CHECKSIG: {OP_CHECKSIG, "CHECKSIG", opCheckSig}, 301 OP_CHECKMULTISIG: {OP_CHECKMULTISIG, "CHECKMULTISIG", opCheckMultiSig}, 302 OP_TXSIGHASH: {OP_TXSIGHASH, "TXSIGHASH", opTxSigHash}, 303 304 OP_CHECKOUTPUT: {OP_CHECKOUTPUT, "CHECKOUTPUT", opCheckOutput}, 305 OP_ASSET: {OP_ASSET, "ASSET", opAsset}, 306 OP_AMOUNT: {OP_AMOUNT, "AMOUNT", opAmount}, 307 OP_PROGRAM: {OP_PROGRAM, "PROGRAM", opProgram}, 308 OP_INDEX: {OP_INDEX, "INDEX", opIndex}, 309 OP_ENTRYID: {OP_ENTRYID, "ENTRYID", opEntryID}, 310 OP_OUTPUTID: {OP_OUTPUTID, "OUTPUTID", opOutputID}, 311 OP_BLOCKHEIGHT: {OP_BLOCKHEIGHT, "BLOCKHEIGHT", opBlockHeight}, 312 } 313 314 opsByName map[string]opInfo 315 ) 316 317 // ParseOp parses the op at position pc in prog, returning the parsed 318 // instruction (opcode plus any associated data). 319 func ParseOp(prog []byte, pc uint32) (inst Instruction, err error) { 320 l := uint32(len(prog)) 321 if l > math.MaxInt32 { 322 return inst, ErrLongProgram 323 } 324 325 if pc >= l { 326 return inst, ErrShortProgram 327 } 328 329 opcode := Op(prog[pc]) 330 inst.Op = opcode 331 inst.Len = 1 332 if opcode >= OP_1 && opcode <= OP_16 { 333 inst.Data = []byte{uint8(opcode-OP_1) + 1} 334 return 335 } 336 337 if opcode >= OP_DATA_1 && opcode <= OP_DATA_75 { 338 inst.Len += uint32(opcode - OP_DATA_1 + 1) 339 end, ok := checked.AddUint32(pc, inst.Len) 340 if !ok { 341 return inst, errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size") 342 } 343 344 if end > l { 345 return inst, ErrShortProgram 346 } 347 348 inst.Data = prog[pc+1 : end] 349 return 350 } 351 352 if opcode == OP_PUSHDATA1 { 353 if pc == l-1 { 354 return inst, ErrShortProgram 355 } 356 357 n := prog[pc+1] 358 inst.Len += uint32(n) + 1 359 end, ok := checked.AddUint32(pc, inst.Len) 360 if !ok { 361 return inst, errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size") 362 } 363 364 if end > l { 365 return inst, ErrShortProgram 366 } 367 368 inst.Data = prog[pc+2 : end] 369 return 370 } 371 372 if opcode == OP_PUSHDATA2 { 373 if len(prog) < 3 || pc > l-3 { 374 return inst, ErrShortProgram 375 } 376 377 n := binary.LittleEndian.Uint16(prog[pc+1 : pc+3]) 378 inst.Len += uint32(n) + 2 379 end, ok := checked.AddUint32(pc, inst.Len) 380 if !ok { 381 return inst, errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size") 382 } 383 384 if end > l { 385 return inst, ErrShortProgram 386 } 387 388 inst.Data = prog[pc+3 : end] 389 return 390 } 391 392 if opcode == OP_PUSHDATA4 { 393 if len(prog) < 5 || pc > l-5 { 394 return inst, ErrShortProgram 395 } 396 397 inst.Len += 4 398 n := binary.LittleEndian.Uint32(prog[pc+1 : pc+5]) 399 var ok bool 400 inst.Len, ok = checked.AddUint32(inst.Len, n) 401 if !ok { 402 return inst, errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size") 403 } 404 405 end, ok := checked.AddUint32(pc, inst.Len) 406 if !ok { 407 return inst, errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size") 408 } 409 410 if end > l { 411 return inst, ErrShortProgram 412 } 413 414 inst.Data = prog[pc+5 : end] 415 return 416 } 417 418 if opcode == OP_JUMP || opcode == OP_JUMPIF { 419 inst.Len += 4 420 end, ok := checked.AddUint32(pc, inst.Len) 421 if !ok { 422 return inst, errors.WithDetail(checked.ErrOverflow, "jump target exceeds max program size") 423 } 424 425 if end > l { 426 return inst, ErrShortProgram 427 } 428 429 inst.Data = prog[pc+1 : end] 430 return 431 } 432 return 433 } 434 435 func ParseProgram(prog []byte) ([]Instruction, error) { 436 var result []Instruction 437 for pc := uint32(0); pc < uint32(len(prog)); { // update pc inside the loop 438 inst, err := ParseOp(prog, pc) 439 if err != nil { 440 return nil, err 441 } 442 443 result = append(result, inst) 444 var ok bool 445 pc, ok = checked.AddUint32(pc, inst.Len) 446 if !ok { 447 return nil, errors.WithDetail(checked.ErrOverflow, "program counter exceeds max program size") 448 } 449 } 450 return result, nil 451 } 452 453 var isExpansion [256]bool 454 455 func init() { 456 for i := 1; i <= 75; i++ { 457 ops[i] = opInfo{Op(i), fmt.Sprintf("DATA_%d", i), opPushdata} 458 } 459 for i := uint8(0); i <= 15; i++ { 460 op := uint8(OP_1) + i 461 ops[op] = opInfo{Op(op), fmt.Sprintf("%d", i+1), opPushdata} 462 } 463 464 // This is here to break a dependency cycle 465 ops[OP_CHECKPREDICATE] = opInfo{OP_CHECKPREDICATE, "CHECKPREDICATE", opCheckPredicate} 466 467 opsByName = make(map[string]opInfo) 468 for _, info := range ops { 469 opsByName[info.name] = info 470 } 471 opsByName["0"] = ops[OP_FALSE] 472 opsByName["TRUE"] = ops[OP_1] 473 474 for i := 0; i <= 255; i++ { 475 if ops[i].name == "" { 476 ops[i] = opInfo{Op(i), fmt.Sprintf("NOPx%02x", i), opNop} 477 isExpansion[i] = true 478 } 479 } 480 } 481 482 // IsPushdata judge instruction whether is a pushdata operation(include opFalse operation) 483 func (inst *Instruction) IsPushdata() bool { 484 return reflect.ValueOf(ops[inst.Op].fn) == reflect.ValueOf(ops[OP_1].fn) || reflect.ValueOf(ops[inst.Op].fn) == reflect.ValueOf(ops[OP_0].fn) 485 }