Beispiel #1
0
        protected internal bool CheckWitnessInternal(UInt160 hash)
        {
            if (hash.Equals(CallingScriptHash))
            {
                return(true);
            }

            if (ScriptContainer is Transaction tx)
            {
                Signer[]       signers;
                OracleResponse response = tx.GetAttribute <OracleResponse>();
                if (response is null)
                {
                    signers = tx.Signers;
                }
                else
                {
                    OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id);
                    signers = Snapshot.GetTransaction(request.OriginalTxid).Signers;
                }
                Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash));
                if (signer is null)
                {
                    return(false);
                }
                if (signer.Scopes == WitnessScope.Global)
                {
                    return(true);
                }
                if (signer.Scopes.HasFlag(WitnessScope.CalledByEntry))
                {
                    if (CallingScriptHash == null || CallingScriptHash == EntryScriptHash)
                    {
                        return(true);
                    }
                }
                if (signer.Scopes.HasFlag(WitnessScope.CustomContracts))
                {
                    if (signer.AllowedContracts.Contains(CurrentScriptHash))
                    {
                        return(true);
                    }
                }
                if (signer.Scopes.HasFlag(WitnessScope.CustomGroups))
                {
                    // Check allow state callflag

                    if (!CurrentContext.GetState <ExecutionContextState>().CallFlags.HasFlag(CallFlags.ReadStates))
                    {
                        throw new InvalidOperationException($"Cannot call this SYSCALL without the flag AllowStates.");
                    }

                    var contract = NativeContract.ContractManagement.GetContract(Snapshot, CallingScriptHash);
                    // check if current group is the required one
                    if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(signer.AllowedGroups).Any())
                    {
                        return(true);
                    }
                }
                return(false);
            }

            // Check allow state callflag

            if (!CurrentContext.GetState <ExecutionContextState>().CallFlags.HasFlag(CallFlags.ReadStates))
            {
                throw new InvalidOperationException($"Cannot call this SYSCALL without the flag AllowStates.");
            }

            // only for non-Transaction types (Block, etc)

            var hashes_for_verifying = ScriptContainer.GetScriptHashesForVerifying(Snapshot);

            return(hashes_for_verifying.Contains(hash));
        }
