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);
        }
예제 #2
0
        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));
                }
            }
        }