static bool TryGetDeploymentSigner(ConfigProps config, ExpressChain?chain, byte version, [MaybeNullWhen(false)] out Signer signer) { if (config.TryGetValue("deploy-signer", out var deploySignerToken)) { return(TryParseSigner(deploySignerToken, chain, version, out signer)); } signer = default; return(false); }
static async Task <IApplicationEngine> CreateEngineAsync(ConfigProps config) { if (!config.TryGetValue("invocation", out var jsonInvocation)) { throw new JsonException("missing invocation property"); } if (jsonInvocation.Type == JTokenType.Object && jsonInvocation["trace-file"] != null) { var traceFile = jsonInvocation.Value <string>("trace-file") ?? throw new JsonException("invalid trace-file property"); var program = ParseProgram(config); var launchContract = LoadNefFile(program); var contracts = new List <NefFile> { launchContract }; // TODO: load other contracts? return(new TraceApplicationEngine(traceFile, contracts)); } return(await CreateDebugEngineAsync(config, jsonInvocation).ConfigureAwait(false)); }
static async Task <IApplicationEngine> CreateDebugEngineAsync(ConfigProps config, JToken jsonInvocation) { var program = ParseProgram(config); var launchNefFile = LoadNefFile(program); var launchManifest = await LoadContractManifestAsync(program).ConfigureAwait(false); var chain = LoadNeoExpress(config); var invocation = ParseInvocation(jsonInvocation); var checkpoint = LoadBlockchainCheckpoint(config, chain?.Network, chain?.AddressVersion); var(trigger, witnessChecker) = ParseRuntime(config, chain, checkpoint.Settings.AddressVersion); if (trigger != TriggerType.Application) { throw new Exception($"Trigger Type {trigger} not supported"); } var signers = ParseSigners(config, chain, checkpoint.Settings.AddressVersion).ToArray(); var store = new MemoryTrackingStore(checkpoint); store.EnsureLedgerInitialized(checkpoint.Settings); Script invokeScript; var attributes = Array.Empty <TransactionAttribute>(); if (invocation.IsT3) // T3 == ContractDeploymentInvocation { if ((signers.Length == 0 || (signers.Length == 1 && signers[0].Account == UInt160.Zero)) && TryGetDeploymentSigner(config, chain, checkpoint.Settings.AddressVersion, out var deploySigner)) { signers = new[] { deploySigner }; } using var builder = new ScriptBuilder(); builder.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", launchNefFile.ToArray(), launchManifest.ToJson().ToString()); invokeScript = builder.ToArray(); } else { var paramParser = CreateContractParameterParser(checkpoint.Settings.AddressVersion, store, chain); var deploySigner = TryGetDeploymentSigner(config, chain, checkpoint.Settings.AddressVersion, out var _deploySigner) ? _deploySigner : new Signer { Account = UInt160.Zero }; var(launchContractId, launchContractHash) = EnsureContractDeployed(store, launchNefFile, launchManifest, deploySigner, checkpoint.Settings); UpdateContractStorage(store, launchContractId, ParseStorage(config, paramParser)); invokeScript = await CreateInvokeScriptAsync(invocation, program, launchContractHash, paramParser); if (invocation.IsT1) // T1 == OracleResponseInvocation { attributes = GetTransactionAttributes(invocation.AsT1, store, launchContractHash, paramParser); } } // TODO: load other contracts // Not sure supporting other contracts is a good idea anymore. Since there's no way to calculate the // contract id hash prior to deployment in Neo 3, I'm thinking the better approach would be to simply // deploy whatever contracts you want and take a snapshot rather than deploying multiple contracts // during launch configuration. var tx = new Transaction { Version = 0, Nonce = (uint)new Random().Next(), Script = invokeScript, Signers = signers, ValidUntilBlock = checkpoint.Settings.MaxValidUntilBlockIncrement, Attributes = attributes, Witnesses = Array.Empty <Witness>() }; var block = CreateDummyBlock(store, tx); var engine = new DebugApplicationEngine(tx, store, checkpoint.Settings, block, witnessChecker); engine.LoadScript(invokeScript); return(engine);
static string ParseProgram(ConfigProps config) => config["program"].Value <string>() ?? throw new JsonException("missing program property");