/// <summary> /// executes the script until it finishes, fails or hits a breakpoint /// </summary> public DebuggerState Run() { do { lastState = Step(); } while (lastState.state == DebuggerState.State.Running); return(lastState); }
public void Reset(byte[] inputScript, ABI ABI, string methodName) { if (ContractByteCode == null || ContractByteCode.Length == 0) { throw new Exception("Contract bytecode is not set yet!"); } if (lastState.state == DebuggerState.State.Reset) { return; } if (currentTransaction == null) { //throw new Exception("Transaction not set"); currentTransaction = new API.Transaction(this.blockchain.currentBlock); } usedGas = 0; usedOpcodeCount = 0; currentTransaction.emulator = this; engine = new ExecutionEngine(currentTransaction, null, interop); engine.LoadScript(ContractByteCode); engine.LoadScript(inputScript); this.currentMethod = methodName; /*foreach (var output in currentTransaction.outputs) * { * if (output.hash == this.currentHash) * { * output.hash = engine.CurrentContext.ScriptHash; * } * }*/ foreach (var pos in _breakpoints) { engine.AddBreakPoint((uint)pos); } //engine.Reset(); lastState = new DebuggerState(DebuggerState.State.Reset, 0); currentTransaction = null; _variables.Clear(); this._ABI = ABI; }
/// <summary> /// executes a single instruction in the current script, and returns the last script offset /// </summary> public DebuggerState Step() { if (lastState.state == DebuggerState.State.Finished || lastState.state == DebuggerState.State.Invalid) { return(lastState); } ExecuteSingleStep(); try { lastOffset = engine.CurrentContext.InstructionPointer; var opcode = engine.lastOpcode; decimal opCost; if (opcode <= OpCode.PUSH16) { opCost = 0; } else { switch (opcode) { case OpCode.SYSCALL: { var callInfo = interop.FindCall(engine.lastSysCall); opCost = (callInfo != null) ? callInfo.gasCost : 0; if (engine.lastSysCall.EndsWith("Storage.Put")) { opCost *= (Storage.lastStorageLength / 1024.0m); if (opCost < 1) { opCost = 1; } } break; } case OpCode.CHECKMULTISIG: case OpCode.CHECKSIG: opCost = 0.1m; break; case OpCode.APPCALL: case OpCode.TAILCALL: case OpCode.SHA256: case OpCode.SHA1: opCost = 0.01m; break; case OpCode.HASH256: case OpCode.HASH160: opCost = 0.02m; break; case OpCode.NOP: opCost = 0; break; default: opCost = 0.001m; break; } } usedGas += opCost; usedOpcodeCount++; OnStep?.Invoke(new EmulatorStepInfo() { byteCode = engine.CurrentContext.Script, offset = engine.CurrentContext.InstructionPointer, opcode = opcode, gasCost = opCost, sysCall = opcode == OpCode.SYSCALL? engine.lastSysCall : null }); } catch { // failed to get instruction pointer } if (engine.State.HasFlag(VMState.FAULT)) { lastState = new DebuggerState(DebuggerState.State.Exception, lastOffset); return(lastState); } if (engine.State.HasFlag(VMState.BREAK)) { lastState = new DebuggerState(DebuggerState.State.Break, lastOffset); engine.State = VMState.NONE; return(lastState); } if (engine.State.HasFlag(VMState.HALT)) { lastState = new DebuggerState(DebuggerState.State.Finished, lastOffset); return(lastState); } lastState = new DebuggerState(DebuggerState.State.Running, lastOffset); return(lastState); }
public void Reset(DataNode inputs, ABI ABI) { if (contractByteCode == null || contractByteCode.Length == 0) { throw new Exception("Contract bytecode is not set yet!"); } if (lastState.state == DebuggerState.State.Reset) { return; } if (currentTransaction == null) { //throw new Exception("Transaction not set"); currentTransaction = new Transaction(this.blockchain.currentBlock); } usedGas = 0; usedOpcodeCount = 0; currentTransaction.emulator = this; engine = new ExecutionEngine(currentTransaction, Crypto.Default, null, interop); engine.LoadScript(contractByteCode); foreach (var output in currentTransaction.outputs) { if (output.hash == this.currentHash) { output.hash = new UInt160(engine.CurrentContext.ScriptHash); } } foreach (var pos in _breakpoints) { engine.AddBreakPoint((uint)pos); } using (ScriptBuilder sb = new ScriptBuilder()) { var items = new Stack <object>(); if (inputs != null) { foreach (var item in inputs.Children) { var obj = Emulator.ConvertArgument(item); items.Push(obj); } } while (items.Count > 0) { var item = items.Pop(); EmitObject(sb, item); } var loaderScript = sb.ToArray(); //System.IO.File.WriteAllBytes("loader.avm", loaderScript); engine.LoadScript(loaderScript); } //engine.Reset(); lastState = new DebuggerState(DebuggerState.State.Reset, 0); currentTransaction = null; _variables.Clear(); this._ABI = ABI; }