/// <summary> /// /// NOTE: UNDER CONSTRUCTION /// /// This method will pull chrono logs from the ChronoLog contract. /// /// <param name=""></param> /// <returns></returns> /// </summary> public static async Task <List <string> > GetChronoLogs(this Wonka.Eth.Init.WonkaEthEngineInitialization poEngineInitData, string psChronoLogContractAddr, GetChronoLogEventsByTypeAndTimeFunction poGetChronoLogEventFunction) { List <string> ChronoLogs = new List <string>(); var account = new Nethereum.Web3.Accounts.Account(poEngineInitData.EthPassword); Nethereum.Web3.Web3 SenderWeb3; if (!String.IsNullOrEmpty(poEngineInitData.Web3HttpUrl)) { SenderWeb3 = new Nethereum.Web3.Web3(account, poEngineInitData.Web3HttpUrl); } else { SenderWeb3 = new Nethereum.Web3.Web3(account); } var getLogsHandler = SenderWeb3.Eth.GetContractQueryHandler <GetChronoLogEventsByTypeAndTimeFunction>(); var ChronoLogList = await getLogsHandler.QueryDeserializingToObjectAsync <GetChronoLogEventsByTypeAndTimeOutputDTOBase>(poGetChronoLogEventFunction, psChronoLogContractAddr); ChronoLogList.ReturnValue1.ForEach(x => ChronoLogs.Add(Convert.ToString(x))); return(ChronoLogs); }
/// <summary> /// /// This method will persist all data to files (metadata, rules, current data, report), zip the files, and then upload the .ZIP to IPFS /// /// <param name="poEngine">The instance of the Wonka engine that has just run</param> /// <param name="poEngineInitProps">Various properties of this instance of the Wonka engine</param> /// <param name="poRecord">This record holds the current snapshot of the data being addressed by the metadata (mentioned in WonkaRefEnvironment)</param> /// <param name="poReport">This report holds the verbose results of running the RuleTree</param> /// <param name="psIpfsUrl">This URL points to the IPFS node that acts as the read-only gateway</param> /// <param name="psWriteIpfsUrl">This URL points to the IPFS node that will be used to upload the Zip file of the results</param> /// <param name="psUniqueChronoLogName">This will be the unique name of the ChronoLog entry</param> /// <returns>IPFS ID of the new file</returns> /// </summary> public static async Task <string> UploadInvocationAsync(this WonkaBizRulesEngine poEngine, Wonka.Eth.Init.WonkaEthEngineInitialization poEngineInitProps, WonkaProduct poRecord, Wonka.Eth.Extensions.RuleTreeReport poReport, string psIpfsUrl, string psWriteIpfsUrl, string psUniqueChronoLogName) { string sZipIpfsUrl = ""; var RefEnv = WonkaRefEnvironment.GetInstance(); string sZipFileUrl = poEngine.ZipInvocation(poRecord, poReport, psUniqueChronoLogName); var zipBytes = File.ReadAllBytes(sZipFileUrl); using (MemoryStream zipStream = new MemoryStream(zipBytes)) { var ipfsClient = new IpfsClient(psWriteIpfsUrl); var merkleNode = await ipfsClient.FileSystem.AddFileAsync(sZipFileUrl, new Ipfs.CoreApi.AddFileOptions() { Pin = true }).ConfigureAwait(false); sZipIpfsUrl = psIpfsUrl + "/" + merkleNode.Id.Hash.ToString(); } return(sZipIpfsUrl); }
private async Task <bool> InitEngineAsync(bool pbInitChainEnv) { bool bResult = false; string sDefaultSource = "S"; moEthEngineInit = new Wonka.Eth.Init.WonkaEthEngineInitialization(); // EthEngineInit.Engine.RulesEngine = moRulesEngine; moEthEngineInit.Engine.MetadataSource = moMetadataSource; moEthEngineInit.Engine.RulesMarkupXml = msRulesContents; moEthEngineInit.Engine.DotNetRetrieveMethod = RetrieveValueMethod; moEthEngineInit.EthSenderAddress = moEthEngineInit.EthRuleTreeOwnerAddress = msSenderAddress; moEthEngineInit.EthPassword = msPassword; moEthEngineInit.Web3HttpUrl = CONST_ONLINE_TEST_CHAIN_URL; moEthEngineInit.RulesEngineContractAddress = msEngineContractAddress; moEthEngineInit.RegistryContractAddress = msRegistryContractAddress; moEthEngineInit.ChronoLogContractAddress = msChronoLogAddress; moEthEngineInit.StorageContractAddress = msTestContractAddress; moEthEngineInit.StorageDefaultSourceId = sDefaultSource; moEthEngineInit.StorageContractABI = msAbiOrchTest; moEthEngineInit.StorageGetterMethod = "getAttrValueBytes32"; moEthEngineInit.StorageSetterMethod = "setAttrValueBytes32"; moEthEngineInit.UsingStorageContract = true; moEthEngineInit.UsingTrxStateContract = false; // NOTE: Optional here // EthEngineInit.RegistryContractABI = msAbiRegistry; // EthEngineInit.RulesEngineABI = msAbiWonka; // EthEngineInit.TestContractABI = msAbiOrchTest; await moEthEngineInit.InitEngineAsync().ConfigureAwait(false); // Serialize the data domain to the blockchain if (pbInitChainEnv) { await moEthEngineInit.SerializeAsync().ConfigureAwait(false); } return(bResult); }
/// <summary> /// /// After running an instance of the Wonka engine, this method will: /// /// 1.) Persist all data to files (metadata, rules, current data, report), zip the files, and then upload the .ZIP to IPFS /// 2.) Create the hash of the Zip file /// 3.) Create an entry on the ChronoLog contract (including the IPFS URL and hash of the Zip file) /// /// <param name="poEngine">The instance of the Wonka engine that has just run a RuleTree</param> /// <param name="poEngineInitProps">Various properties of this instance of the Wonka engine</param> /// <param name="poRecord">This record holds the current snapshot of the data being addressed by the metadata (mentioned in WonkaRefEnvironment)</param> /// <param name="poReport">This report holds the verbose results of running the RuleTree</param> /// <param name="psIpfsUrl">This URL points to the IPFS node that acts as the read-only gateway</param> /// <param name="psWriteIpfsUrl">This URL points to the IPFS node that will be used to upload the Zip file of the results</param> /// <param name="psChronoLogContractAddr">This address points to an instance of the ChronoLog contract</param> /// <returns>Unique name for entry in the ChronoLog contract</returns> /// </summary> public static async Task <string> StoreWonkaResultsAsync(this WonkaBizRulesEngine poEngine, Wonka.Eth.Init.WonkaEthEngineInitialization poEngineInitProps, WonkaProduct poRecord, Wonka.Eth.Extensions.RuleTreeReport poReport, string psIpfsUrl, string psWriteIpfsUrl, string psChronoLogContractAddr) { var RefEnv = WonkaRefEnvironment.GetInstance(); var signer = new EthereumMessageSigner(); var prodMsgXml = new WonkaProductMsgWriter().WriteWonkaMsg(new WonkaProductMessage(poRecord, true)); var inputSignature = signer.EncodeUTF8AndSign(prodMsgXml, new EthECKey(poEngineInitProps.EthPassword)); string sUniqueChronoLogName = "WI-" + DateTime.Now.ToUniversalTime().ToEpochTime(); string sZipIpfsUrl = await poEngine.UploadInvocationAsync(poEngineInitProps, poRecord, poReport, psIpfsUrl, psWriteIpfsUrl, sUniqueChronoLogName).ConfigureAwait(false); var addChronoLogEventFunction = new Wonka.Eth.Autogen.ChronoLog.AddChronoLogEventFunction() { UniqueName = sUniqueChronoLogName, EType = "WONKA_INVOKE", Desc = "", // Empty for now Data = "", // Empty for now Hash = inputSignature, Url = sZipIpfsUrl }; string sTrxHash = await poReport.WriteToChronoLog(poEngineInitProps, psChronoLogContractAddr, addChronoLogEventFunction).ConfigureAwait(false); return(sUniqueChronoLogName); }
/// <summary> /// /// NOTE: UNDER CONSTRUCTION /// /// This method will log the Wonka Report to an instance of the ChronoLog contract. /// /// <param name=""></param> /// <returns></returns> /// </summary> public static async Task <string> WriteToChronoLog(this Wonka.Eth.Extensions.RuleTreeReport poReport, Wonka.Eth.Init.WonkaEthEngineInitialization poEngineInitData, string psChronoLogContractAddr, AddChronoLogEventFunction poAddChronoLogEventFunction) { var account = new Nethereum.Web3.Accounts.Account(poEngineInitData.EthPassword); Nethereum.Web3.Web3 SenderWeb3; if (!String.IsNullOrEmpty(poEngineInitData.Web3HttpUrl)) { SenderWeb3 = new Nethereum.Web3.Web3(account, poEngineInitData.Web3HttpUrl); } else { SenderWeb3 = new Nethereum.Web3.Web3(account); } var addLogHandler = SenderWeb3.Eth.GetContractTransactionHandler <AddChronoLogEventFunction>(); var receipt = await addLogHandler.SendRequestAndWaitForReceiptAsync(psChronoLogContractAddr, poAddChronoLogEventFunction); return(receipt.TransactionHash); }
/// <summary> /// /// This method will execute the RuleTree collection of a Grove, invoking each one either on the chain or off the chain. /// All of the invocations will be assembled and then returned in a report about the execution of the Grove. /// /// NOTE: UNDER CONSTRUCTION /// /// <param name="poGrove">The Grove that we are looking to execute, especially its pool of RuleTree members</param> /// <returns>The report that will hold the aggregated reports about the execution of each Grove member</returns> /// </summary> public static async Task <WonkaBizGroveReport> ExecuteAsync(this WonkaBizGrove poGrove, Wonka.Eth.Init.WonkaEthEngineInitialization poEngineInitData) { if (poGrove.RuleTreeMembers.Count == 0) { throw new WonkaEthException("ERROR! Execute() cannot be invoked for Grove(" + poGrove.GroveDesc + ") when it has no members."); } if (poEngineInitData == null) { throw new WonkaEthException("ERROR! Cannot invoke the Grove(" + poGrove.GroveDesc + ") since the EthEngineInit data provided is empty."); } var GroveReport = new WonkaBizGroveReport(poGrove); foreach (WonkaBizRulesEngine RuleTreeMember in poGrove.RuleTreeMembers) { if (poGrove.ExecuteRuleTreesOnChain.Contains(RuleTreeMember)) { var OnChainReport = new Wonka.Eth.Extensions.RuleTreeReport(); // NOTE: We assume here that that the Wonka contract instance (mentioned within 'poEngineInitData') and certain RuleTrees of 'poGrove' // exist on the chain - maybe we should check that fact? string sTrxHash = await RuleTreeMember.ExecuteOnChainAsync(poEngineInitData, OnChainReport).ConfigureAwait(false); GroveReport.RuleTreeReports[RuleTreeMember.DetermineRuleTreeChainID()] = OnChainReport; } else { var OffChainReport = new WonkaBizRuleTreeReport(); WonkaProduct CurrValues = new WonkaProduct(); bool bResult = await CurrValues.PopulateWithDataFromChainAsync(RuleTreeMember.RefEnvHandle, RuleTreeMember.SourceMap, poEngineInitData.Web3HttpUrl).ConfigureAwait(false); OffChainReport = RuleTreeMember.Validate(CurrValues); GroveReport.RuleTreeReports[RuleTreeMember.DetermineRuleTreeChainID()] = OffChainReport; } if (poGrove.ExecutionBreakpointDelegate != null) { poGrove.ExecutionBreakpointDelegate.Invoke(poGrove, RuleTreeMember); } if ((GroveReport.GetTotalGasUsed() >= poGrove.MaxGasCostAllowed) && (poGrove.MaxGasCostExceededDelegate != null)) { poGrove.MaxGasCostExceededDelegate.Invoke(poGrove, RuleTreeMember); } } GroveReport.EndTime = DateTime.Now; return(GroveReport); }