示例#1
0
 public bool RemoveBreakPoint(uint position)
 {
     if (InvocationStack.Count == 0)
     {
         return(false);
     }
     return(InvocationStack.Peek().BreakPoints.Remove(position));
 }
示例#2
0
        public void StepInto()
        {
            if (InvocationStack.Count == 0)
            {
                State |= VMState.HALT;
            }
            if (State.HasFlag(VMState.HALT) || State.HasFlag(VMState.FAULT))
            {
                return;
            }
            ExecutionContext context = InvocationStack.Peek();
            OpCode           opcode  = context.InstructionPointer >= context.Script.Length ? OpCode.RET : (OpCode)context.OpReader.ReadByte();

            nOpCount++;
            try
            {
                ExecuteOp(opcode, context);
            }
            catch (Exception ex) when(ex is EndOfStreamException || ex is InvalidOperationException)
            {
                State |= VMState.FAULT;
            }
        }
示例#3
0
        private void ExecuteOp(OpCode opcode, ExecutionContext context)
        {
            if (opcode > OpCode.PUSH16 && opcode != OpCode.RET && context.PushOnly)
            {
                State |= VMState.FAULT;
                return;
            }
            if (opcode > OpCode.PUSH16 && nOpCount > max_steps)
            {
                State |= VMState.FAULT | VMState.INSUFFICIENT_RESOURCE;
                return;
            }
            if (opcode >= OpCode.PUSHBYTES1 && opcode <= OpCode.PUSHBYTES75)
            {
                EvaluationStack.Push(context.OpReader.ReadBytes((byte)opcode));
            }
            else
            {
                switch (opcode)
                {
                // Push value
                case OpCode.PUSH0:
                    EvaluationStack.Push(new byte[0]);
                    break;

                case OpCode.PUSHDATA1:
                    EvaluationStack.Push(context.OpReader.ReadBytes(context.OpReader.ReadByte()));
                    break;

                case OpCode.PUSHDATA2:
                    EvaluationStack.Push(context.OpReader.ReadBytes(context.OpReader.ReadUInt16()));
                    break;

                case OpCode.PUSHDATA4:
                    EvaluationStack.Push(context.OpReader.ReadBytes(context.OpReader.ReadInt32()));
                    break;

                case OpCode.PUSHM1:
                case OpCode.PUSH1:
                case OpCode.PUSH2:
                case OpCode.PUSH3:
                case OpCode.PUSH4:
                case OpCode.PUSH5:
                case OpCode.PUSH6:
                case OpCode.PUSH7:
                case OpCode.PUSH8:
                case OpCode.PUSH9:
                case OpCode.PUSH10:
                case OpCode.PUSH11:
                case OpCode.PUSH12:
                case OpCode.PUSH13:
                case OpCode.PUSH14:
                case OpCode.PUSH15:
                case OpCode.PUSH16:
                    EvaluationStack.Push(opcode - OpCode.PUSH1 + 1);
                    break;

                // Control
                case OpCode.NOP:
                    break;

                case OpCode.JMP:
                case OpCode.JMPIF:
                case OpCode.JMPIFNOT:
                {
                    int offset = context.OpReader.ReadInt16();
                    offset = context.InstructionPointer + offset - 3;
                    if (offset < 0 || offset > context.Script.Length)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    bool fValue = true;
                    if (opcode > OpCode.JMP)
                    {
                        fValue = EvaluationStack.Pop().GetBoolean();
                        if (opcode == OpCode.JMPIFNOT)
                        {
                            fValue = !fValue;
                        }
                    }
                    if (fValue)
                    {
                        context.InstructionPointer = offset;
                    }
                }
                break;

                case OpCode.CALL:
                    InvocationStack.Push(context.Clone());
                    context.InstructionPointer += 2;
                    ExecuteOp(OpCode.JMP, InvocationStack.Peek());
                    break;

                case OpCode.RET:
                    InvocationStack.Pop().Dispose();
                    if (InvocationStack.Count == 0)
                    {
                        State |= VMState.HALT;
                    }
                    break;

                case OpCode.APPCALL:
                {
                    if (table == null)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    byte[] script_hash = context.OpReader.ReadBytes(20);
                    byte[] script      = table.GetScript(script_hash);
                    if (script == null)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    LoadScript(script);
                }
                break;

                case OpCode.SYSCALL:
                    if (!service.Invoke(Encoding.ASCII.GetString(context.OpReader.ReadVarBytes(252)), this))
                    {
                        State |= VMState.FAULT;
                    }
                    break;

                // Stack ops
                case OpCode.TOALTSTACK:
                    AltStack.Push(EvaluationStack.Pop());
                    break;

                case OpCode.FROMALTSTACK:
                    EvaluationStack.Push(AltStack.Pop());
                    break;

                case OpCode.XDROP:
                {
                    int n = (int)EvaluationStack.Pop().GetBigInteger();
                    if (n < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    EvaluationStack.Remove(n);
                }
                break;

                case OpCode.XSWAP:
                {
                    int n = (int)EvaluationStack.Pop().GetBigInteger();
                    if (n < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    if (n == 0)
                    {
                        break;
                    }
                    StackItem xn = EvaluationStack.Peek(n);
                    EvaluationStack.Set(n, EvaluationStack.Peek());
                    EvaluationStack.Set(0, xn);
                }
                break;

                case OpCode.XTUCK:
                {
                    int n = (int)EvaluationStack.Pop().GetBigInteger();
                    if (n <= 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    EvaluationStack.Insert(n, EvaluationStack.Peek());
                }
                break;

                case OpCode.DEPTH:
                    EvaluationStack.Push(EvaluationStack.Count);
                    break;

                case OpCode.DROP:
                    EvaluationStack.Pop();
                    break;

                case OpCode.DUP:
                    EvaluationStack.Push(EvaluationStack.Peek());
                    break;

                case OpCode.NIP:
                {
                    StackItem x2 = EvaluationStack.Pop();
                    EvaluationStack.Pop();
                    EvaluationStack.Push(x2);
                }
                break;

                case OpCode.OVER:
                {
                    StackItem x2 = EvaluationStack.Pop();
                    StackItem x1 = EvaluationStack.Peek();
                    EvaluationStack.Push(x2);
                    EvaluationStack.Push(x1);
                }
                break;

                case OpCode.PICK:
                {
                    int n = (int)EvaluationStack.Pop().GetBigInteger();
                    if (n < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    EvaluationStack.Push(EvaluationStack.Peek(n));
                }
                break;

                case OpCode.ROLL:
                {
                    int n = (int)EvaluationStack.Pop().GetBigInteger();
                    if (n < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    if (n == 0)
                    {
                        break;
                    }
                    EvaluationStack.Push(EvaluationStack.Remove(n));
                }
                break;

                case OpCode.ROT:
                {
                    StackItem x3 = EvaluationStack.Pop();
                    StackItem x2 = EvaluationStack.Pop();
                    StackItem x1 = EvaluationStack.Pop();
                    EvaluationStack.Push(x2);
                    EvaluationStack.Push(x3);
                    EvaluationStack.Push(x1);
                }
                break;

                case OpCode.SWAP:
                {
                    StackItem x2 = EvaluationStack.Pop();
                    StackItem x1 = EvaluationStack.Pop();
                    EvaluationStack.Push(x2);
                    EvaluationStack.Push(x1);
                }
                break;

                case OpCode.TUCK:
                {
                    StackItem x2 = EvaluationStack.Pop();
                    StackItem x1 = EvaluationStack.Pop();
                    EvaluationStack.Push(x2);
                    EvaluationStack.Push(x1);
                    EvaluationStack.Push(x2);
                }
                break;

                case OpCode.CAT:
                {
                    byte[] x2 = EvaluationStack.Pop().GetByteArray();
                    byte[] x1 = EvaluationStack.Pop().GetByteArray();
                    EvaluationStack.Push(x1.Concat(x2).ToArray());
                }
                break;

                case OpCode.SUBSTR:
                {
                    int count = (int)EvaluationStack.Pop().GetBigInteger();
                    if (count < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    int index = (int)EvaluationStack.Pop().GetBigInteger();
                    if (index < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    byte[] x = EvaluationStack.Pop().GetByteArray();
                    EvaluationStack.Push(x.Skip(index).Take(count).ToArray());
                }
                break;

                case OpCode.LEFT:
                {
                    int count = (int)EvaluationStack.Pop().GetBigInteger();
                    if (count < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    byte[] x = EvaluationStack.Pop().GetByteArray();
                    EvaluationStack.Push(x.Take(count).ToArray());
                }
                break;

                case OpCode.RIGHT:
                {
                    int count = (int)EvaluationStack.Pop().GetBigInteger();
                    if (count < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    byte[] x = EvaluationStack.Pop().GetByteArray();
                    if (x.Length < count)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    EvaluationStack.Push(x.Skip(x.Length - count).ToArray());
                }
                break;

                case OpCode.SIZE:
                {
                    byte[] x = EvaluationStack.Peek().GetByteArray();
                    EvaluationStack.Push(x.Length);
                }
                break;

                // Bitwise logic
                case OpCode.INVERT:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(~x);
                }
                break;

                case OpCode.AND:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 & x2);
                }
                break;

                case OpCode.OR:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 | x2);
                }
                break;

                case OpCode.XOR:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 ^ x2);
                }
                break;

                case OpCode.EQUAL:
                {
                    StackItem x2 = EvaluationStack.Pop();
                    StackItem x1 = EvaluationStack.Pop();
                    EvaluationStack.Push(x1.Equals(x2));
                }
                break;

                // Numeric
                case OpCode.INC:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x + 1);
                }
                break;

                case OpCode.DEC:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x - 1);
                }
                break;

                case OpCode.SAL:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x << 1);
                }
                break;

                case OpCode.SAR:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x >> 1);
                }
                break;

                case OpCode.NEGATE:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(-x);
                }
                break;

                case OpCode.ABS:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(BigInteger.Abs(x));
                }
                break;

                case OpCode.NOT:
                {
                    bool x = EvaluationStack.Pop().GetBoolean();
                    EvaluationStack.Push(!x);
                }
                break;

                case OpCode.NZ:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x != BigInteger.Zero);
                }
                break;

                case OpCode.ADD:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 + x2);
                }
                break;

                case OpCode.SUB:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 - x2);
                }
                break;

                case OpCode.MUL:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 * x2);
                }
                break;

                case OpCode.DIV:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 / x2);
                }
                break;

                case OpCode.MOD:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 % x2);
                }
                break;

                case OpCode.SHL:
                {
                    int        n = (int)EvaluationStack.Pop().GetBigInteger();
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x << n);
                }
                break;

                case OpCode.SHR:
                {
                    int        n = (int)EvaluationStack.Pop().GetBigInteger();
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x >> n);
                }
                break;

                case OpCode.BOOLAND:
                {
                    bool x2 = EvaluationStack.Pop().GetBoolean();
                    bool x1 = EvaluationStack.Pop().GetBoolean();
                    EvaluationStack.Push(x1 && x2);
                }
                break;

                case OpCode.BOOLOR:
                {
                    bool x2 = EvaluationStack.Pop().GetBoolean();
                    bool x1 = EvaluationStack.Pop().GetBoolean();
                    EvaluationStack.Push(x1 || x2);
                }
                break;

                case OpCode.NUMEQUAL:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 == x2);
                }
                break;

                case OpCode.NUMNOTEQUAL:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 != x2);
                }
                break;

                case OpCode.LT:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 < x2);
                }
                break;

                case OpCode.GT:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 > x2);
                }
                break;

                case OpCode.LTE:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 <= x2);
                }
                break;

                case OpCode.GTE:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x1 >= x2);
                }
                break;

                case OpCode.MIN:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(BigInteger.Min(x1, x2));
                }
                break;

                case OpCode.MAX:
                {
                    BigInteger x2 = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x1 = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(BigInteger.Max(x1, x2));
                }
                break;

                case OpCode.WITHIN:
                {
                    BigInteger b = EvaluationStack.Pop().GetBigInteger();
                    BigInteger a = EvaluationStack.Pop().GetBigInteger();
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(a <= x && x < b);
                }
                break;

                // Crypto
                case OpCode.SHA1:
                    using (SHA1 sha = SHA1.Create())
                    {
                        byte[] x = EvaluationStack.Pop().GetByteArray();
                        EvaluationStack.Push(sha.ComputeHash(x));
                    }
                    break;

                case OpCode.SHA256:
                    using (SHA256 sha = SHA256.Create())
                    {
                        byte[] x = EvaluationStack.Pop().GetByteArray();
                        EvaluationStack.Push(sha.ComputeHash(x));
                    }
                    break;

                case OpCode.HASH160:
                {
                    byte[] x = EvaluationStack.Pop().GetByteArray();
                    EvaluationStack.Push(Crypto.Hash160(x));
                }
                break;

                case OpCode.HASH256:
                {
                    byte[] x = EvaluationStack.Pop().GetByteArray();
                    EvaluationStack.Push(Crypto.Hash256(x));
                }
                break;

                case OpCode.CHECKSIG:
                {
                    byte[] pubkey    = EvaluationStack.Pop().GetByteArray();
                    byte[] signature = EvaluationStack.Pop().GetByteArray();
                    EvaluationStack.Push(Crypto.VerifySignature(ScriptContainer.GetMessage(), signature, pubkey));
                }
                break;

                case OpCode.CHECKMULTISIG:
                {
                    int n = (int)EvaluationStack.Pop().GetBigInteger();
                    if (n < 1)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    nOpCount += n;
                    if (nOpCount > max_steps)
                    {
                        State |= VMState.FAULT | VMState.INSUFFICIENT_RESOURCE;
                        return;
                    }
                    byte[][] pubkeys = new byte[n][];
                    for (int i = 0; i < n; i++)
                    {
                        pubkeys[i] = EvaluationStack.Pop().GetByteArray();
                    }
                    int m = (int)EvaluationStack.Pop().GetBigInteger();
                    if (m < 1 || m > n)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    byte[][] signatures = new byte[m][];
                    for (int i = 0; i < m; i++)
                    {
                        signatures[i] = EvaluationStack.Pop().GetByteArray();
                    }
                    byte[] message  = ScriptContainer.GetMessage();
                    bool   fSuccess = true;
                    for (int i = 0, j = 0; fSuccess && i < m && j < n;)
                    {
                        if (Crypto.VerifySignature(message, signatures[i], pubkeys[j]))
                        {
                            i++;
                        }
                        j++;
                        if (m - i > n - j)
                        {
                            fSuccess = false;
                        }
                    }
                    EvaluationStack.Push(fSuccess);
                }
                break;

                // Array
                case OpCode.ARRAYSIZE:
                    EvaluationStack.Push(EvaluationStack.Pop().ArraySize);
                    break;

                case OpCode.PACK:
                {
                    int size = (int)EvaluationStack.Pop().GetBigInteger();
                    if (size < 0 || size > EvaluationStack.Count)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    StackItem[] items = new StackItem[size];
                    for (int i = 0; i < size; i++)
                    {
                        items[i] = EvaluationStack.Pop();
                    }
                    EvaluationStack.Push(items);
                }
                break;

                case OpCode.UNPACK:
                {
                    StackItem[] items = EvaluationStack.Pop().GetArray();
                    for (int i = items.Length - 1; i >= 0; i--)
                    {
                        EvaluationStack.Push(items[i]);
                    }
                    EvaluationStack.Push(items.Length);
                }
                break;

                case OpCode.PICKITEM:
                {
                    int index = (int)EvaluationStack.Pop().GetBigInteger();
                    if (index < 0)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    StackItem[] items = EvaluationStack.Pop().GetArray();
                    if (index >= items.Length)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    EvaluationStack.Push(items[index]);
                }
                break;

                default:
                    State |= VMState.FAULT;
                    return;
                }
            }
            if (InvocationStack.Count > 0)
            {
                context = InvocationStack.Peek();
                if (context.BreakPoints.Contains((uint)context.InstructionPointer))
                {
                    State |= VMState.BREAK;
                }
            }
        }
示例#4
0
 public void AddBreakPoint(uint position)
 {
     InvocationStack.Peek().BreakPoints.Add(position);
 }