Esempio n. 1
0
        public ScriptBuilder EmitJump(EVMOpCode op, short offset)
        {
            if (op != EVMOpCode.JMP && op != EVMOpCode.JMPIF && op != EVMOpCode.JMPIFNOT && op != EVMOpCode.CALL)
            {
                throw new ArgumentException();
            }

            return(Emit(op, BitConverter.GetBytes(offset)));
        }
Esempio n. 2
0
        /// <summary>
        /// Create new instruction
        /// </summary>
        /// <param name="location">Location</param>
        /// <param name="opCode">Opcode</param>
        public Instruction New(InstructionLocation location, EVMOpCode opCode)
        {
            var ret = (Instruction)Activator.CreateInstance(InstructionType);

            ret.Location = location;
            ret.OpCode   = opCode;

            return(ret);
        }
Esempio n. 3
0
        public ScriptBuilder Emit(EVMOpCode op, params byte[] arg)
        {
            writer.WriteByte((byte)op);

            if (arg != null)
            {
                writer.Write(arg, 0, arg.Length);
            }

            return(this);
        }
Esempio n. 4
0
        /// <summary>
        /// Parse script to instructions
        /// </summary>
        /// <param name="script">Script</param>
        public IEnumerable <Instruction> Parse(byte[] script)
        {
            var index  = 0;
            var offset = 0L;
            var opType = typeof(EVMOpCode);

            using (var ms = new MemoryStream(script))
                using (var reader = new BinaryReader(ms))
                {
                    while (offset < ms.Length)
                    {
                        var location = new InstructionLocation()
                        {
                            Index  = index,
                            Offset = offset
                        };

                        var opRead = reader.ReadByte();
                        if (!Enum.IsDefined(opType, opRead))
                        {
                            yield break;
                        }

                        EVMOpCode opcode = (EVMOpCode)Enum.ToObject(opType, opRead);
                        if (!_cache.TryGetValue(opcode, out var attr))
                        {
                            yield break;
                        }

                        Instruction i = attr.New(location, opcode);

                        if (!attr.Fill(reader, i))
                        {
                            yield break;
                        }

                        offset = ms.Position;
                        index++;

                        yield return(i);
                    }
                }
        }