Beispiel #2
0
        private void ExecuteOp(OpCode opcode, ExecutionContext context)
        {
            if (opcode > OpCode.PUSH16 && opcode != OpCode.RET && context.PushOnly)
            {
                State |= VMState.FAULT;
                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((int)opcode - (int)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, CurrentContext);
                    break;

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

                case OpCode.APPCALL:
                case OpCode.TAILCALL:
                {
                    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;
                    }
                    if (opcode == OpCode.TAILCALL)
                    {
                        InvocationStack.Pop().Dispose();
                    }
                    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.DUPFROMALTSTACK:
                    EvaluationStack.Push(AltStack.Peek());
                    break;

                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.Pop().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.SIGN:
                {
                    BigInteger x = EvaluationStack.Pop().GetBigInteger();
                    EvaluationStack.Push(x.Sign);
                }
                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();
                    try
                    {
                        EvaluationStack.Push(Crypto.VerifySignature(ScriptContainer.GetMessage(), signature, pubkey));
                    }
                    catch (ArgumentException)
                    {
                        EvaluationStack.Push(false);
                    }
                }
                break;

                case OpCode.CHECKMULTISIG:
                {
                    int       n;
                    byte[][]  pubkeys;
                    StackItem item = EvaluationStack.Pop();
                    if (item.IsArray)
                    {
                        pubkeys = item.GetArray().Select(p => p.GetByteArray()).ToArray();
                        n       = pubkeys.Length;
                        if (n == 0)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                    }
                    else
                    {
                        n = (int)item.GetBigInteger();
                        if (n < 1)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        pubkeys = new byte[n][];
                        for (int i = 0; i < n; i++)
                        {
                            pubkeys[i] = EvaluationStack.Pop().GetByteArray();
                        }
                    }
                    int      m;
                    byte[][] signatures;
                    item = EvaluationStack.Pop();
                    if (item.IsArray)
                    {
                        signatures = item.GetArray().Select(p => p.GetByteArray()).ToArray();
                        m          = signatures.Length;
                        if (m == 0 || m > n)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                    }
                    else
                    {
                        m = (int)item.GetBigInteger();
                        if (m < 1 || m > n)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        signatures = new byte[m][];
                        for (int i = 0; i < m; i++)
                        {
                            signatures[i] = EvaluationStack.Pop().GetByteArray();
                        }
                    }
                    byte[] message  = ScriptContainer.GetMessage();
                    bool   fSuccess = true;
                    try
                    {
                        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;
                            }
                        }
                    }
                    catch (ArgumentException)
                    {
                        fSuccess = false;
                    }
                    EvaluationStack.Push(fSuccess);
                }
                break;

                // Array
                case OpCode.ARRAYSIZE:
                {
                    StackItem item = EvaluationStack.Pop();
                    if (!item.IsArray)
                    {
                        EvaluationStack.Push(item.GetByteArray().Length);
                    }
                    else
                    {
                        EvaluationStack.Push(item.GetArray().Length);
                    }
                }
                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 item = EvaluationStack.Pop();
                    if (!item.IsArray)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    StackItem[] items = item.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 item = EvaluationStack.Pop();
                    if (!item.IsArray)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    StackItem[] items = item.GetArray();
                    if (index >= items.Length)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    EvaluationStack.Push(items[index]);
                }
                break;

                case OpCode.SETITEM:
                {
                    StackItem newItem = EvaluationStack.Pop();
                    if (newItem.IsStruct)
                    {
                        newItem = (newItem as Types.Struct).Clone();
                    }
                    int       index   = (int)EvaluationStack.Pop().GetBigInteger();
                    StackItem arrItem = EvaluationStack.Pop();
                    if (!arrItem.IsArray)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    StackItem[] items = arrItem.GetArray();
                    if (index < 0 || index >= items.Length)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    items[index] = newItem;
                }
                break;

                case OpCode.NEWARRAY:
                {
                    int         count = (int)EvaluationStack.Pop().GetBigInteger();
                    StackItem[] items = new StackItem[count];
                    for (var i = 0; i < count; i++)
                    {
                        items[i] = false;
                    }
                    EvaluationStack.Push(new Types.Array(items));
                }
                break;

                case OpCode.NEWSTRUCT:
                {
                    int         count = (int)EvaluationStack.Pop().GetBigInteger();
                    StackItem[] items = new StackItem[count];
                    for (var i = 0; i < count; i++)
                    {
                        items[i] = false;
                    }
                    EvaluationStack.Push(new VM.Types.Struct(items));
                }
                break;

                // Exceptions
                case OpCode.THROW:
                    State |= VMState.FAULT;
                    return;

                case OpCode.THROWIFNOT:
                    if (!EvaluationStack.Pop().GetBoolean())
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    break;

                default:
                    State |= VMState.FAULT;
                    return;
                }
            }
            if (!State.HasFlag(VMState.FAULT) && InvocationStack.Count > 0)
            {
                if (CurrentContext.BreakPoints.Contains((uint)CurrentContext.InstructionPointer))
                {
                    State |= VMState.BREAK;
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Returns an empty string
        /// </summary>
        /// <returns>Empty string</returns>
        protected virtual string CreateScriptContainerSource(ScriptContainer container)
        {
            CodeCompileUnit unit = new CodeCompileUnit();
            CodeNamespace ns = new CodeNamespace("CANAPE.Scripting");

            CodeTypeDeclaration decl = new CodeTypeDeclaration("Runtime");
            decl.Attributes = MemberAttributes.Public | MemberAttributes.Static;

            CodeTypeReference propType = new CodeTypeReference(typeof(ScriptContainer));

            CodeMemberProperty prop = new CodeMemberProperty();
            prop.Name = "Script";
            prop.Type = propType;
            prop.Attributes = MemberAttributes.Public | MemberAttributes.Static;

            CodeObjectCreateExpression createObject = new CodeObjectCreateExpression(
                    propType, new CodePrimitiveExpression(container.Engine),
                    new CodeObjectCreateExpression(new CodeTypeReference(typeof(Guid)), new CodePrimitiveExpression(container.Uuid.ToString())),
                    new CodePrimitiveExpression(container.Script), new CodePrimitiveExpression(container.EnableDebug));

            prop.GetStatements.Add(new CodeMethodReturnStatement(createObject));

            decl.Members.Add(prop);

            ns.Types.Add(decl);

            unit.Namespaces.Add(ns);

            return GenerateCode(unit);
        }
Beispiel #4
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public override ScriptError[] Parse(ScriptContainer container)
        {
            List<ScriptError> errors = new List<ScriptError>();

            try
            {
                CompilerParameters compileParams = new CompilerParameters();
                TempFileCollection tempFiles = new TempFileCollection(Path.GetTempPath(), container.EnableDebug);

                compileParams.GenerateExecutable = false;
                compileParams.GenerateInMemory = true;
                compileParams.IncludeDebugInformation = true;
                compileParams.TempFiles = tempFiles;
                compileParams.ReferencedAssemblies.Add("System.dll");
                compileParams.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
                compileParams.ReferencedAssemblies.Add("System.Core.dll");
                compileParams.ReferencedAssemblies.Add("System.Numerics.dll");

                foreach (AssemblyName name in container.ReferencedNames)
                {
                    Assembly asm = Assembly.Load(name);

                    if (!String.IsNullOrWhiteSpace(asm.Location))
                    {
                        compileParams.ReferencedAssemblies.Add(asm.Location);
                    }
                    else
                    {
                        byte[] assemblyData = GetDataForAssembly(name);

                        if (assemblyData != null)
                        {
                            string fileName = Path.GetTempFileName();
                            File.WriteAllBytes(fileName, assemblyData);

                            tempFiles.AddFile(fileName, false);

                            compileParams.ReferencedAssemblies.Add(fileName);
                        }
                        else
                        {
                            errors.Add(new ScriptError(String.Format(Properties.Resources.DotNetScriptEngine_CannotGetAssemblyLocation, name),
                                Properties.Resources.Scripting_Warning, 1, 1));
                        }
                    }
                }

                if (!String.IsNullOrEmpty(_options))
                {
                    compileParams.CompilerOptions = _options;
                }

                List<string> scripts = new List<string>();
                scripts.Add(container.Script);

                string src = CreateScriptContainerSource(container);
                if (!String.IsNullOrWhiteSpace(src))
                {
                    scripts.Add(src);
                }

                CompilerResults results = _provider.CompileAssemblyFromSource(compileParams, scripts.ToArray());
                if (results.Errors.HasErrors)
                {
                    foreach (CompilerError e in results.Errors)
                    {
                        errors.Add(new ScriptError(e.ErrorText, Properties.Resources.Scripting_Error, e.Line, e.Column));
                    }
                }
                else
                {
                    _assembly = results.CompiledAssembly;
                }

                if (container.EnableDebug)
                {
                    foreach (string file in tempFiles)
                    {
                        ScriptUtils.AddTempFile(file);
                    }
                }
            }
            catch (Exception ex)
            {
                errors.Add(new ScriptError(String.Format(Properties.Resources.DotNetScriptEngine_CompileException, ex.Message), Properties.Resources.Scripting_FatalError, 0, 0));
            }

            // Test Code
            foreach(ScriptError error in errors)
            {
                System.Diagnostics.Trace.WriteLine(error.Description);
            }

            return errors.ToArray();
        }
Beispiel #5
0
 public static void LandMineRiseFall_Init(ScriptContainer scriptContainer, float fuseTime)
 {
     scriptContainer.PropertyBag.SetValue(LandMineFuseTimeId, fuseTime);
 }
Beispiel #6
0
 public ScriptParserType(string name, string engine, string script)
     : base(name)
 {
     _script = new DummyScriptContainer(this, engine, script);
 }
 public DummyScriptDocument(ScriptContainer script)
 {
     _script = script;
 }
Beispiel #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public override ScriptError[] Parse(ScriptContainer container)
        {
            List <ScriptError> errors = new List <ScriptError>();

            try
            {
                CompilerParameters compileParams = new CompilerParameters();
                TempFileCollection tempFiles     = new TempFileCollection(Path.GetTempPath(), container.EnableDebug);

                compileParams.GenerateExecutable      = false;
                compileParams.GenerateInMemory        = true;
                compileParams.IncludeDebugInformation = true;
                compileParams.TempFiles = tempFiles;
                compileParams.ReferencedAssemblies.Add("System.dll");
                compileParams.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
                compileParams.ReferencedAssemblies.Add("System.Core.dll");
                compileParams.ReferencedAssemblies.Add("System.Numerics.dll");

                foreach (AssemblyName name in container.ReferencedNames)
                {
                    Assembly asm = Assembly.Load(name);

                    if (!String.IsNullOrWhiteSpace(asm.Location))
                    {
                        compileParams.ReferencedAssemblies.Add(asm.Location);
                    }
                    else
                    {
                        byte[] assemblyData = GetDataForAssembly(name);

                        if (assemblyData != null)
                        {
                            string fileName = Path.GetTempFileName();
                            File.WriteAllBytes(fileName, assemblyData);

                            tempFiles.AddFile(fileName, false);

                            compileParams.ReferencedAssemblies.Add(fileName);
                        }
                        else
                        {
                            errors.Add(new ScriptError(String.Format(Properties.Resources.DotNetScriptEngine_CannotGetAssemblyLocation, name),
                                                       Properties.Resources.Scripting_Warning, 1, 1));
                        }
                    }
                }

                if (!String.IsNullOrEmpty(_options))
                {
                    compileParams.CompilerOptions = _options;
                }

                List <string> scripts = new List <string>();
                scripts.Add(container.Script);

                string src = CreateScriptContainerSource(container);
                if (!String.IsNullOrWhiteSpace(src))
                {
                    scripts.Add(src);
                }

                CompilerResults results = _provider.CompileAssemblyFromSource(compileParams, scripts.ToArray());
                if (results.Errors.HasErrors)
                {
                    foreach (CompilerError e in results.Errors)
                    {
                        errors.Add(new ScriptError(e.ErrorText, Properties.Resources.Scripting_Error, e.Line, e.Column));
                    }
                }
                else
                {
                    _assembly = results.CompiledAssembly;
                }

                if (container.EnableDebug)
                {
                    foreach (string file in tempFiles)
                    {
                        ScriptUtils.AddTempFile(file);
                    }
                }
            }
            catch (Exception ex)
            {
                errors.Add(new ScriptError(String.Format(Properties.Resources.DotNetScriptEngine_CompileException, ex.Message), Properties.Resources.Scripting_FatalError, 0, 0));
            }

            // Test Code
            foreach (ScriptError error in errors)
            {
                System.Diagnostics.Trace.WriteLine(error.Description);
            }

            return(errors.ToArray());
        }
Beispiel #9
0
 protected void Page_Init()
 {
     if (scriptTemplate != null)
     {
         ScriptWrapperStart.Visible = ScriptWrapperEnd.Visible = true;
         ScriptContainer container = new ScriptContainer(_SLIDER.ClientID);
         scriptTemplate.InstantiateIn(container);
         ScriptPlaceHolder.Controls.Add(container);
     }
 }
Beispiel #10
0
 public static void Pulsate_Init(ScriptContainer scriptContainer, float period)
 {
     scriptContainer.PropertyBag.SetValue(PulsatePeriodId, period);
 }
Beispiel #11
0
        private void ExecuteOp(OpCode opcode, ExecutionContext context)
        {
            if (opcode >= OpCode.PUSHBYTES1 && opcode <= OpCode.PUSHBYTES75)
            {
                context.EvaluationStack.Push(context.OpReader.ReadBytes((byte)opcode));
            }
            else
            {
                switch (opcode)
                {
                // Push value
                case OpCode.PUSH0:
                    context.EvaluationStack.Push(new byte[0]);
                    break;

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

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

                case OpCode.PUSHDATA4:
                    context.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:
                    context.EvaluationStack.Push((int)opcode - (int)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 = context.EvaluationStack.Pop().GetBoolean();
                        if (opcode == OpCode.JMPIFNOT)
                        {
                            fValue = !fValue;
                        }
                    }
                    if (fValue)
                    {
                        context.InstructionPointer = offset;
                    }
                }
                break;

                case OpCode.CALL:
                {
                    ExecutionContext context_call = LoadScript(context.Script);
                    context.EvaluationStack.CopyTo(context_call.EvaluationStack);
                    context_call.InstructionPointer = context.InstructionPointer;
                    context.EvaluationStack.Clear();
                    context.InstructionPointer += 2;
                    ExecuteOp(OpCode.JMP, context_call);
                }
                break;

                case OpCode.RET:
                    using (ExecutionContext context_pop = InvocationStack.Pop())
                    {
                        int rvcount = context_pop.RVCount;
                        if (rvcount == -1)
                        {
                            rvcount = context_pop.EvaluationStack.Count;
                        }
                        if (rvcount > 0)
                        {
                            if (context_pop.EvaluationStack.Count < rvcount)
                            {
                                State |= VMState.FAULT;
                                return;
                            }
                            RandomAccessStack <StackItem> stack_eval;
                            if (InvocationStack.Count == 0)
                            {
                                stack_eval = ResultStack;
                            }
                            else
                            {
                                stack_eval = CurrentContext.EvaluationStack;
                            }
                            context_pop.EvaluationStack.CopyTo(stack_eval, rvcount);
                        }
                    }
                    if (InvocationStack.Count == 0)
                    {
                        State |= VMState.HALT;
                    }
                    break;

                case OpCode.APPCALL:
                case OpCode.TAILCALL:
                {
                    if (table == null)
                    {
                        State |= VMState.FAULT;
                        return;
                    }

                    byte[] script_hash = context.OpReader.ReadBytes(20);
                    if (script_hash.All(p => p == 0))
                    {
                        script_hash = context.EvaluationStack.Pop().GetByteArray();
                    }

                    byte[] script = table.GetScript(script_hash);
                    if (script == null)
                    {
                        State |= VMState.FAULT;
                        return;
                    }

                    ExecutionContext context_new = LoadScript(script);
                    context.EvaluationStack.CopyTo(context_new.EvaluationStack);

                    if (opcode == OpCode.TAILCALL)
                    {
                        InvocationStack.Remove(1).Dispose();
                    }
                    else
                    {
                        context.EvaluationStack.Clear();
                    }
                }
                break;

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

                // Stack ops
                case OpCode.DUPFROMALTSTACK:
                    context.EvaluationStack.Push(context.AltStack.Peek());
                    break;

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

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

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

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

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

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

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

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

                case OpCode.NIP:
                    context.EvaluationStack.Remove(1);
                    break;

                case OpCode.OVER:
                    context.EvaluationStack.Push(context.EvaluationStack.Peek(1));
                    break;

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

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

                case OpCode.ROT:
                    context.EvaluationStack.Push(context.EvaluationStack.Remove(2));
                    break;

                case OpCode.SWAP:
                    context.EvaluationStack.Push(context.EvaluationStack.Remove(1));
                    break;

                case OpCode.TUCK:
                    context.EvaluationStack.Insert(2, context.EvaluationStack.Peek());
                    break;

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

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

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

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

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

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

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

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

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

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

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

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

                case OpCode.SIGN:
                {
                    BigInteger x = context.EvaluationStack.Pop().GetBigInteger();
                    context.EvaluationStack.Push(x.Sign);
                }
                break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                case OpCode.VERIFY:
                {
                    byte[] pubkey    = context.EvaluationStack.Pop().GetByteArray();
                    byte[] signature = context.EvaluationStack.Pop().GetByteArray();
                    byte[] message   = context.EvaluationStack.Pop().GetByteArray();
                    try
                    {
                        context.EvaluationStack.Push(Crypto.VerifySignature(message, signature, pubkey));
                    }
                    catch (ArgumentException)
                    {
                        context.EvaluationStack.Push(false);
                    }
                }
                break;

                case OpCode.CHECKMULTISIG:
                {
                    int       n;
                    byte[][]  pubkeys;
                    StackItem item = context.EvaluationStack.Pop();
                    if (item is VMArray array1)
                    {
                        pubkeys = array1.Select(p => p.GetByteArray()).ToArray();
                        n       = pubkeys.Length;
                        if (n == 0)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                    }
                    else
                    {
                        n = (int)item.GetBigInteger();
                        if (n < 1 || n > context.EvaluationStack.Count)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        pubkeys = new byte[n][];
                        for (int i = 0; i < n; i++)
                        {
                            pubkeys[i] = context.EvaluationStack.Pop().GetByteArray();
                        }
                    }
                    int      m;
                    byte[][] signatures;
                    item = context.EvaluationStack.Pop();
                    if (item is VMArray array2)
                    {
                        signatures = array2.Select(p => p.GetByteArray()).ToArray();
                        m          = signatures.Length;
                        if (m == 0 || m > n)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                    }
                    else
                    {
                        m = (int)item.GetBigInteger();
                        if (m < 1 || m > n || m > context.EvaluationStack.Count)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        signatures = new byte[m][];
                        for (int i = 0; i < m; i++)
                        {
                            signatures[i] = context.EvaluationStack.Pop().GetByteArray();
                        }
                    }
                    byte[] message  = ScriptContainer.GetMessage();
                    bool   fSuccess = true;
                    try
                    {
                        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;
                            }
                        }
                    }
                    catch (ArgumentException)
                    {
                        fSuccess = false;
                    }
                    context.EvaluationStack.Push(fSuccess);
                }
                break;

                // Array
                case OpCode.ARRAYSIZE:
                {
                    StackItem item = context.EvaluationStack.Pop();
                    if (item is ICollection collection)
                    {
                        context.EvaluationStack.Push(collection.Count);
                    }
                    else
                    {
                        context.EvaluationStack.Push(item.GetByteArray().Length);
                    }
                }
                break;

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

                case OpCode.UNPACK:
                {
                    StackItem item = context.EvaluationStack.Pop();
                    if (item is VMArray array)
                    {
                        for (int i = array.Count - 1; i >= 0; i--)
                        {
                            context.EvaluationStack.Push(array[i]);
                        }
                        context.EvaluationStack.Push(array.Count);
                    }
                    else
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.PICKITEM:
                {
                    StackItem key = context.EvaluationStack.Pop();
                    if (key is ICollection)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    switch (context.EvaluationStack.Pop())
                    {
                    case VMArray array:
                        int index = (int)key.GetBigInteger();
                        if (index < 0 || index >= array.Count)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        context.EvaluationStack.Push(array[index]);
                        break;

                    case Map map:
                        if (map.TryGetValue(key, out StackItem value))
                        {
                            context.EvaluationStack.Push(value);
                        }
                        else
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        break;

                    default:
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.SETITEM:
                {
                    StackItem value = context.EvaluationStack.Pop();
                    if (value is Struct s)
                    {
                        value = s.Clone();
                    }
                    StackItem key = context.EvaluationStack.Pop();
                    if (key is ICollection)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    switch (context.EvaluationStack.Pop())
                    {
                    case VMArray array:
                        int index = (int)key.GetBigInteger();
                        if (index < 0 || index >= array.Count)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        array[index] = value;
                        break;

                    case Map map:
                        map[key] = value;
                        break;

                    default:
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.NEWARRAY:
                {
                    int count = (int)context.EvaluationStack.Pop().GetBigInteger();
                    List <StackItem> items = new List <StackItem>(count);
                    for (var i = 0; i < count; i++)
                    {
                        items.Add(false);
                    }
                    context.EvaluationStack.Push(new Types.Array(items));
                }
                break;

                case OpCode.NEWSTRUCT:
                {
                    int count = (int)context.EvaluationStack.Pop().GetBigInteger();
                    List <StackItem> items = new List <StackItem>(count);
                    for (var i = 0; i < count; i++)
                    {
                        items.Add(false);
                    }
                    context.EvaluationStack.Push(new VM.Types.Struct(items));
                }
                break;

                case OpCode.NEWMAP:
                    context.EvaluationStack.Push(new Map());
                    break;

                case OpCode.APPEND:
                {
                    StackItem newItem = context.EvaluationStack.Pop();
                    if (newItem is Types.Struct s)
                    {
                        newItem = s.Clone();
                    }
                    StackItem arrItem = context.EvaluationStack.Pop();
                    if (arrItem is VMArray array)
                    {
                        array.Add(newItem);
                    }
                    else
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.REVERSE:
                {
                    StackItem arrItem = context.EvaluationStack.Pop();
                    if (arrItem is VMArray array)
                    {
                        array.Reverse();
                    }
                    else
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.REMOVE:
                {
                    StackItem key = context.EvaluationStack.Pop();
                    if (key is ICollection)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    switch (context.EvaluationStack.Pop())
                    {
                    case VMArray array:
                        int index = (int)key.GetBigInteger();
                        if (index < 0 || index >= array.Count)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        array.RemoveAt(index);
                        break;

                    case Map map:
                        map.Remove(key);
                        break;

                    default:
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.HASKEY:
                {
                    StackItem key = context.EvaluationStack.Pop();
                    if (key is ICollection)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    switch (context.EvaluationStack.Pop())
                    {
                    case VMArray array:
                        int index = (int)key.GetBigInteger();
                        if (index < 0)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                        context.EvaluationStack.Push(index < array.Count);
                        break;

                    case Map map:
                        context.EvaluationStack.Push(map.ContainsKey(key));
                        break;

                    default:
                        State |= VMState.FAULT;
                        return;
                    }
                }
                break;

                case OpCode.KEYS:
                    switch (context.EvaluationStack.Pop())
                    {
                    case Map map:
                        context.EvaluationStack.Push(new VMArray(map.Keys));
                        break;

                    default:
                        State |= VMState.FAULT;
                        return;
                    }
                    break;

                case OpCode.VALUES:
                {
                    ICollection <StackItem> values;
                    switch (context.EvaluationStack.Pop())
                    {
                    case VMArray array:
                        values = array;
                        break;

                    case Map map:
                        values = map.Values;
                        break;

                    default:
                        State |= VMState.FAULT;
                        return;
                    }
                    List <StackItem> newArray = new List <StackItem>(values.Count);
                    foreach (StackItem item in values)
                    {
                        if (item is Struct s)
                        {
                            newArray.Add(s.Clone());
                        }
                        else
                        {
                            newArray.Add(item);
                        }
                    }
                    context.EvaluationStack.Push(new VMArray(newArray));
                }
                break;

                // Stack isolation
                case OpCode.CALL_I:
                {
                    int rvcount = context.OpReader.ReadByte();
                    int pcount  = context.OpReader.ReadByte();
                    if (context.EvaluationStack.Count < pcount)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    ExecutionContext context_call = LoadScript(context.Script, rvcount);
                    context.EvaluationStack.CopyTo(context_call.EvaluationStack, pcount);
                    context_call.InstructionPointer = context.InstructionPointer;
                    for (int i = 0; i < pcount; i++)
                    {
                        context.EvaluationStack.Pop();
                    }
                    context.InstructionPointer += 2;
                    ExecuteOp(OpCode.JMP, context_call);
                }
                break;

                case OpCode.CALL_E:
                case OpCode.CALL_ED:
                case OpCode.CALL_ET:
                case OpCode.CALL_EDT:
                {
                    if (table == null)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    int rvcount = context.OpReader.ReadByte();
                    int pcount  = context.OpReader.ReadByte();
                    if (context.EvaluationStack.Count < pcount)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    if (opcode == OpCode.CALL_ET || opcode == OpCode.CALL_EDT)
                    {
                        if (context.RVCount != rvcount)
                        {
                            State |= VMState.FAULT;
                            return;
                        }
                    }
                    byte[] script_hash;
                    if (opcode == OpCode.CALL_ED || opcode == OpCode.CALL_EDT)
                    {
                        script_hash = context.EvaluationStack.Pop().GetByteArray();
                    }
                    else
                    {
                        script_hash = context.OpReader.ReadBytes(20);
                    }
                    byte[] script = table.GetScript(script_hash);
                    if (script == null)
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    ExecutionContext context_new = LoadScript(script, rvcount);
                    context.EvaluationStack.CopyTo(context_new.EvaluationStack, pcount);
                    if (opcode == OpCode.CALL_ET || opcode == OpCode.CALL_EDT)
                    {
                        InvocationStack.Remove(1).Dispose();
                    }
                    else
                    {
                        for (int i = 0; i < pcount; i++)
                        {
                            context.EvaluationStack.Pop();
                        }
                    }
                }
                break;

                // Exceptions
                case OpCode.THROW:
                    State |= VMState.FAULT;
                    return;

                case OpCode.THROWIFNOT:
                    if (!context.EvaluationStack.Pop().GetBoolean())
                    {
                        State |= VMState.FAULT;
                        return;
                    }
                    break;

                default:
                    State |= VMState.FAULT;
                    return;
                }
            }
            if (!State.HasFlag(VMState.FAULT) && InvocationStack.Count > 0)
            {
                if (break_points.TryGetValue(CurrentContext.ScriptHash, out HashSet <uint> hashset) && hashset.Contains((uint)CurrentContext.InstructionPointer))
                {
                    State |= VMState.BREAK;
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// Parse a script
        /// </summary>
        /// <param name="container">Script container</param>
        /// <returns>An array of errors, if no errors then empty</returns>
        public ScriptError[] Parse(ScriptContainer container)
        {
            ScriptErrorListener listener = new ScriptErrorListener();

            try
            {
                foreach (AssemblyName name in container.ReferencedNames)
                {
                    _engine.Runtime.LoadAssembly(Assembly.Load(name));
                }

                if (container.EnableDebug)
                {
                    string newFile = Path.GetTempFileName();

                    ScriptUtils.AddTempFile(newFile);
                    File.WriteAllText(newFile, container.Script);
                    _source = _engine.CreateScriptSourceFromFile(newFile);
                }
                else
                {
                    _source = _engine.CreateScriptSourceFromString(container.Script);
                }

                _code = _source.Compile(listener);

                if (listener.Errors.Count == 0)
                {
                    // Just create the global scope, don't execute it yet
                    _scope = _engine.CreateScope();
                    _scope.SetVariable("CANAPEScriptContainer", new ScriptContainer(container));
                }
            }
            catch (Exception ex)
            {
                listener.Errors.Add(new ScriptError(ex.Message, "FatalError", 0, 0));
            }

            return listener.Errors.ToArray();
        }
Beispiel #13
0
        private static void MakeBombs()
        {
            ScriptContainer scriptContainer1 = new ScriptContainer("Pulsate".CRC32Hash())
            {
            };

            Scripts.Scripts.Pulsate_Init(scriptContainer1, period: GameConstants.PulsationPeriod);

            EntityTemplateManager.AddTemplate(
                new EntityTemplate(
                    "BasicBomb",
                    new Placement()
            {
                Layer   = 2,
                Visible = true,
            },
                    new Aspect()
            {
                ModelNameId = "Bomb".CRC32Hash(),                    // Possibly Over-ridden when we create the bomb.
                Tint        = Color.White,
                Size        = new Vector2(1.12f),
            },
                    new ExplosionImpact()
            {
                Barrier           = ExplosionBarrier.None,
                ShouldSendMessage = true,
            },
                    new MessageHandler(
                        new MessageAndHandler(Messages.HitByInitialExplosion, "TriggerOnExplosion".CRC32Hash())
                        )
            {
            },
                    new Bomb()
            {
                Countdown = GameConstants.BombSecondsToExplode,
                // Other things are filled in when we create the bomb.
            },
                    scriptContainer1,
                    new Physics()
            {
                IsSensor           = true,
                BoundingVolumeType = BoundingVolumeType.Box,
                Size                = 1f,
                IsDynamic           = false, // REVIEW: We'll need to modify this in the case of throwing bombs.
                CollisionCategories = CollisionCategory.Bombs,
                CollidesWidth       = CollisionCategory.AllPlayers,
            }
                    )
                );

            // Land mines are different enough that we'll use a different prefab
            ScriptContainer scriptContainer2 = new ScriptContainer("LandMineRiseFall".CRC32Hash())
            {
            };

            Scripts.Scripts.LandMineRiseFall_Init(scriptContainer2, GameConstants.LandMineFuseTime);

            EntityTemplateManager.AddTemplate(
                new EntityTemplate(
                    "LandMineBomb",
                    new Placement()
            {
                Layer   = 2,
                Visible = true,
            },
                    new Aspect()
            {
                ModelNameId = "LandMine".CRC32Hash(),                    // Possibly Over-ridden when we create the bomb.
                Tint        = new Color(196, 196, 196, 255),
                Size        = new Vector2(1.12f),
            },
                    new ExplosionImpact()
            {
                Barrier           = ExplosionBarrier.None,
                ShouldSendMessage = true,
            },
                    new MessageHandler(
                        new MessageAndHandler(Messages.HitByInitialExplosion, "TriggerOnExplosion".CRC32Hash())
                        )
            {
            },
                    new Bomb()
            {
                Countdown = GameConstants.BombSecondsToExplode,
                // Other things are filled in when we create the bomb.
            },
                    scriptContainer2
                    // No physics for land mines, since we can walk over them.
                    )
                );
        }