9 "github.com/bytom/vapor/errors"
10 "github.com/bytom/vapor/math/checked"
15 func (op Op) String() string {
19 type Instruction struct {
27 OP_0 Op = 0x00 // synonym
30 OP_TRUE Op = 0x51 // synonym
124 OP_PUSHDATA1 Op = 0x4c
125 OP_PUSHDATA2 Op = 0x4d
126 OP_PUSHDATA4 Op = 0x4e
134 OP_CHECKPREDICATE Op = 0xc0
136 OP_TOALTSTACK Op = 0x6b
137 OP_FROMALTSTACK Op = 0x6c
161 OP_CATPUSHDATA Op = 0x89
168 OP_EQUALVERIFY Op = 0x88
177 OP_0NOTEQUAL Op = 0x92
187 OP_NUMEQUAL Op = 0x9c
188 OP_NUMEQUALVERIFY Op = 0x9d
189 OP_NUMNOTEQUAL Op = 0x9e
190 OP_LESSTHAN Op = 0x9f
191 OP_GREATERTHAN Op = 0xa0
192 OP_LESSTHANOREQUAL Op = 0xa1
193 OP_GREATERTHANOREQUAL Op = 0xa2
197 OP_MULFRACTION Op = 0xa6
202 OP_CHECKSIG Op = 0xac
203 OP_CHECKMULTISIG Op = 0xad
204 OP_TXSIGHASH Op = 0xae
206 OP_CHECKOUTPUT Op = 0xc1
212 OP_OUTPUTID Op = 0xcb
213 OP_BLOCKHEIGHT Op = 0xcd
219 fn func(*virtualMachine) error
225 OP_FALSE: {OP_FALSE, "FALSE", opFalse},
227 // sic: the PUSHDATA ops all share an implementation
228 OP_PUSHDATA1: {OP_PUSHDATA1, "PUSHDATA1", opPushdata},
229 OP_PUSHDATA2: {OP_PUSHDATA2, "PUSHDATA2", opPushdata},
230 OP_PUSHDATA4: {OP_PUSHDATA4, "PUSHDATA4", opPushdata},
232 OP_1NEGATE: {OP_1NEGATE, "1NEGATE", op1Negate},
234 OP_NOP: {OP_NOP, "NOP", opNop},
237 OP_JUMP: {OP_JUMP, "JUMP", opJump},
238 OP_JUMPIF: {OP_JUMPIF, "JUMPIF", opJumpIf},
240 OP_VERIFY: {OP_VERIFY, "VERIFY", opVerify},
241 OP_FAIL: {OP_FAIL, "FAIL", opFail},
243 OP_TOALTSTACK: {OP_TOALTSTACK, "TOALTSTACK", opToAltStack},
244 OP_FROMALTSTACK: {OP_FROMALTSTACK, "FROMALTSTACK", opFromAltStack},
245 OP_2DROP: {OP_2DROP, "2DROP", op2Drop},
246 OP_2DUP: {OP_2DUP, "2DUP", op2Dup},
247 OP_3DUP: {OP_3DUP, "3DUP", op3Dup},
248 OP_2OVER: {OP_2OVER, "2OVER", op2Over},
249 OP_2ROT: {OP_2ROT, "2ROT", op2Rot},
250 OP_2SWAP: {OP_2SWAP, "2SWAP", op2Swap},
251 OP_IFDUP: {OP_IFDUP, "IFDUP", opIfDup},
252 OP_DEPTH: {OP_DEPTH, "DEPTH", opDepth},
253 OP_DROP: {OP_DROP, "DROP", opDrop},
254 OP_DUP: {OP_DUP, "DUP", opDup},
255 OP_NIP: {OP_NIP, "NIP", opNip},
256 OP_OVER: {OP_OVER, "OVER", opOver},
257 OP_PICK: {OP_PICK, "PICK", opPick},
258 OP_ROLL: {OP_ROLL, "ROLL", opRoll},
259 OP_ROT: {OP_ROT, "ROT", opRot},
260 OP_SWAP: {OP_SWAP, "SWAP", opSwap},
261 OP_TUCK: {OP_TUCK, "TUCK", opTuck},
263 OP_CAT: {OP_CAT, "CAT", opCat},
264 OP_SUBSTR: {OP_SUBSTR, "SUBSTR", opSubstr},
265 OP_LEFT: {OP_LEFT, "LEFT", opLeft},
266 OP_RIGHT: {OP_RIGHT, "RIGHT", opRight},
267 OP_SIZE: {OP_SIZE, "SIZE", opSize},
268 OP_CATPUSHDATA: {OP_CATPUSHDATA, "CATPUSHDATA", opCatpushdata},
270 OP_INVERT: {OP_INVERT, "INVERT", opInvert},
271 OP_AND: {OP_AND, "AND", opAnd},
272 OP_OR: {OP_OR, "OR", opOr},
273 OP_XOR: {OP_XOR, "XOR", opXor},
274 OP_EQUAL: {OP_EQUAL, "EQUAL", opEqual},
275 OP_EQUALVERIFY: {OP_EQUALVERIFY, "EQUALVERIFY", opEqualVerify},
277 OP_1ADD: {OP_1ADD, "1ADD", op1Add},
278 OP_1SUB: {OP_1SUB, "1SUB", op1Sub},
279 OP_2MUL: {OP_2MUL, "2MUL", op2Mul},
280 OP_2DIV: {OP_2DIV, "2DIV", op2Div},
281 OP_NEGATE: {OP_NEGATE, "NEGATE", opNegate},
282 OP_ABS: {OP_ABS, "ABS", opAbs},
283 OP_NOT: {OP_NOT, "NOT", opNot},
284 OP_0NOTEQUAL: {OP_0NOTEQUAL, "0NOTEQUAL", op0NotEqual},
285 OP_ADD: {OP_ADD, "ADD", opAdd},
286 OP_SUB: {OP_SUB, "SUB", opSub},
287 OP_MUL: {OP_MUL, "MUL", opMul},
288 OP_DIV: {OP_DIV, "DIV", opDiv},
289 OP_MOD: {OP_MOD, "MOD", opMod},
290 OP_LSHIFT: {OP_LSHIFT, "LSHIFT", opLshift},
291 OP_RSHIFT: {OP_RSHIFT, "RSHIFT", opRshift},
292 OP_BOOLAND: {OP_BOOLAND, "BOOLAND", opBoolAnd},
293 OP_BOOLOR: {OP_BOOLOR, "BOOLOR", opBoolOr},
294 OP_NUMEQUAL: {OP_NUMEQUAL, "NUMEQUAL", opNumEqual},
295 OP_NUMEQUALVERIFY: {OP_NUMEQUALVERIFY, "NUMEQUALVERIFY", opNumEqualVerify},
296 OP_NUMNOTEQUAL: {OP_NUMNOTEQUAL, "NUMNOTEQUAL", opNumNotEqual},
297 OP_LESSTHAN: {OP_LESSTHAN, "LESSTHAN", opLessThan},
298 OP_GREATERTHAN: {OP_GREATERTHAN, "GREATERTHAN", opGreaterThan},
299 OP_LESSTHANOREQUAL: {OP_LESSTHANOREQUAL, "LESSTHANOREQUAL", opLessThanOrEqual},
300 OP_GREATERTHANOREQUAL: {OP_GREATERTHANOREQUAL, "GREATERTHANOREQUAL", opGreaterThanOrEqual},
301 OP_MIN: {OP_MIN, "MIN", opMin},
302 OP_MAX: {OP_MAX, "MAX", opMax},
303 OP_WITHIN: {OP_WITHIN, "WITHIN", opWithin},
304 OP_MULFRACTION: {OP_MULFRACTION, "MULFRACTION", opMulFraction},
306 OP_SHA256: {OP_SHA256, "SHA256", opSha256},
307 OP_SHA3: {OP_SHA3, "SHA3", opSha3},
308 OP_HASH160: {OP_HASH160, "HASH160", opHash160},
309 OP_CHECKSIG: {OP_CHECKSIG, "CHECKSIG", opCheckSig},
310 OP_CHECKMULTISIG: {OP_CHECKMULTISIG, "CHECKMULTISIG", opCheckMultiSig},
311 OP_TXSIGHASH: {OP_TXSIGHASH, "TXSIGHASH", opTxSigHash},
313 OP_CHECKOUTPUT: {OP_CHECKOUTPUT, "CHECKOUTPUT", opCheckOutput},
314 OP_ASSET: {OP_ASSET, "ASSET", opAsset},
315 OP_AMOUNT: {OP_AMOUNT, "AMOUNT", opAmount},
316 OP_PROGRAM: {OP_PROGRAM, "PROGRAM", opProgram},
317 OP_INDEX: {OP_INDEX, "INDEX", opIndex},
318 OP_ENTRYID: {OP_ENTRYID, "ENTRYID", opEntryID},
319 OP_OUTPUTID: {OP_OUTPUTID, "OUTPUTID", opOutputID},
320 OP_BLOCKHEIGHT: {OP_BLOCKHEIGHT, "BLOCKHEIGHT", opBlockHeight},
323 opsByName map[string]opInfo
326 // ParseOp parses the op at position pc in prog, returning the parsed
327 // instruction (opcode plus any associated data).
328 func ParseOp(prog []byte, pc uint32) (inst Instruction, err error) {
329 if len(prog) > math.MaxInt32 {
332 l := uint32(len(prog))
334 err = ErrShortProgram
337 opcode := Op(prog[pc])
340 if opcode >= OP_1 && opcode <= OP_16 {
341 inst.Data = []byte{uint8(opcode-OP_1) + 1}
344 if opcode >= OP_DATA_1 && opcode <= OP_DATA_75 {
345 inst.Len += uint32(opcode - OP_DATA_1 + 1)
346 end, ok := checked.AddUint32(pc, inst.Len)
348 err = errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size")
352 err = ErrShortProgram
355 inst.Data = prog[pc+1 : end]
358 if opcode == OP_PUSHDATA1 {
360 err = ErrShortProgram
364 inst.Len += uint32(n) + 1
365 end, ok := checked.AddUint32(pc, inst.Len)
367 err = errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size")
370 err = ErrShortProgram
373 inst.Data = prog[pc+2 : end]
376 if opcode == OP_PUSHDATA2 {
377 if len(prog) < 3 || pc > l-3 {
378 err = ErrShortProgram
381 n := binary.LittleEndian.Uint16(prog[pc+1 : pc+3])
382 inst.Len += uint32(n) + 2
383 end, ok := checked.AddUint32(pc, inst.Len)
385 err = errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size")
389 err = ErrShortProgram
392 inst.Data = prog[pc+3 : end]
395 if opcode == OP_PUSHDATA4 {
396 if len(prog) < 5 || pc > l-5 {
397 err = ErrShortProgram
402 n := binary.LittleEndian.Uint32(prog[pc+1 : pc+5])
404 inst.Len, ok = checked.AddUint32(inst.Len, n)
406 err = errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size")
409 end, ok := checked.AddUint32(pc, inst.Len)
411 err = errors.WithDetail(checked.ErrOverflow, "data length exceeds max program size")
415 err = ErrShortProgram
418 inst.Data = prog[pc+5 : end]
421 if opcode == OP_JUMP || opcode == OP_JUMPIF {
423 end, ok := checked.AddUint32(pc, inst.Len)
425 err = errors.WithDetail(checked.ErrOverflow, "jump target exceeds max program size")
429 err = ErrShortProgram
432 inst.Data = prog[pc+1 : end]
438 func ParseProgram(prog []byte) ([]Instruction, error) {
439 var result []Instruction
440 for pc := uint32(0); pc < uint32(len(prog)); { // update pc inside the loop
441 inst, err := ParseOp(prog, pc)
445 result = append(result, inst)
447 pc, ok = checked.AddUint32(pc, inst.Len)
449 return nil, errors.WithDetail(checked.ErrOverflow, "program counter exceeds max program size")
455 var isExpansion [256]bool
458 for i := 1; i <= 75; i++ {
459 ops[i] = opInfo{Op(i), fmt.Sprintf("DATA_%d", i), opPushdata}
461 for i := uint8(0); i <= 15; i++ {
462 op := uint8(OP_1) + i
463 ops[op] = opInfo{Op(op), fmt.Sprintf("%d", i+1), opPushdata}
466 // This is here to break a dependency cycle
467 ops[OP_CHECKPREDICATE] = opInfo{OP_CHECKPREDICATE, "CHECKPREDICATE", opCheckPredicate}
469 opsByName = make(map[string]opInfo)
470 for _, info := range ops {
471 opsByName[info.name] = info
473 opsByName["0"] = ops[OP_FALSE]
474 opsByName["TRUE"] = ops[OP_1]
476 for i := 0; i <= 255; i++ {
477 if ops[i].name == "" {
478 ops[i] = opInfo{Op(i), fmt.Sprintf("NOPx%02x", i), opNop}
479 isExpansion[i] = true
484 // IsPushdata judge instruction whether is a pushdata operation(include opFalse operation)
485 func (inst *Instruction) IsPushdata() bool {
486 if reflect.ValueOf(ops[inst.Op].fn) == reflect.ValueOf(ops[OP_1].fn) ||
487 reflect.ValueOf(ops[inst.Op].fn) == reflect.ValueOf(ops[OP_0].fn) {