Esempio n. 5
0
        /// <summary>
        /// Check operand with one BigIntegers
        /// </summary>
        /// <param name="operand">Operand</param>
        /// <param name="check">Check</param>
        protected void InternalTestBigInteger(EVMOpCode operand, Func <BigInteger, object> check)
        {
            // Test without push

            using (var script = new ScriptBuilder(operand))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Test with wrong type

            using (var script = new ScriptBuilder
                                (
                       EVMOpCode.PUSH1,
                       EVMOpCode.NEWARRAY,
                       operand
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Test with push

            foreach (var bi in IntSingleIteration())
            {
                using (var script = new ScriptBuilder())
                    using (var engine = CreateEngine(Args))
                    {
                        // Make the script

                        script.EmitPush(bi);
                        script.Emit(operand, EVMOpCode.RET);

                        // Load script

                        engine.LoadScript(script);

                        // Execute

                        var currentContext = engine.CurrentContext;
                        {
                            // PUSH A
                            engine.StepInto();
                            Assert.AreEqual(1, currentContext.EvaluationStack.Count);
                        }

                        // Operand

                        engine.StepInto(2);

                        try
                        {
                            var ret = check(bi);

                            using (var it = engine.ResultStack.Pop())
                            {
                                CheckValue(it, ret);
                            }

                            // RET

                            Assert.AreEqual(EVMState.Halt, engine.State);
                            CheckClean(engine);
                        }
                        catch
                        {
                            // RET

                            Assert.AreEqual(EVMState.Fault, engine.State);
                            CheckClean(engine, false);
                        }
                    }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Check operand with two BigIntegers
        /// </summary>
        /// <param name="operand">Operand</param>
        /// <param name="check">Check</param>
        protected void InternalTestBigInteger(EVMOpCode operand, Func <BigIntegerPair, object> check)
        {
            // Test without push

            using (var script = new ScriptBuilder(operand))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Test with wrong type

            using (var script = new ScriptBuilder
                                (
                       EVMOpCode.PUSH1,
                       EVMOpCode.PUSH1,
                       EVMOpCode.NEWARRAY,
                       operand
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    if (operand == EVMOpCode.EQUAL)
                    {
                        // Equal command don't FAULT here

                        Assert.IsTrue(engine.Execute());

                        using (var i = engine.ResultStack.Pop <BooleanStackItem>())
                        {
                            Assert.AreEqual(i.Value, false);
                        }
                    }
                    else
                    {
                        Assert.IsFalse(engine.Execute());
                    }

                    // Check

                    CheckClean(engine, false);
                }

            // Test with push

            foreach (var pair in IntPairIteration())
            {
                using (var script = new ScriptBuilder())
                    using (var engine = CreateEngine(Args))
                    {
                        // Make the script

                        foreach (var bb in new BigInteger[] { pair.A, pair.B })
                        {
                            script.EmitPush(bb);
                        }

                        script.Emit(operand, EVMOpCode.RET);

                        // Load script

                        engine.LoadScript(script.ToArray());

                        // Execute

                        var currentContext = engine.CurrentContext;
                        {
                            // PUSH A
                            engine.StepInto();

                            Assert.AreEqual(1, currentContext.EvaluationStack.Count);

                            // PUSH B
                            engine.StepInto();
                            Assert.AreEqual(2, currentContext.EvaluationStack.Count);
                        }

                        // Operand

                        engine.StepInto();
                        engine.StepInto();

                        try
                        {
                            var ret = check(pair);

                            using (var it = engine.ResultStack.Pop())
                            {
                                CheckValue(it, ret);
                            }

                            // RET

                            Assert.AreEqual(EVMState.Halt, engine.State);
                            CheckClean(engine);
                        }
                        catch
                        {
                            // RET

                            Assert.AreEqual(EVMState.Fault, engine.State);
                            CheckClean(engine, false);
                        }
                    }
            }

            // Test with dup

            foreach (var i in IntSingleIteration())
            {
                using (var script = new ScriptBuilder())
                    using (var engine = CreateEngine(Args))
                    {
                        // Make the script

                        script.EmitPush(i);
                        script.Emit(EVMOpCode.DUP);
                        script.Emit(operand, EVMOpCode.RET);

                        // Load script

                        engine.LoadScript(script.ToArray());

                        // Execute

                        var currentContext = engine.CurrentContext;
                        {
                            // PUSH A
                            engine.StepInto();
                            Assert.AreEqual(1, currentContext.EvaluationStack.Count);

                            // PUSH B
                            engine.StepInto();
                            Assert.AreEqual(2, currentContext.EvaluationStack.Count);
                        }

                        // Operand

                        engine.StepInto(2);

                        try
                        {
                            var ret = check(new BigIntegerPair(i, i));

                            using (var it = engine.ResultStack.Pop())
                            {
                                CheckValue(it, ret);
                            }

                            // RET

                            Assert.AreEqual(EVMState.Halt, engine.State);
                            CheckClean(engine);
                        }
                        catch
                        {
                            // RET

                            Assert.AreEqual(EVMState.Fault, engine.State);
                            CheckClean(engine, false);
                        }
                    }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Check operand with one BigIntegers
        /// </summary>
        /// <param name="operand">Operand</param>
        /// <param name="check">Check</param>
        protected void InternalTestBigInteger(EVMOpCode operand, Action <IExecutionEngine, BigInteger, CancelEventArgs> check)
        {
            // Test without push

            using (var script = new ScriptBuilder(operand))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Test with wrong type

            using (var script = new ScriptBuilder
                                (
                       EVMOpCode.PUSH1,
                       EVMOpCode.NEWARRAY,
                       operand
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Test with push

            Stopwatch sw = new Stopwatch();

            foreach (var bi in IntSingleIteration())
            {
                using (var script = new ScriptBuilder())
                    using (var engine = CreateEngine(Args))
                    {
                        // Make the script

                        script.EmitPush(bi);
                        script.Emit(operand, EVMOpCode.RET);

                        // Load script

                        engine.LoadScript(script);

                        // Execute

                        using (var currentContext = engine.CurrentContext)
                        {
                            // PUSH A
                            engine.StepInto();
                            Assert.AreEqual(1, currentContext.EvaluationStack.Count);
                        }

                        // Operand

                        CancelEventArgs cancel = new CancelEventArgs(false);

#pragma warning disable CS0162
                        if (CalculateNumericalTimes)
                        {
                            sw.Restart();
                        }
#pragma warning restore

                        engine.StepInto(2);
                        check(engine, bi, cancel);

#pragma warning disable CS0162
                        if (CalculateNumericalTimes)
                        {
                            sw.Stop();
                            Console.WriteLine("[" + sw.Elapsed.ToString() + "] " + bi);
                        }
#pragma warning restore

                        if (cancel.Cancel)
                        {
                            continue;
                        }

                        // RET
                        engine.StepInto();
                        Assert.AreEqual(EVMState.Halt, engine.State);

                        // Check

                        CheckClean(engine);
                    }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Check operand with two BigIntegers
        /// </summary>
        /// <param name="operand">Operand</param>
        /// <param name="check">Check</param>
        protected void InternalTestBigInteger(EVMOpCode operand, Action <IExecutionEngine, BigInteger, BigInteger, CancelEventArgs> check)
        {
            // Test without push

            using (var script = new ScriptBuilder(operand))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Test with wrong type

            using (var script = new ScriptBuilder
                                (
                       EVMOpCode.PUSH1,
                       EVMOpCode.PUSH1,
                       EVMOpCode.NEWARRAY,
                       operand
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    if (operand == EVMOpCode.EQUAL)
                    {
                        // Equal command don't FAULT here

                        Assert.IsTrue(engine.Execute());
                        Assert.AreEqual(engine.ResultStack.Pop <BooleanStackItem>().Value, false);
                    }
                    else
                    {
                        Assert.IsFalse(engine.Execute());
                    }

                    // Check

                    CheckClean(engine, false);
                }

            Stopwatch sw = new Stopwatch();

            // Test with push

            foreach (var pair in IntPairIteration())
            {
                using (var script = new ScriptBuilder())
                    using (var engine = CreateEngine(Args))
                    {
                        // Make the script

                        foreach (BigInteger bb in new BigInteger[] { pair.A, pair.B })
                        {
                            script.EmitPush(bb);
                        }

                        script.Emit(operand, EVMOpCode.RET);

                        // Load script

                        engine.LoadScript(script.ToArray());

                        // Execute

                        using (var currentContext = engine.CurrentContext)
                        {
                            // PUSH A
                            engine.StepInto();

                            Assert.AreEqual(1, currentContext.EvaluationStack.Count);

                            // PUSH B
                            engine.StepInto();
                            Assert.AreEqual(2, currentContext.EvaluationStack.Count);
                        }

                        // Operand

                        CancelEventArgs cancel = new CancelEventArgs(false);

#pragma warning disable CS0162
                        if (CalculateNumericalTimes)
                        {
                            sw.Restart();
                        }
#pragma warning restore

                        engine.StepInto();
                        engine.StepInto();

                        check(engine, pair.A, pair.B, cancel);

#pragma warning disable CS0162
                        if (CalculateNumericalTimes)
                        {
                            sw.Stop();
                            Console.WriteLine("[" + sw.Elapsed.ToString() + "] " + pair.A + " " + operand.ToString() + " " + pair.B);
                        }
#pragma warning restore

                        if (cancel.Cancel)
                        {
                            CheckClean(engine, false);
                            continue;
                        }

                        // RET

                        Assert.AreEqual(EVMState.Halt, engine.State);

                        // Check

                        CheckClean(engine);
                    }
            }

            // Test with dup

            foreach (var i in IntSingleIteration())
            {
                using (var script = new ScriptBuilder())
                    using (var engine = CreateEngine(Args))
                    {
                        // Make the script

                        script.EmitPush(i);
                        script.Emit(EVMOpCode.DUP);
                        script.Emit(operand, EVMOpCode.RET);

                        // Load script

                        engine.LoadScript(script.ToArray());

                        // Execute

                        using (var currentContext = engine.CurrentContext)
                        {
                            // PUSH A
                            engine.StepInto();
                            Assert.AreEqual(1, currentContext.EvaluationStack.Count);

                            // PUSH B
                            engine.StepInto();
                            Assert.AreEqual(2, currentContext.EvaluationStack.Count);
                        }

                        // Operand

                        CancelEventArgs cancel = new CancelEventArgs(false);

#pragma warning disable CS0162
                        if (CalculateNumericalTimes)
                        {
                            sw.Restart();
                        }
#pragma warning restore

                        engine.StepInto(2);
                        check(engine, i, i, cancel);

#pragma warning disable CS0162
                        if (CalculateNumericalTimes)
                        {
                            sw.Stop();
                            Console.WriteLine("[" + sw.Elapsed.ToString() + "] " + i + " " + operand.ToString() + " " + i);
                        }
#pragma warning restore

                        if (cancel.Cancel)
                        {
                            CheckClean(engine, false);
                            continue;
                        }

                        // RET
                        engine.StepInto();
                        Assert.AreEqual(EVMState.Halt, engine.State);

                        // Check

                        CheckClean(engine);
                    }
            }
        }
Esempio n. 9
0
        public void APPCALL_AND_TAILCALL(EVMOpCode opcode)
        {
            Assert.IsTrue(opcode == EVMOpCode.APPCALL || opcode == EVMOpCode.TAILCALL);

            // Check without IScriptTable

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)opcode,
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
                0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A
            }
                                ))
            {
                // Test cache with the real hash

                byte[] msg = Args.ScriptTable.GetScript(script.ToArray().Skip(1).Take(20).ToArray(), false);

                byte[] realHash;
                using (var sha = SHA256.Create())
                    using (var ripe = new RIPEMD160Managed())
                    {
                        realHash = sha.ComputeHash(msg);
                        realHash = ripe.ComputeHash(realHash);
                    }

                script.Emit(opcode);
                script.Emit(realHash);

                using (var engine = CreateEngine(new ExecutionEngineArgs()))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

                // Check without complete hash

                using (var engine = CreateEngine(new ExecutionEngineArgs()))
                {
                    // Load script

                    engine.LoadScript(script.ToArray().Take((int)script.Length - 1).ToArray());

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

                // Check script

                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsTrue(engine.Execute());

                    // Check

                    Assert.AreEqual(engine.ResultStack.Pop <IntegerStackItem>().Value, 0x04);

                    if (opcode == EVMOpCode.APPCALL)
                    {
                        Assert.AreEqual(engine.ResultStack.Pop <IntegerStackItem>().Value, 0x04);
                    }

                    CheckClean(engine);
                }
            }

            // Check empty hash without push

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)opcode,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            }
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Check empty with wrong push

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)EVMOpCode.PUSHBYTES1,
                0x01,

                (byte)opcode,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            }
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }

            // Check empty with with push

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)EVMOpCode.PUSHBYTES1 + 19,
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
                0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,

                (byte)opcode,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            }
                                ))
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    // PUSH

                    engine.StepInto();
                    Assert.AreEqual(0, engine.CurrentContext.AltStack.Count);
                    Assert.AreEqual(1, engine.CurrentContext.EvaluationStack.Count);
                    Assert.AreEqual(1, engine.InvocationStack.Count);

                    if (opcode == EVMOpCode.APPCALL)
                    {
                        // APP CALL

                        engine.StepInto();
                        Assert.AreEqual(0, engine.CurrentContext.AltStack.Count);
                        Assert.AreEqual(0, engine.CurrentContext.EvaluationStack.Count);
                        Assert.AreEqual(2, engine.InvocationStack.Count);

                        // PUSH 0x05

                        engine.StepInto();
                        Assert.AreEqual(0, engine.CurrentContext.AltStack.Count);
                        Assert.AreEqual(1, engine.CurrentContext.EvaluationStack.Count);
                        Assert.AreEqual(2, engine.InvocationStack.Count);

                        // RET 1

                        engine.StepInto();
                        Assert.AreEqual(0, engine.CurrentContext.AltStack.Count);
                        Assert.AreEqual(1, engine.CurrentContext.EvaluationStack.Count);
                        Assert.AreEqual(1, engine.InvocationStack.Count);

                        // RET 2

                        engine.StepInto();
                        Assert.AreEqual(1, engine.ResultStack.Count);
                        Assert.AreEqual(0, engine.InvocationStack.Count);
                    }
                    else
                    {
                        // TAIL CALL

                        engine.StepInto();
                        Assert.AreEqual(0, engine.CurrentContext.AltStack.Count);
                        Assert.AreEqual(0, engine.CurrentContext.EvaluationStack.Count);
                        Assert.AreEqual(1, engine.InvocationStack.Count);

                        // PUSH 0x05

                        engine.StepInto();
                        Assert.AreEqual(0, engine.CurrentContext.AltStack.Count);
                        Assert.AreEqual(1, engine.CurrentContext.EvaluationStack.Count);
                        Assert.AreEqual(1, engine.InvocationStack.Count);

                        // RET 1

                        engine.StepInto();
                        Assert.AreEqual(1, engine.ResultStack.Count);
                        Assert.AreEqual(0, engine.InvocationStack.Count);
                    }

                    Assert.AreEqual(EVMState.Halt, engine.State);

                    // Check

                    Assert.AreEqual(engine.ResultStack.Pop <IntegerStackItem>().Value, 0x06);

                    CheckClean(engine);
                }
        }
Esempio n. 10
0
        void GLOBAL_CALL_EX(EVMOpCode opcode)
        {
            // Without push

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)opcode, 0x00, 0x01
            }
                                ))
            {
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }
            }

            // Without pcount

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)opcode, 0x00
            }
                                ))
            {
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }
            }

            // Without rvcount

            using (var script = new ScriptBuilder
                                (
                       new byte[]
            {
                (byte)opcode
            }
                                ))
            {
                using (var engine = CreateEngine(Args))
                {
                    // Load script

                    engine.LoadScript(script);

                    // Execute

                    Assert.IsFalse(engine.Execute());

                    // Check

                    CheckClean(engine, false);
                }
            }
        }
Esempio n. 11
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="opcode">OpCode</param>
 /// <param name="rawOpCodes">Raw OpCodes</param>
 public ScriptBuilder(EVMOpCode opcode, params byte[] rawOpCodes) : this()
 {
     Emit(opcode);
     Emit(rawOpCodes);
 }