github.com/ontio/ontology@v1.14.4/vm/neovm/executor.go (about) 1 /* 2 * Copyright (C) 2018 The ontology Authors 3 * This file is part of The ontology library. 4 * 5 * The ontology is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * The ontology is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with The ontology. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package neovm 20 21 import ( 22 "crypto/sha1" 23 "crypto/sha256" 24 "fmt" 25 26 "github.com/ontio/ontology-crypto/keypair" 27 "github.com/ontio/ontology/common" 28 "github.com/ontio/ontology/core/signature" 29 "github.com/ontio/ontology/vm/neovm/constants" 30 "github.com/ontio/ontology/vm/neovm/errors" 31 "github.com/ontio/ontology/vm/neovm/types" 32 "golang.org/x/crypto/ripemd160" 33 ) 34 35 type VmFeatureFlag struct { 36 DisableHasKey bool // disable haskey, dcall, values opcode 37 AllowReaderEOF bool // allow VmReader.ReadBytes got EOF and return 0 bytes 38 } 39 40 func NewExecutor(code []byte, feature VmFeatureFlag) *Executor { 41 var engine Executor 42 engine.EvalStack = NewValueStack(STACK_LIMIT) 43 engine.AltStack = NewValueStack(STACK_LIMIT) 44 context := NewExecutionContext(code, feature) 45 engine.Context = context 46 engine.State = BREAK 47 engine.Features = feature 48 return &engine 49 } 50 51 type Executor struct { 52 EvalStack *ValueStack 53 AltStack *ValueStack 54 State VMState 55 Features VmFeatureFlag 56 Callers []*ExecutionContext 57 Context *ExecutionContext 58 } 59 60 func (self *Executor) PopContext() (*ExecutionContext, error) { 61 total := len(self.Callers) 62 if total == 0 { 63 return nil, errors.ERR_INDEX_OUT_OF_BOUND 64 } 65 context := self.Callers[total-1] 66 self.Callers = self.Callers[:total-1] 67 return context, nil 68 } 69 70 func (self *Executor) PushContext(context *ExecutionContext) error { 71 if len(self.Callers) >= constants.MAX_INVOCATION_STACK_SIZE { 72 return errors.ERR_OVER_STACK_LEN 73 } 74 self.Callers = append(self.Callers, context) 75 return nil 76 } 77 78 func (self *Executor) Execute() error { 79 self.State = self.State & (^BREAK) 80 for self.Context != nil { 81 if self.State == FAULT || self.State == HALT || self.State == BREAK { 82 break 83 } 84 if self.Context == nil { 85 break 86 } 87 88 opcode, eof := self.Context.ReadOpCode() 89 if eof { 90 break 91 } 92 93 var err error 94 self.State, err = self.ExecuteOp(opcode, self.Context) 95 if err != nil { 96 return err 97 } 98 } 99 return nil 100 } 101 102 func (self *Executor) checkFeaturesEnabled(opcode OpCode) error { 103 switch opcode { 104 case HASKEY, KEYS, DCALL, VALUES: 105 if self.Features.DisableHasKey { 106 return errors.ERR_NOT_SUPPORT_OPCODE 107 } 108 } 109 110 return nil 111 } 112 113 func (self *Executor) ExecuteOp(opcode OpCode, context *ExecutionContext) (VMState, error) { 114 if err := self.checkFeaturesEnabled(opcode); err != nil { 115 return FAULT, err 116 } 117 118 if opcode >= PUSHBYTES1 && opcode <= PUSHBYTES75 { 119 buf, err := context.OpReader.ReadBytes(int(opcode)) 120 if err != nil { 121 return FAULT, err 122 } 123 val, err := types.VmValueFromBytes(buf) 124 if err != nil { 125 return FAULT, err 126 } 127 err = self.EvalStack.Push(val) 128 if err != nil { 129 return FAULT, err 130 } 131 return NONE, nil 132 } 133 134 switch opcode { 135 case PUSH0: 136 err := self.EvalStack.Push(types.VmValueFromInt64(0)) 137 if err != nil { 138 return FAULT, err 139 } 140 case PUSHDATA1, PUSHDATA2, PUSHDATA4: 141 var numBytes int 142 if opcode == PUSHDATA1 { 143 d, err := context.OpReader.ReadByte() 144 if err != nil { 145 return FAULT, err 146 } 147 148 numBytes = int(d) 149 } else if opcode == PUSHDATA2 { 150 num, err := context.OpReader.ReadUint16() 151 if err != nil { 152 return FAULT, err 153 } 154 numBytes = int(num) 155 } else { 156 num, err := context.OpReader.ReadUint32() 157 if err != nil { 158 return FAULT, err 159 } 160 numBytes = int(num) 161 } 162 163 data, err := context.OpReader.ReadBytes(numBytes) 164 if err != nil { 165 return FAULT, err 166 } 167 val, err := types.VmValueFromBytes(data) 168 if err != nil { 169 return FAULT, err 170 } 171 err = self.EvalStack.Push(val) 172 if err != nil { 173 return FAULT, err 174 } 175 case PUSHM1, PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16: 176 val := int64(opcode) - int64(PUSH1) + 1 177 err := self.EvalStack.Push(types.VmValueFromInt64(val)) 178 if err != nil { 179 return FAULT, err 180 } 181 // Flow control 182 case NOP: 183 return NONE, nil 184 case JMP, JMPIF, JMPIFNOT, CALL: 185 if opcode == CALL { 186 caller := context.Clone() 187 err := caller.SetInstructionPointer(int64(caller.GetInstructionPointer() + 2)) 188 if err != nil { 189 return FAULT, err 190 } 191 err = self.PushContext(caller) 192 if err != nil { 193 return FAULT, err 194 } 195 opcode = JMP 196 } 197 198 num, err := context.OpReader.ReadInt16() 199 if err != nil { 200 return FAULT, err 201 } 202 offset := int(num) 203 offset = context.GetInstructionPointer() + offset - 3 204 205 if offset < 0 || offset > len(context.Code) { 206 return FAULT, errors.ERR_FAULT 207 } 208 var needJmp = true 209 if opcode != JMP { 210 val, err := self.EvalStack.PopAsBool() 211 if err != nil { 212 return FAULT, err 213 } 214 if opcode == JMPIF { 215 needJmp = val 216 } else { 217 needJmp = !val 218 } 219 } 220 221 if needJmp { 222 err := context.SetInstructionPointer(int64(offset)) 223 if err != nil { 224 return FAULT, err 225 } 226 } 227 case DCALL: 228 caller := context.Clone() 229 err := self.PushContext(caller) 230 if err != nil { 231 return FAULT, errors.ERR_OVER_STACK_LEN 232 } 233 target, err := self.EvalStack.PopAsInt64() 234 if err != nil { 235 return FAULT, err 236 } 237 if target < 0 || target >= int64(len(self.Context.Code)) { 238 return FAULT, errors.ERR_DCALL_OFFSET_ERROR 239 } 240 err = self.Context.SetInstructionPointer(target) 241 if err != nil { 242 return FAULT, err 243 } 244 case RET: 245 // omit handle error is ok, if context stack is empty, self.Context will be nil 246 // which will be checked outside before the next opcode call 247 self.Context, _ = self.PopContext() 248 case DUPFROMALTSTACK: 249 val, err := self.AltStack.Peek(0) 250 if err != nil { 251 return FAULT, err 252 } 253 err = self.EvalStack.Push(val) 254 if err != nil { 255 return FAULT, err 256 } 257 case TOALTSTACK: 258 val, err := self.EvalStack.Pop() 259 if err != nil { 260 return FAULT, err 261 } 262 err = self.AltStack.Push(val) 263 if err != nil { 264 return FAULT, err 265 } 266 case FROMALTSTACK: 267 val, err := self.AltStack.Pop() 268 if err != nil { 269 return FAULT, err 270 } 271 err = self.EvalStack.Push(val) 272 if err != nil { 273 return FAULT, err 274 } 275 276 case XDROP: // XDROP is zero based 277 n, err := self.EvalStack.PopAsInt64() 278 if err != nil { 279 return FAULT, err 280 } 281 _, err = self.EvalStack.Remove(n) 282 if err != nil { 283 return FAULT, err 284 } 285 case XSWAP: 286 n, err := self.EvalStack.PopAsInt64() 287 if err != nil { 288 return FAULT, err 289 } 290 291 err = self.EvalStack.Swap(0, n) 292 if err != nil { 293 return FAULT, err 294 } 295 case XTUCK: 296 n, err := self.EvalStack.PopAsInt64() 297 if err != nil { 298 return FAULT, err 299 } 300 301 val, err := self.EvalStack.Peek(0) 302 if err != nil { 303 return FAULT, err 304 } 305 306 err = self.EvalStack.Insert(n, val) 307 if err != nil { 308 return FAULT, err 309 } 310 case DEPTH: 311 err := self.EvalStack.PushInt64(int64(self.EvalStack.Count())) 312 if err != nil { 313 return FAULT, err 314 } 315 case DROP: 316 _, err := self.EvalStack.Pop() 317 if err != nil { 318 return FAULT, err 319 } 320 case DUP: 321 val, err := self.EvalStack.Peek(0) 322 if err != nil { 323 return FAULT, err 324 } 325 err = self.EvalStack.Push(val) 326 if err != nil { 327 return FAULT, err 328 } 329 case NIP: 330 _, val, err := self.EvalStack.PopPair() 331 if err != nil { 332 return FAULT, err 333 } 334 335 err = self.EvalStack.Push(val) 336 if err != nil { 337 return FAULT, err 338 } 339 case OVER: 340 val, err := self.EvalStack.Peek(1) 341 if err != nil { 342 return FAULT, err 343 } 344 345 err = self.EvalStack.Push(val) 346 if err != nil { 347 return FAULT, err 348 } 349 case PICK: 350 n, err := self.EvalStack.PopAsInt64() 351 if err != nil { 352 return FAULT, err 353 } 354 355 val, err := self.EvalStack.Peek(n) 356 if err != nil { 357 return FAULT, err 358 } 359 360 err = self.EvalStack.Push(val) 361 if err != nil { 362 return FAULT, err 363 } 364 case ROLL, ROT: 365 var n int64 366 var err error 367 if opcode == ROT { 368 n = 2 369 } else { 370 n, err = self.EvalStack.PopAsInt64() 371 if err != nil { 372 return FAULT, err 373 } 374 } 375 376 // need clearly define the behave when n == 0 and stack is empty 377 val, err := self.EvalStack.Remove(n) 378 if err != nil { 379 return FAULT, err 380 } 381 382 err = self.EvalStack.Push(val) 383 if err != nil { 384 return FAULT, err 385 } 386 case SWAP: // The top two items on the stack are swapped. 387 err := self.EvalStack.Swap(0, 1) 388 if err != nil { 389 return FAULT, err 390 } 391 case TUCK: // The item at the top of the stack is copied and inserted before the second-to-top item. 392 x1, x2, err := self.EvalStack.PopPair() 393 if err != nil { 394 return FAULT, err 395 } 396 397 err = self.EvalStack.PushMany(x2, x1, x2) 398 if err != nil { 399 return FAULT, err 400 } 401 // Splice 402 case CAT: 403 left, right, err := self.EvalStack.PopPairAsBytes() 404 if err != nil { 405 return FAULT, err 406 } 407 408 val := make([]byte, 0, len(left)+len(right)) 409 val = append(val, left...) 410 val = append(val, right...) 411 err = self.EvalStack.PushBytes(val) 412 if err != nil { 413 return FAULT, err 414 } 415 case SUBSTR: 416 start, count, err := self.EvalStack.PopPairAsInt64() 417 if err != nil { 418 return FAULT, err 419 } 420 arr, err := self.EvalStack.PopAsBytes() 421 if err != nil { 422 return FAULT, err 423 } 424 425 length := int64(len(arr)) 426 if start < 0 || start > length { 427 return FAULT, errors.ERR_OVER_MAX_ARRAY_SIZE 428 } 429 if count < 0 || count > length { 430 return FAULT, errors.ERR_OVER_MAX_ARRAY_SIZE 431 } 432 end := start + count 433 if end > length { 434 return FAULT, errors.ERR_OVER_MAX_ARRAY_SIZE 435 } 436 437 b := arr[start:end] 438 err = self.EvalStack.PushBytes(b) 439 if err != nil { 440 return FAULT, err 441 } 442 443 case LEFT: 444 count, err := self.EvalStack.PopAsInt64() 445 if err != nil { 446 return FAULT, err 447 } 448 arr, err := self.EvalStack.PopAsBytes() 449 if err != nil { 450 return FAULT, err 451 } 452 453 length := int64(len(arr)) 454 if count < 0 || count > length { 455 return FAULT, errors.ERR_OVER_MAX_ARRAY_SIZE 456 } 457 458 b := arr[:count] 459 err = self.EvalStack.PushBytes(b) 460 if err != nil { 461 return FAULT, err 462 } 463 case RIGHT: 464 count, err := self.EvalStack.PopAsInt64() 465 if err != nil { 466 return FAULT, err 467 } 468 arr, err := self.EvalStack.PopAsBytes() 469 if err != nil { 470 return FAULT, err 471 } 472 473 length := int64(len(arr)) 474 if count < 0 || count > length { 475 return FAULT, errors.ERR_OVER_MAX_ARRAY_SIZE 476 } 477 478 b := arr[length-count:] 479 err = self.EvalStack.PushBytes(b) 480 if err != nil { 481 return FAULT, err 482 } 483 case SIZE: 484 arr, err := self.EvalStack.PopAsBytes() 485 if err != nil { 486 return FAULT, err 487 } 488 489 err = self.EvalStack.PushInt64(int64(len(arr))) 490 if err != nil { 491 return FAULT, err 492 } 493 // Bitwise logic 494 case INVERT: 495 left, err := self.EvalStack.PopAsIntValue() 496 if err != nil { 497 return FAULT, err 498 } 499 val := left.Not() 500 err = self.EvalStack.Push(types.VmValueFromIntValue(val)) 501 if err != nil { 502 return FAULT, err 503 } 504 case AND, OR, XOR: 505 left, right, err := self.EvalStack.PopPairAsIntVal() 506 if err != nil { 507 return FAULT, err 508 } 509 510 var val types.IntValue 511 switch opcode { 512 case AND: 513 val, err = left.And(right) 514 case OR: 515 val, err = left.Or(right) 516 case XOR: 517 val, err = left.Xor(right) 518 default: 519 panic("unreachable") 520 } 521 if err != nil { 522 return FAULT, err 523 } 524 err = self.EvalStack.Push(types.VmValueFromIntValue(val)) 525 if err != nil { 526 return FAULT, err 527 } 528 case EQUAL: 529 left, right, err := self.EvalStack.PopPair() 530 if err != nil { 531 return FAULT, err 532 } 533 err = self.EvalStack.PushBool(left.Equals(right)) 534 if err != nil { 535 return FAULT, err 536 } 537 case INC, DEC, SIGN, NEGATE, ABS: 538 x, err := self.EvalStack.PopAsIntValue() 539 if err != nil { 540 return FAULT, err 541 } 542 543 var val types.IntValue 544 switch opcode { 545 case INC: 546 val, err = x.Add(types.IntValFromInt(1)) 547 case DEC: 548 val, err = x.Sub(types.IntValFromInt(1)) 549 case SIGN: 550 cmp := x.Cmp(types.IntValFromInt(0)) 551 val = types.IntValFromInt(int64(cmp)) 552 case NEGATE: 553 val, err = types.IntValFromInt(0).Sub(x) 554 case ABS: 555 val = x.Abs() 556 default: 557 panic("unreachable") 558 } 559 if err != nil { 560 return FAULT, err 561 } 562 563 err = self.EvalStack.Push(types.VmValueFromIntValue(val)) 564 if err != nil { 565 return FAULT, err 566 } 567 case NZ: 568 x, err := self.EvalStack.PopAsIntValue() 569 if err != nil { 570 return FAULT, err 571 } 572 573 cmp := x.Cmp(types.IntValFromInt(0)) 574 if cmp == 0 { 575 err = self.EvalStack.PushBool(false) 576 } else { 577 err = self.EvalStack.PushBool(true) 578 } 579 580 if err != nil { 581 return FAULT, err 582 } 583 case ADD, SUB, MUL, DIV, MOD, MAX, MIN: 584 left, right, err := self.EvalStack.PopPairAsIntVal() 585 if err != nil { 586 return FAULT, err 587 } 588 var val types.IntValue 589 switch opcode { 590 case ADD: 591 val, err = left.Add(right) 592 case SUB: 593 val, err = left.Sub(right) 594 case MUL: 595 val, err = left.Mul(right) 596 case DIV: 597 val, err = left.Div(right) 598 case MOD: 599 val, err = left.Mod(right) 600 case MAX: 601 val, err = left.Max(right) 602 case MIN: 603 val, err = left.Min(right) 604 default: 605 panic("unreachable") 606 } 607 if err != nil { 608 return FAULT, err 609 } 610 err = self.EvalStack.Push(types.VmValueFromIntValue(val)) 611 if err != nil { 612 return FAULT, err 613 } 614 case SHL, SHR: 615 x2, err := self.EvalStack.PopAsIntValue() 616 if err != nil { 617 return FAULT, err 618 } 619 x1, err := self.EvalStack.PopAsIntValue() 620 if err != nil { 621 return FAULT, err 622 } 623 var res types.IntValue 624 switch opcode { 625 case SHL: 626 res, err = x1.Lsh(x2) 627 if err != nil { 628 return FAULT, err 629 } 630 case SHR: 631 res, err = x1.Rsh(x2) 632 if err != nil { 633 return FAULT, err 634 } 635 default: 636 panic("unreachable") 637 } 638 b := types.VmValueFromIntValue(res) 639 err = self.EvalStack.Push(b) 640 if err != nil { 641 return FAULT, err 642 } 643 case NUMNOTEQUAL, NUMEQUAL: 644 // note : pop as bytes to avoid hard-fork because previous version missing check 645 // whether the params are a valid 32 byte integer 646 left, right, err := self.EvalStack.PopPairAsBytes() 647 if err != nil { 648 return FAULT, err 649 } 650 l := common.BigIntFromNeoBytes(left) 651 r := common.BigIntFromNeoBytes(right) 652 var val bool 653 switch opcode { 654 case NUMEQUAL: 655 val = l.Cmp(r) == 0 656 case NUMNOTEQUAL: 657 val = l.Cmp(r) != 0 658 default: 659 panic("unreachable") 660 } 661 err = self.EvalStack.PushBool(val) 662 if err != nil { 663 return FAULT, err 664 } 665 case LT, GT, LTE, GTE: 666 leftVal, rightVal, err := self.EvalStack.PopPair() 667 if err != nil { 668 return FAULT, err 669 } 670 left, err := leftVal.AsBigInt() 671 if err != nil { 672 return FAULT, err 673 } 674 right, err := rightVal.AsBigInt() 675 if err != nil { 676 return FAULT, err 677 } 678 var val bool 679 switch opcode { 680 case LT: 681 val = left.Cmp(right) < 0 682 case GT: 683 val = left.Cmp(right) > 0 684 case LTE: 685 val = left.Cmp(right) <= 0 686 case GTE: 687 val = left.Cmp(right) >= 0 688 default: 689 panic("unreachable") 690 } 691 if err != nil { 692 return FAULT, err 693 } 694 err = self.EvalStack.PushBool(val) 695 if err != nil { 696 return FAULT, err 697 } 698 699 case BOOLAND, BOOLOR: 700 left, right, err := self.EvalStack.PopPairAsBool() 701 if err != nil { 702 return FAULT, err 703 } 704 705 var val bool 706 switch opcode { 707 case BOOLAND: 708 val = left && right 709 case BOOLOR: 710 val = left || right 711 default: 712 panic("unreachable") 713 } 714 err = self.EvalStack.PushBool(val) 715 if err != nil { 716 return FAULT, err 717 } 718 case NOT: 719 x, err := self.EvalStack.PopAsBool() 720 if err != nil { 721 return FAULT, err 722 } 723 724 err = self.EvalStack.PushBool(!x) 725 if err != nil { 726 return FAULT, err 727 } 728 case WITHIN: 729 val, left, right, err := self.EvalStack.PopTripleAsIntVal() 730 if err != nil { 731 return FAULT, err 732 } 733 v1 := val.Cmp(left) 734 v2 := val.Cmp(right) 735 736 err = self.EvalStack.PushBool(v1 >= 0 && v2 < 0) 737 if err != nil { 738 return FAULT, err 739 } 740 case SHA1, SHA256, HASH160, HASH256: 741 x, err := self.EvalStack.PopAsBytes() 742 if err != nil { 743 return FAULT, err 744 } 745 746 var hash []byte 747 switch opcode { 748 case SHA1: 749 sh := sha1.New() 750 sh.Write(x) 751 hash = sh.Sum(nil) 752 case SHA256: 753 sh := sha256.New() 754 sh.Write(x) 755 hash = sh.Sum(nil) 756 case HASH160: 757 temp := sha256.Sum256(x) 758 md := ripemd160.New() 759 md.Write(temp[:]) 760 hash = md.Sum(nil) 761 case HASH256: 762 temp := sha256.Sum256(x) 763 data := sha256.Sum256(temp[:]) 764 hash = data[:] 765 } 766 val, err := types.VmValueFromBytes(hash) 767 if err != nil { 768 return FAULT, err 769 } 770 err = self.EvalStack.Push(val) 771 if err != nil { 772 return FAULT, err 773 } 774 case VERIFY: 775 pub, sig, data, err := self.EvalStack.PopTripleAsBytes() 776 if err != nil { 777 return FAULT, err 778 } 779 780 key, err := keypair.DeserializePublicKey(pub) 781 if err != nil { 782 return FAULT, err 783 } 784 785 verErr := signature.Verify(key, data, sig) 786 err = self.EvalStack.PushBool(verErr == nil) 787 if err != nil { 788 return FAULT, err 789 } 790 // Array 791 case ARRAYSIZE: 792 val, err := self.EvalStack.Pop() 793 if err != nil { 794 return FAULT, err 795 } 796 797 var length int64 798 if array, err := val.AsArrayValue(); err == nil { 799 length = array.Len() 800 } else if buf, err := val.AsBytes(); err == nil { 801 length = int64(len(buf)) 802 } else { 803 return FAULT, errors.ERR_BAD_TYPE 804 } 805 806 err = self.EvalStack.PushInt64(length) 807 if err != nil { 808 return FAULT, err 809 } 810 case PACK: 811 size, err := self.EvalStack.PopAsInt64() 812 if err != nil { 813 return FAULT, err 814 } 815 if size < 0 { 816 return FAULT, errors.ERR_BAD_VALUE 817 } 818 array := types.NewArrayValue() 819 for i := int64(0); i < size; i++ { 820 val, err := self.EvalStack.Pop() 821 if err != nil { 822 return FAULT, err 823 } 824 825 err = array.Append(val) 826 if err != nil { 827 return FAULT, err 828 } 829 } 830 err = self.EvalStack.Push(types.VmValueFromArrayVal(array)) 831 if err != nil { 832 return FAULT, err 833 } 834 case UNPACK: 835 arr, err := self.EvalStack.PopAsArray() 836 if err != nil { 837 return FAULT, err 838 } 839 l := len(arr.Data) 840 for i := l - 1; i >= 0; i-- { 841 err = self.EvalStack.Push(arr.Data[i]) 842 if err != nil { 843 return FAULT, err 844 } 845 } 846 err = self.EvalStack.PushInt64(int64(l)) 847 if err != nil { 848 return FAULT, err 849 } 850 case PICKITEM: 851 item, index, err := self.EvalStack.PopPair() 852 if err != nil { 853 return FAULT, err 854 } 855 856 var val types.VmValue 857 if array, err := item.AsArrayValue(); err == nil { 858 ind, err := index.AsInt64() 859 if err != nil { 860 return FAULT, err 861 } 862 if ind < 0 || ind >= array.Len() { 863 return FAULT, errors.ERR_INDEX_OUT_OF_BOUND 864 } 865 866 val = array.Data[ind] 867 } else if struc, err := item.AsStructValue(); err == nil { 868 ind, err := index.AsInt64() 869 if err != nil { 870 return FAULT, err 871 } 872 if ind < 0 || ind >= struc.Len() { 873 return FAULT, errors.ERR_INDEX_OUT_OF_BOUND 874 } 875 val = struc.Data[ind] 876 } else if mapVal, err := item.AsMapValue(); err == nil { 877 value, ok, err := mapVal.Get(index) 878 if err != nil { 879 return FAULT, err 880 } else if !ok { 881 // todo: suply a nil value in vm? 882 return FAULT, errors.ERR_MAP_NOT_EXIST 883 } 884 val = value 885 } else if buf, err := item.AsBytes(); err == nil { 886 ind, err := index.AsInt64() 887 if err != nil { 888 return FAULT, err 889 } 890 if ind < 0 || ind >= int64(len(buf)) { 891 return FAULT, errors.ERR_INDEX_OUT_OF_BOUND 892 } 893 val = types.VmValueFromInt64(int64(buf[ind])) 894 } else { 895 return FAULT, errors.ERR_BAD_TYPE 896 } 897 898 err = self.EvalStack.Push(val) 899 if err != nil { 900 return FAULT, err 901 } 902 903 case SETITEM: 904 //todo: the original implementation for Struct type may have problem. 905 item, index, val, err := self.EvalStack.PopTriple() 906 if err != nil { 907 return FAULT, err 908 } 909 if s, err := val.AsStructValue(); err == nil { 910 t, err := s.Clone() 911 if err != nil { 912 return FAULT, err 913 } 914 val = types.VmValueFromStructVal(t) 915 } 916 if array, err := item.AsArrayValue(); err == nil { 917 ind, err := index.AsInt64() 918 if err != nil { 919 return FAULT, err 920 } 921 if ind < 0 || ind >= array.Len() { 922 return FAULT, errors.ERR_INDEX_OUT_OF_BOUND 923 } 924 925 array.Data[ind] = val 926 } else if struc, err := item.AsStructValue(); err == nil { 927 ind, err := index.AsInt64() 928 if err != nil { 929 return FAULT, err 930 } 931 if ind < 0 || ind >= struc.Len() { 932 return FAULT, errors.ERR_INDEX_OUT_OF_BOUND 933 } 934 935 struc.Data[ind] = val 936 } else if mapVal, err := item.AsMapValue(); err == nil { 937 err = mapVal.Set(index, val) 938 if err != nil { 939 return FAULT, err 940 } 941 } else { 942 return FAULT, errors.ERR_BAD_TYPE 943 } 944 case NEWARRAY: 945 count, err := self.EvalStack.PopAsInt64() 946 if err != nil { 947 return FAULT, err 948 } 949 if count < 0 || count > MAX_ARRAY_SIZE { 950 return FAULT, errors.ERR_BAD_VALUE 951 } 952 array := types.NewArrayValue() 953 for i := int64(0); i < count; i++ { 954 err = array.Append(types.VmValueFromBool(false)) 955 if err != nil { 956 return FAULT, err 957 } 958 } 959 err = self.EvalStack.Push(types.VmValueFromArrayVal(array)) 960 if err != nil { 961 return FAULT, err 962 } 963 case NEWSTRUCT: 964 count, err := self.EvalStack.PopAsInt64() 965 if err != nil { 966 return FAULT, err 967 } 968 if count < 0 || count > MAX_ARRAY_SIZE { 969 return FAULT, errors.ERR_BAD_VALUE 970 } 971 array := types.NewStructValue() 972 for i := int64(0); i < count; i++ { 973 err = array.Append(types.VmValueFromBool(false)) 974 if err != nil { 975 return FAULT, err 976 } 977 } 978 err = self.EvalStack.Push(types.VmValueFromStructVal(array)) 979 if err != nil { 980 return FAULT, err 981 } 982 case NEWMAP: 983 err := self.EvalStack.Push(types.NewMapVmValue()) 984 if err != nil { 985 return FAULT, err 986 } 987 case APPEND: 988 item, err := self.EvalStack.Pop() 989 if err != nil { 990 return FAULT, err 991 } 992 if s, err := item.AsStructValue(); err == nil { 993 t, err := s.Clone() 994 if err != nil { 995 return FAULT, err 996 } 997 item = types.VmValueFromStructVal(t) 998 } 999 val, err := self.EvalStack.Pop() 1000 switch val.GetType() { 1001 case types.StructType: 1002 array, _ := val.AsStructValue() 1003 err = array.Append(item) 1004 if err != nil { 1005 return FAULT, err 1006 } 1007 case types.ArrayType: 1008 array, _ := val.AsArrayValue() 1009 err = array.Append(item) 1010 if err != nil { 1011 return FAULT, err 1012 } 1013 default: 1014 return FAULT, fmt.Errorf("[executor] ExecuteOp APPEND error, unknown datatype") 1015 } 1016 case REVERSE: 1017 var data []types.VmValue 1018 item, err := self.EvalStack.Pop() 1019 if err != nil { 1020 return FAULT, err 1021 } 1022 if array, err := item.AsArrayValue(); err == nil { 1023 data = array.Data 1024 } else if struc, err := item.AsStructValue(); err == nil { 1025 data = struc.Data 1026 } else { 1027 return FAULT, errors.ERR_BAD_TYPE 1028 } 1029 1030 for i, j := 0, len(data)-1; i < j; i, j = i+1, j-1 { 1031 data[i], data[j] = data[j], data[i] 1032 } 1033 case REMOVE: 1034 item, index, err := self.EvalStack.PopPair() 1035 if err != nil { 1036 return FAULT, err 1037 } 1038 switch item.GetType() { 1039 case types.MapType: 1040 value, err := item.AsMapValue() 1041 if err != nil { 1042 return FAULT, err 1043 } 1044 err = value.Remove(index) 1045 if err != nil { 1046 return FAULT, err 1047 } 1048 case types.ArrayType: 1049 value, err := item.AsArrayValue() 1050 if err != nil { 1051 return FAULT, err 1052 } 1053 i, err := index.AsInt64() 1054 if err != nil { 1055 return FAULT, err 1056 } 1057 err = value.RemoveAt(i) 1058 if err != nil { 1059 return FAULT, err 1060 } 1061 default: 1062 return FAULT, fmt.Errorf("[REMOVE] not support datatype") 1063 } 1064 case HASKEY: 1065 item, key, err := self.EvalStack.PopPair() 1066 if err != nil { 1067 return FAULT, err 1068 } 1069 mapValue, err := item.AsMapValue() 1070 if err != nil { 1071 return FAULT, err 1072 } 1073 _, ok, err := mapValue.Get(key) 1074 if err != nil { 1075 return FAULT, err 1076 } 1077 err = self.EvalStack.Push(types.VmValueFromBool(ok)) 1078 if err != nil { 1079 return FAULT, err 1080 } 1081 case KEYS: 1082 item, err := self.EvalStack.Pop() 1083 if err != nil { 1084 return FAULT, err 1085 } 1086 mapValue, err := item.AsMapValue() 1087 if err != nil { 1088 return FAULT, err 1089 } 1090 keys := mapValue.GetMapSortedKey() 1091 arr := types.NewArrayValue() 1092 for _, v := range keys { 1093 err = arr.Append(v) 1094 if err != nil { 1095 return FAULT, err 1096 } 1097 } 1098 err = self.EvalStack.Push(types.VmValueFromArrayVal(arr)) 1099 if err != nil { 1100 return FAULT, err 1101 } 1102 case VALUES: 1103 item, err := self.EvalStack.Pop() 1104 if err != nil { 1105 return FAULT, err 1106 } 1107 mapVal, err := item.AsMapValue() 1108 if err != nil { 1109 return FAULT, err 1110 } 1111 vals, err := mapVal.GetValues() 1112 arr := types.NewArrayValue() 1113 for _, v := range vals { 1114 err := arr.Append(v) 1115 if err != nil { 1116 return FAULT, err 1117 } 1118 } 1119 err = self.EvalStack.Push(types.VmValueFromArrayVal(arr)) 1120 if err != nil { 1121 return FAULT, err 1122 } 1123 case THROW: 1124 return FAULT, nil 1125 case THROWIFNOT: 1126 val, err := self.EvalStack.PopAsBool() 1127 if err != nil { 1128 return FAULT, err 1129 } 1130 if !val { 1131 return FAULT, nil 1132 } 1133 default: 1134 return FAULT, errors.ERR_NOT_SUPPORT_OPCODE 1135 } 1136 1137 return NONE, nil 1138 }