public ApplicationEngine?Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, Diagnostic?diagnostic) { if (trigger == TriggerType.Application && container is Transaction tx && tx.Witnesses != null && tx.Witnesses.Length > 0 && EnumerateContractCalls(tx.Script).Any()) { var path = SysIO.Path.Combine(Environment.CurrentDirectory, $"{tx.Hash}.neo-trace"); var sink = new TraceDebugStream(SysIO.File.OpenWrite(path)); return(new TraceApplicationEngine(sink, trigger, container, snapshot, persistingBlock, settings, gas, diagnostic)); } return(null); }
static void TraceBlock(Uri uri, Block block, ProtocolSettings settings, IConsole console, UInt256?txHash = null) { IReadOnlyStore roStore = block.Index > 0 ? new StateServiceStore(uri, block.Index - 1) : NullStore.Instance; using var store = new MemoryTrackingStore(roStore); using var snapshot = new SnapshotCache(store.GetSnapshot()); using (var engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, block, settings, 0)) { using var sb = new ScriptBuilder(); sb.EmitSysCall(ApplicationEngine.System_Contract_NativeOnPersist); engine.LoadScript(sb.ToArray()); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException("NativeOnPersist operation failed", engine.FaultException); } } var clonedSnapshot = snapshot.CreateSnapshot(); for (int i = 0; i < block.Transactions.Length; i++) { Transaction tx = block.Transactions[i]; using var engine = GetEngine(tx, clonedSnapshot); if (engine is TraceApplicationEngine) { console.Out.WriteLine($"Tracing Transaction #{i} ({tx.Hash})"); } else { console.Out.WriteLine($"Executing Transaction #{i} ({tx.Hash})"); } engine.LoadScript(tx.Script); if (engine.Execute() == VMState.HALT) { clonedSnapshot.Commit(); } else { clonedSnapshot = snapshot.CreateSnapshot(); } } ApplicationEngine GetEngine(Transaction tx, DataCache snapshot) { if (txHash == null || txHash == tx.Hash) { var path = SysIO.Path.Combine(Environment.CurrentDirectory, $"{tx.Hash}.neo-trace"); var sink = new TraceDebugStream(SysIO.File.OpenWrite(path)); return(new TraceApplicationEngine(sink, TriggerType.Application, tx, snapshot, block, settings, tx.SystemFee)); } else { return(ApplicationEngine.Create(TriggerType.Application, tx, snapshot, block, settings, tx.SystemFee)); } } }