public WonkaNoviceOnlineChainTest(string psContractAddress, bool pbInitChainEnv = true, bool pbRetrieveMarkupFromIpfs = false)
        {
            msSenderAddress = "0x12890D2cce102216644c59daE5baed380d84830c";
            msPassword      = "******";

            msAbiWonka         = WonkaEth.Autogen.WonkaEngine.WonkaEngineDeployment.ABI;
            msByteCodeWonka    = WonkaEth.Autogen.WonkaEngine.WonkaEngineDeployment.BYTECODE;
            msAbiRegistry      = WonkaEth.Autogen.WonkaRegistry.WonkaRegistryDeployment.ABI;
            msByteCodeRegistry = WonkaEth.Autogen.WonkaRegistry.WonkaRegistryDeployment.BYTECODE;
            msAbiOrchTest      = WonkaEth.Autogen.WonkaTestContract.WonkaTestContractDeployment.ABI;
            msByteCodeOrchTest = WonkaEth.Autogen.WonkaTestContract.WonkaTestContractDeployment.BYTECODE;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data record
            moMetadataSource = new WonkaBre.Samples.WonkaBreMetadataTestSource();
            WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            // NOTE: As a reminder, you must have a IPFS daemon configured and running (perhaps on your machine)
            // in order for the Ipfs.Api to work successfully
            if (pbRetrieveMarkupFromIpfs)
            {
                using (System.Net.WebClient client = new System.Net.WebClient())
                {
                    string sIpfsUrl = String.Format("{0}/{1}", CONST_INFURA_IPFS_GATEWAY_URL, "QmXcsGDQthxbGW8C3Sx9r4tV9PGSj4MxJmtXF7dnXN5XUT");

                    msRulesContents = client.DownloadString(sIpfsUrl);
                }
            }
            else
            {
                var TmpAssembly = Assembly.GetExecutingAssembly();

                // Read the XML markup that lists the business rules
                using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.SimpleAccountCheck.xml")))
                {
                    msRulesContents = RulesReader.ReadToEnd();
                }
            }

            // By setting the addresses to NULL, we indicates that we want the API to deploy the contracts for us
            if (psContractAddress == null)
            {
                msEngineContractAddress   = null;
                msRegistryContractAddress = null;
                msTestContractAddress     = null;
            }
            // By using the indicator "DEPLOY" here, we will manually deploy the contracts ourselves
            else if (psContractAddress == "DEPLOY")
            {
                msEngineContractAddress = DeployWonka();
            }
            // Else, we will use existing contracts on the test chain
            else
            {
                if (psContractAddress == "")
                {
                    msEngineContractAddress = "0xfB419DEA1f28283edAD89103fc1f1272f7573E6A";
                }
                else
                {
                    msEngineContractAddress = psContractAddress;
                }

                msRegistryContractAddress = "0x7E618a3948F6a5D2EA6b92D8Ce6723a468540CaA";
                msTestContractAddress     = "0x4092bc250ef6c384804af2f871Af9c679b672d0B";
            }

            Init(pbInitChainEnv);
        }
        public async Task <bool> Execute(bool pbValidateTransaction = false)
        {
            bool bResult = false;

            var RefEnv      = WonkaRefEnvironment.GetInstance();
            var RulesEngine = moEthEngineInit.Engine.RulesEngine;
            var SourceMap   = moEthEngineInit.Engine.SourceMap;

            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr RvwFlagAttr    = RefEnv.GetAttributeByAttrName("AuditReviewFlag");

            // Gets a predefined data record that will be our analog for new data coming into the system
            // We are only using this record to test the .NET implementation
            WonkaProduct NewProduct = moProduct;

            string sStatusValueBefore = NewProduct.GetAttributeValue(AccountStsAttr);
            string sFlagValueBefore   = NewProduct.GetAttributeValue(RvwFlagAttr);

            // Validate that the .NET implementation and the rules markup are both working properly
            Wonka.BizRulesEngine.Reporting.WonkaBizRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            string sStatusValueAfter = NewProduct.GetAttributeValue(AccountStsAttr);
            string sFlagValueAfter   = NewProduct.GetAttributeValue(RvwFlagAttr);

            if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS)
            {
                // NOTE: This should only be used for further testing
                // Serialize(NewProduct);
            }
            else if (Report.GetRuleSetFailureCount() > 0)
            {
                System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\"");
            }
            else
            {
                System.Console.WriteLine(".NET Engine says \"What in the world is happening?\"");
            }

            // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes
            // to use Orchestration
            if (!String.IsNullOrEmpty(moEthEngineInit.StorageContractAddress))
            {
                /**
                ** Now execute the rules engine on the blockchain.
                **
                ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly -
                **       If set to 'true', we issue a call() when we execute the rules engine, since we are only
                **       looking to validate here.  However, if the value if 'false', we issue a sendTransaction()
                **       so that we can attempts to set values (i.e., change the blockchain) will take effect.
                **       In that case, we might want to pull back the record afterwards with a subsequent function
                **       call, in order to examine the record here.
                **
                **/
                var BlockchainReport = await ExecuteWithReportAsync(RulesEngine, pbValidateTransaction).ConfigureAwait(false);

                if (BlockchainReport.NumberOfRuleFailures == 0)
                {
                    // Indication of a success
                }
                else if (BlockchainReport.NumberOfRuleFailures > 0)
                {
                    throw new Exception("Oh heavens to Betsy! Something bad happened!");
                }
                else
                {
                    throw new Exception("Seriously, what in the world is happening?!");
                }
            }

            return(bResult);
        }
Example #3
0
        /// <summary>
        ///
        /// This method will apply the arithmetic limit rule to either the incoming record or the current (i.e., database)
        /// record, using the other record as a reference.
        ///
        /// <param name="poTransactionRecord">The incoming record</param>
        /// <param name="poCurrentRecord">The current record (i.e., the already existing record)</param>
        /// <param name="poErrorMessage">The buffer that will contain an error message if the rule fails</param>
        /// <returns>Indicates whether or not the target product passed the rule successfully</returns>
        /// </summary>
        public override bool Execute(WonkaProduct poTransactionRecord,
                                     WonkaProduct poCurrentRecord,
                                     StringBuilder poErrorMessage)
        {
            bool bResult = false;

            WonkaProduct        TargetRecord = null;
            WonkaRefEnvironment WonkaRefEnv  = WonkaRefEnvironment.GetInstance();

            if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD)
            {
                TargetRecord = poTransactionRecord;
            }
            else if (RecordOfInterest == TARGET_RECORD.TRID_OLD_RECORD)
            {
                TargetRecord = poCurrentRecord;
            }
            else
            {
                throw new Exception("ERROR!  The target record is none!");
            }

            string sTargetData =
                TargetRecord.GetPrimaryAttributeData(TargetAttribute.GroupId, TargetAttribute.AttrId);

            if (!string.IsNullOrEmpty(sTargetData))
            {
                RefreshMinAndMax(poTransactionRecord, poCurrentRecord);

                try
                {
                    double dTargetValue = Convert.ToDouble(sTargetData);

                    if ((this.MaxValue >= dTargetValue) && (dTargetValue >= this.MinValue))
                    {
                        bResult = true;
                    }
                    else
                    {
                        bResult = false;
                    }

                    if (poErrorMessage != null)
                    {
                        poErrorMessage.Clear();
                        poErrorMessage.Append(GetVerboseError(TargetRecord));
                    }
                }
                catch (Exception ex)
                {
                    bResult = false;

                    if (poErrorMessage != null)
                    {
                        poErrorMessage.Clear();
                        poErrorMessage.Append(ex.ToString());
                    }
                }
            }

            return(bResult);
        }
Example #4
0
        /// <summary>
        ///
        /// This method will initialize an instance of the Wonka.Net engine, using all the data provided.
        ///
        /// <returns>None</returns>
        /// </summary>
        public static void InitEngine(this WonkaEthEngineInitialization poEngineInitData, bool pbRequireRetrieveValueMethod = true)
        {
            var EngineProps = poEngineInitData.Engine;

            if (EngineProps == null)
            {
                throw new Exception("ERROR!  No engine properties provided.");
            }

            if ((EngineProps.RulesEngine == null) && !String.IsNullOrEmpty(EngineProps.RulesMarkupXml))
            {
                if (pbRequireRetrieveValueMethod && (EngineProps.DotNetRetrieveMethod == null))
                {
                    throw new WonkaEthInitException("ERROR!  Retrieve method not provided for the Wonka.NET engine.", poEngineInitData);
                }

                if (EngineProps.MetadataSource == null)
                {
                    throw new WonkaEthInitException("ERROR!  No metadata source has been provided.", poEngineInitData);
                }

                // Using the metadata source, we create an instance of a defined data domain
                WonkaRefEnvironment WonkaRefEnv = WonkaRefEnvironment.CreateInstance(false, EngineProps.MetadataSource);

                var account = new Account(poEngineInitData.EthPassword);

                Nethereum.Web3.Web3 web3 = null;
                if (!String.IsNullOrEmpty(poEngineInitData.Web3HttpUrl))
                {
                    web3 = new Nethereum.Web3.Web3(account, poEngineInitData.Web3HttpUrl);
                }
                else
                {
                    web3 = new Nethereum.Web3.Web3(account);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RulesEngineContractAddress))
                {
                    var EngineDeployment = new Autogen.WonkaEngine.WonkaEngineDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_ENGINE_CONTRACT_GAS_COST);

                    poEngineInitData.RulesEngineContractAddress =
                        EngineDeployment.DeployContract(web3, poEngineInitData.RulesEngineABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RegistryContractAddress))
                {
                    var RegistryDeployment = new Autogen.WonkaRegistry.WonkaRegistryDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.RegistryContractAddress =
                        RegistryDeployment.DeployContract(web3, poEngineInitData.RegistryContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl);
                }

                if (String.IsNullOrEmpty(poEngineInitData.StorageContractAddress))
                {
                    var TestContractDeployment = new Autogen.WonkaTestContract.WonkaTestContractDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.StorageContractAddress =
                        TestContractDeployment.DeployContract(web3, poEngineInitData.StorageContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl);
                }

                if ((EngineProps.SourceMap == null) || (EngineProps.SourceMap.Count == 0))
                {
                    EngineProps.SourceMap = new Dictionary <string, WonkaBre.RuleTree.WonkaBreSource>();

                    // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods
                    // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type
                    foreach (WonkaRefAttr TempAttr in WonkaRefEnv.AttrCache)
                    {
                        WonkaBreSource TempSource =
                            new WonkaBreSource(poEngineInitData.StorageDefaultSourceId,
                                               poEngineInitData.EthSenderAddress,
                                               poEngineInitData.EthPassword,
                                               poEngineInitData.StorageContractAddress,
                                               poEngineInitData.StorageContractABI,
                                               poEngineInitData.StorageGetterMethod,
                                               poEngineInitData.StorageSetterMethod,
                                               EngineProps.DotNetRetrieveMethod);

                        EngineProps.SourceMap[TempAttr.AttrName] = TempSource;
                    }
                }

                EngineProps.RulesEngine =
                    new WonkaBreRulesEngine(new StringBuilder(EngineProps.RulesMarkupXml), EngineProps.SourceMap, EngineProps.MetadataSource);

                EngineProps.RulesEngine.DefaultSource = poEngineInitData.StorageDefaultSourceId;

                EngineProps.RulesEngine.SetDefaultStdOps(poEngineInitData.EthPassword, poEngineInitData.Web3HttpUrl);
            }
        }
        public WonkaSimpleCustomOpsTest(string psSenderAddress, string psPassword, string psContractAddress, bool pbSerializeMetadataToBlockchain = true)
        {
            msSenderAddress   = psSenderAddress;
            msPassword        = psPassword;
            msContractAddress = psContractAddress;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data record
            moMetadataSource = new WonkaMetadataVATSource();

            var TmpAssembly = Assembly.GetExecutingAssembly();

            // Read the ABI of the Ethereum contract for the Wonka rules engine
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.abi")))
            {
                msAbiWonka = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract for the Wonka rules engine
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.bin")))
            {
                msByteCodeWonka = ByteCodeReader.ReadToEnd();
            }

            // Read the ABI of the Ethereum contract that will demonstrate both our Custom Operator functionality and our Orchestration functionality
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.abi")))
            {
                msAbiOrchTest = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract that will hold our data record and provide Custom Operator functionality
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.bin")))
            {
                msByteCodeOrchTest = ByteCodeReader.ReadToEnd();
            }

            // Read the XML markup that lists the business rules
            using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.VATCalculationExample.xml")))
            {
                msRulesContents = RulesReader.ReadToEnd();
            }

            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment WonkaRefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr NewSalesTransSeqAttr    = WonkaRefEnv.GetAttributeByAttrName("NewSalesTransSeq");
            WonkaRefAttr NewSaleVATRateDenomAttr = WonkaRefEnv.GetAttributeByAttrName("NewSaleVATRateDenom");
            WonkaRefAttr NewSaleItemTypeAttr     = WonkaRefEnv.GetAttributeByAttrName("NewSaleItemType");
            WonkaRefAttr CountryOfSaleAttr       = WonkaRefEnv.GetAttributeByAttrName("CountryOfSale");
            WonkaRefAttr NewSalePriceAttr        = WonkaRefEnv.GetAttributeByAttrName("NewSalePrice");
            WonkaRefAttr PrevSellTaxAmountAttr   = WonkaRefEnv.GetAttributeByAttrName("PrevSellTaxAmount");
            WonkaRefAttr NewSellTaxAmountAttr    = WonkaRefEnv.GetAttributeByAttrName("NewSellTaxAmount");
            WonkaRefAttr NewVATAmountForHMRCAttr = WonkaRefEnv.GetAttributeByAttrName("NewVATAmountForHMRC");
            WonkaRefAttr NewSaleEANAttr          = WonkaRefEnv.GetAttributeByAttrName("NewSaleEAN");

            // We create a target list of the Attributes of the old (i.e., existing) record that currently exists on the blockchain
            // and which we want to pull back during the engine's execution
            moTargetAttrList = new List <WonkaRefAttr>();

            moTargetAttrList =
                new List <WonkaRefAttr>()
            {
                NewSalesTransSeqAttr, NewSaleVATRateDenomAttr, NewSaleItemTypeAttr,
                CountryOfSaleAttr, NewSalePriceAttr, PrevSellTaxAmountAttr,
                NewSellTaxAmountAttr, NewVATAmountForHMRCAttr, NewSaleEANAttr
            };

            if (pbSerializeMetadataToBlockchain)
            {
                SerializeMetadataToBlockchain();
            }
        }
Example #6
0
        /// <summary>
        ///
        /// This method will apply the assignment rule to either the transaction record or the current (i.e., database)
        /// record, using the other record as a reference.
        ///
        /// <param name="poTransactionRecord">The incoming record</param>
        /// <param name="poCurrentRecord">The current record (i.e., in the database)</param>
        /// <param name="poErrorMessage">The buffer that will contain an error message if the rule fails</param>
        /// <returns>Indicates whether or not the target product passed the rule successfully</returns>
        /// </summary>
        public override bool Execute(WonkaProduct poTransactionRecord,
                                     WonkaProduct poCurrentRecord,
                                     StringBuilder poErrorMessage)
        {
            bool bResult      = false;
            bool bAssignValue = true;

            int nAttrId  = TargetAttribute.AttrId;
            int nGroupId = TargetAttribute.GroupId;

            WonkaProduct        TargetRecord = null;
            WonkaRefEnvironment WonkaRefEnv  = WonkaRefEnvironment.GetInstance();

            if (poTransactionRecord == null)
            {
                throw new Exception("ERROR!  The new Product is null.");
            }

            if (poCurrentRecord == null)
            {
                throw new Exception("ERROR!  The old Product is null.");
            }

            if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD)
            {
                TargetRecord = poTransactionRecord;
            }
            else if (RecordOfInterest == TARGET_RECORD.TRID_OLD_RECORD)
            {
                TargetRecord = poCurrentRecord;
            }
            else
            {
                throw new Exception("ERROR!  The target record is none!");
            }

            if (DefaultAssignment)
            {
                WonkaPrdGroup TempProductGroup = null;

                if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD)
                {
                    TempProductGroup = poTransactionRecord.GetProductGroup(nGroupId);
                }
                else
                {
                    TempProductGroup = poCurrentRecord.GetProductGroup(nGroupId);
                }

                string sCurrentValue = "";

                if (TempProductGroup.GetRowCount() > 0)
                {
                    if (TempProductGroup[0].ContainsKey(nAttrId))
                    {
                        sCurrentValue = TempProductGroup[0][nAttrId];
                    }
                }

                if (!String.IsNullOrEmpty(sCurrentValue))
                {
                    bAssignValue = false;
                }
            }

            if (bAssignValue)
            {
                RefreshAssignValue(poTransactionRecord, poCurrentRecord);

                WonkaPrdGroup TempProductGroup = null;

                if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD)
                {
                    TempProductGroup = poTransactionRecord.GetProductGroup(nGroupId);
                }
                else
                {
                    TempProductGroup = poCurrentRecord.GetProductGroup(nGroupId);
                }

                TempProductGroup[0][nAttrId] = AssignValue;
            }

            return(bResult);
        }
        public void Execute(string psOrchestrationTestAddress = null, bool pbValidateWithinTransaction = false)
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            Dictionary <string, WonkaBre.RuleTree.WonkaBreSource> SourceMap =
                new Dictionary <string, WonkaBre.RuleTree.WonkaBreSource>();

            string sDefaultSourceId  = "S";
            string sContractSourceId = sDefaultSourceId;
            string sContractAddress  = "";
            string sContractAbi      = "";
            string sOrchGetterMethod = "";
            string sOrchSetterMethod = "";

            // These values indicate the Custom Operator "INVOKE_VAT_LOOKUP" which has been used in the markup -
            // its implementation can be found in the method "lookupVATDenominator"
            string sCustomOpId     = "INVOKE_VAT_LOOKUP";
            string sCustomOpMethod = "lookupVATDenominator";

            // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes
            // to use Orchestration
            if (!String.IsNullOrEmpty(psOrchestrationTestAddress))
            {
                sContractAddress  = psOrchestrationTestAddress;
                sContractAbi      = msAbiOrchTest;
                sOrchGetterMethod = "getAttrValueBytes32";
                sOrchSetterMethod = "setAttrValueBytes32";
            }
            else
            {
                sContractAddress  = msContractAddress;
                sContractAbi      = msAbiWonka;
                sOrchGetterMethod = "getValueOnRecord";
                sOrchSetterMethod = "";
            }

            WonkaBreSource DefaultSource =
                new WonkaBreSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod);

            // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods
            // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type
            foreach (WonkaRefAttr TempAttr in moTargetAttrList)
            {
                SourceMap[TempAttr.AttrName] = DefaultSource;
            }

            Dictionary <string, WonkaBreSource> CustomOpSourceMap = new Dictionary <string, WonkaBreSource>();

            // Here a mapping is created, where each Custom Operator points to a specific contract and its "implementation" method
            // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type
            WonkaBreSource CustomOpSource =
                new WonkaBreSource(sCustomOpId, msSenderAddress, msPassword, sContractAddress, sContractAbi, LookupVATDenominator, sCustomOpMethod);

            CustomOpSourceMap[sCustomOpId] = CustomOpSource;

            // Creating an instance of the rules engine using our rules and the metadata
            WonkaBreRulesEngine RulesEngine =
                new WonkaBreRulesEngine(new StringBuilder(msRulesContents), SourceMap, CustomOpSourceMap, moMetadataSource, false);

            RulesEngine.DefaultSource = sDefaultSourceId;

            // The contract dictates that the RuleTree (and its other info, like the Orchestration and CU metadata)
            // is serialized to the blockchain before interacting with it
            SerializeRulesEngineToBlockchain(RulesEngine);

            WonkaRefAttr NewSellTaxAmountAttr    = RefEnv.GetAttributeByAttrName("NewSellTaxAmount");
            WonkaRefAttr NewVATAmountForHMRCAttr = RefEnv.GetAttributeByAttrName("NewVATAmountForHMRC");

            // Gets a predefined data record that will be our analog for new data coming into the system
            // We are only using this record to test the .NET implementation
            WonkaProduct NewProduct = GetNewProduct();

            string sSellAmtBefore = GetAttributeValue(NewProduct, NewSellTaxAmountAttr);
            string sVATAmtBefore  = GetAttributeValue(NewProduct, NewVATAmountForHMRCAttr);

            /**
            ** Test the .NET side
            */
            WonkaBre.Reporting.WonkaBreRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            string sSellAmtAfter = GetAttributeValue(NewProduct, NewSellTaxAmountAttr);
            string sVATAmtAfter  = GetAttributeValue(NewProduct, NewVATAmountForHMRCAttr);

            if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS)
            {
                // NOTE: This should only be used for further testing
                // Serialize(NewProduct);
            }
            else if (Report.GetRuleSetFailureCount() > 0)
            {
                System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\"");
            }
            else
            {
                System.Console.WriteLine(".NET Engine says \"What in the world is happening?\"");
            }

            // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes
            // to use Orchestration
            if (!String.IsNullOrEmpty(psOrchestrationTestAddress))
            {
                /**
                ** Now execute the rules engine on the blockchain, using both Orchestration to call accessors
                ** on other contract(s) and Custom Operators to invoke the "INVOKE_VAT_LOOKUP" operator
                ** (i.e., the "lookupVATDenominator()" method) implemented on a contract.
                **
                ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly -
                **       If set to 'true', we issue a call() when we execute the rules engine, since we are only
                **       looking to validate here.  However, if the value if 'false', we issue a sendTransaction()
                **       so that we can attempts to set values (i.e., change the blockchain) will take effect.
                **       In that case, we might want to pull back the record afterwards with a subsequent function
                **       call, in order to examine the record here.
                **
                **/
                var BlockchainReport = ExecuteWithReport(RulesEngine, pbValidateWithinTransaction, SourceMap[NewSellTaxAmountAttr.AttrName], psOrchestrationTestAddress);

                if (BlockchainReport.NumberOfRuleFailures == 0)
                {
                    // Indication of a success
                }
                else if (BlockchainReport.NumberOfRuleFailures > 0)
                {
                    throw new Exception("Oh heavens to Betsy! Something bad happened!");
                }
                else
                {
                    throw new Exception("Seriously, what in the world is happening?!");
                }
            }
        }
        public RuleTreeReport ExecuteWithReport(WonkaBreRulesEngine poRulesEngine, bool pbValidateWithinTransaction, WonkaBreSource poSource, string psOrchestrationAddress)
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            WonkaRefAttr NewSellTaxAmountAttr    = RefEnv.GetAttributeByAttrName("NewSellTaxAmount");
            WonkaRefAttr NewVATAmountForHMRCAttr = RefEnv.GetAttributeByAttrName("NewVATAmountForHMRC");
            WonkaRefAttr NewSalesTransSeqAttr    = RefEnv.GetAttributeByAttrName("NewSalesTransSeq");
            WonkaRefAttr NewSaleVATRateDenomAttr = RefEnv.GetAttributeByAttrName("NewSaleVATRateDenom");
            WonkaRefAttr PrevSellTaxAmtAttr      = RefEnv.GetAttributeByAttrName("PrevSellTaxAmount");
            WonkaRefAttr NewSaleItemTypeAttr     = RefEnv.GetAttributeByAttrName("NewSaleItemType");
            WonkaRefAttr CountryOfSaleAttr       = RefEnv.GetAttributeByAttrName("CountryOfSale");

            bool bTestLookupMethod = true;

            Dictionary <string, string> PrdKeys = new Dictionary <string, string>();

            var contract = GetContract();

            var executeWithReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_EXEC_RPT);

            RuleTreeReport ruleTreeReport = null;

            if (bTestLookupMethod)
            {
                var contractOrchTest = GetContractOrchTest(psOrchestrationAddress);

                var gas = new Nethereum.Hex.HexTypes.HexBigInteger(1000000);

                var executeLookupFunction = contractOrchTest.GetFunction("lookupVATDenominator");
                var lookupValue           = executeLookupFunction.CallAsync <string>("Widget", "UK", "", "").Result;

                var getValOnRecordFunction = contract.GetFunction("getValueOnRecord");
                var attrVal = getValOnRecordFunction.CallAsync <string>(poSource.SenderAddress, "NewSaleItemType").Result;
            }

            if (pbValidateWithinTransaction)
            {
                var executeGetLastReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_GET_LAST_RPT);

                // NOTE: Caused exception to be thrown
                // var gas = executeWithReportFunction.EstimateGasAsync(msSenderAddress).Result;
                var gas = new Nethereum.Hex.HexTypes.HexBigInteger(2000000);

                WonkaProduct OrchContractCurrValues = poRulesEngine.AssembleCurrentProduct(new Dictionary <string, string>());

                string sNSTABeforeOrchestrationAssignment  = RetrieveValueMethod(poSource, NewSellTaxAmountAttr.AttrName);
                string sNVABeforeOrchestrationAssignment   = RetrieveValueMethod(poSource, NewVATAmountForHMRCAttr.AttrName);
                string sNSTSBeforeOrchestrationAssignment  = RetrieveValueMethod(poSource, NewSalesTransSeqAttr.AttrName);
                string sNSVRDBeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleVATRateDenomAttr.AttrName);
                string sPSTABeforeOrchestrationAssignment  = RetrieveValueMethod(poSource, PrevSellTaxAmtAttr.AttrName);
                string sNSITDBeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleItemTypeAttr.AttrName);
                string sCoSBeforeOrchestrationAssignment   = RetrieveValueMethod(poSource, CountryOfSaleAttr.AttrName);

                var receiptAddAttribute =
                    executeWithReportFunction.SendTransactionAsync(msSenderAddress, gas, null, msSenderAddress).Result;

                string sNSTAfterOrchestrationAssignment   = RetrieveValueMethod(poSource, NewSellTaxAmountAttr.AttrName);
                string sNVAAfterOrchestrationAssignment   = RetrieveValueMethod(poSource, NewVATAmountForHMRCAttr.AttrName);
                string sNSTSAfterOrchestrationAssignment  = RetrieveValueMethod(poSource, NewSalesTransSeqAttr.AttrName);
                string sNSVRDAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleVATRateDenomAttr.AttrName);
                string sPSTAAfterOrchestrationAssignment  = RetrieveValueMethod(poSource, PrevSellTaxAmtAttr.AttrName);
                string sNSITDAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleItemTypeAttr.AttrName);
                string sCoSAfterOrchestrationAssignment   = RetrieveValueMethod(poSource, CountryOfSaleAttr.AttrName);

                ruleTreeReport = executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().Result;
            }
            else
            {
                ruleTreeReport = executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(msSenderAddress).Result;
            }

            return(ruleTreeReport);
        }
Example #9
0
        /// <summary>
        ///
        /// This method will iterate through all of the data in the contained groups and detect whether
        /// any of them are not valid according to the designated type for that Attribute.
        ///
        /// <param name="poErrors">The list to which we will add any errors concerning the validation of types</param>
        /// <returns>Indicates whether or not there any errors with validating types</returns>
        /// </summary>
        public bool ValidateTypes(List <WonkaProductError> poErrors)
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            bool bResult = true;

            foreach (int nGrpId in this.ProductGroups.Keys)
            {
                WonkaPrdGroup TempGroup = ProductGroups[nGrpId];

                foreach (WonkaPrdGroupDataRow TempDataRow in TempGroup)
                {
                    foreach (int nAttrId in TempDataRow.Keys)
                    {
                        string sAttrValue = TempDataRow[nAttrId];

                        if (!String.IsNullOrEmpty(sAttrValue))
                        {
                            WonkaRefAttr TempAttr = RefEnv.GetAttributeByAttrId(nAttrId);

                            if (TempAttr.IsDecimal)
                            {
                                try
                                {
                                    Decimal dValue = Convert.ToDecimal(sAttrValue);
                                }
                                catch (Exception ex)
                                {
                                    poErrors.Add(new WonkaProductError()
                                    {
                                        AttrName     = TempAttr.AttrName,
                                        ErrorMessage = "ERROR!  Value(" + sAttrValue + ") is not a valid decimal!"
                                    });
                                }
                            }
                            else if (TempAttr.IsNumeric)
                            {
                                try
                                {
                                    long nValue = Convert.ToInt64(sAttrValue);
                                }
                                catch (Exception ex)
                                {
                                    poErrors.Add(new WonkaProductError()
                                    {
                                        AttrName     = TempAttr.AttrName,
                                        ErrorMessage = "ERROR!  Value(" + sAttrValue + ") is not a valid number!"
                                    });
                                }
                            }
                            else if (TempAttr.IsDate)
                            {
                                try
                                {
                                    DateTime dtValue = DateTime.Parse(sAttrValue);
                                }
                                catch (Exception ex)
                                {
                                    poErrors.Add(new WonkaProductError()
                                    {
                                        AttrName     = TempAttr.AttrName,
                                        ErrorMessage = "ERROR!  Value(" + sAttrValue + ") is not a valid date!"
                                    });
                                }
                            }
                        }
                    }
                }
            }

            return(bResult);
        }
        public WonkaSimpleOrchestrationTest(string psSenderAddress, string psPassword, string psContractAddress, bool pbSerializeMetadataToBlockchain = true)
        {
            msSenderAddress   = psSenderAddress;
            msPassword        = psPassword;
            msContractAddress = psContractAddress;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data record
            moMetadataSource = new WonkaMetadataTestSource();

            var TmpAssembly = Assembly.GetExecutingAssembly();

            // Read the ABI of the Ethereum contract for the Wonka rules engine
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.abi")))
            {
                msAbiWonka = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract for the Wonka rules engine
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.bin")))
            {
                msByteCodeWonka = ByteCodeReader.ReadToEnd();
            }

            // Read the ABI of the Ethereum contract that will demonstrate our Orchestration functionality by getting/setting Attribute values
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.abi")))
            {
                msAbiOrchTest = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract that will hold our data record
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.bin")))
            {
                msByteCodeOrchTest = ByteCodeReader.ReadToEnd();
            }

            // Read the XML markup that lists the business rules
            using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.SimpleAccountCheck.xml")))
            {
                msRulesContents = RulesReader.ReadToEnd();
            }

            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment WonkaRefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr AccountIDAttr       = WonkaRefEnv.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr AccountNameAttr     = WonkaRefEnv.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr AccountStsAttr      = WonkaRefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AccountCurrValAttr  = WonkaRefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr AccountTypeAttr     = WonkaRefEnv.GetAttributeByAttrName("AccountType");
            WonkaRefAttr AccountCurrencyAttr = WonkaRefEnv.GetAttributeByAttrName("AccountCurrency");
            WonkaRefAttr RvwFlagAttr         = WonkaRefEnv.GetAttributeByAttrName("AuditReviewFlag");

            // We create a target list of the Attributes of the old (i.e., existing) record that currently exists on the blockchain
            // and which we want to pull back during the engine's execution
            moTargetAttrList = new List <WonkaRefAttr>();

            moTargetAttrList =
                new List <WonkaRefAttr>()
            {
                AccountIDAttr, AccountNameAttr, AccountStsAttr, AccountCurrValAttr, AccountTypeAttr, AccountCurrencyAttr, RvwFlagAttr
            };

            // Serialize the data domain to the blockchain
            if (pbSerializeMetadataToBlockchain)
            {
                SerializeMetadataToBlockchain();
            }
        }
        public void Execute(string psOrchestrationTestAddress = null, bool pbValidateWithinTransaction = false)
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            Dictionary <string, WonkaBre.RuleTree.WonkaBreSource> SourceMap =
                new Dictionary <string, WonkaBre.RuleTree.WonkaBreSource>();

            string sDefaultSource    = "S";
            string sContractSourceId = sDefaultSource;
            string sContractAddress  = "";
            string sContractAbi      = "";
            string sOrchGetterMethod = "";
            string sOrchSetterMethod = "";

            // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes
            // to use Orchestration
            if (!String.IsNullOrEmpty(psOrchestrationTestAddress))
            {
                // Here we set the values for Orchestration (like the target contract) and the implemented
                // methods that have the expected function signatures for getting/setting Attribute values
                sContractAddress  = psOrchestrationTestAddress;
                sContractAbi      = msAbiOrchTest;
                sOrchGetterMethod = "getAttrValueBytes32";
                sOrchSetterMethod = "setAttrValueBytes32";
            }
            else
            {
                sContractAddress  = msContractAddress;
                sContractAbi      = msAbiWonka;
                sOrchGetterMethod = "getValueOnRecord";
                sOrchSetterMethod = "";
            }

            // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods
            // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type
            foreach (WonkaRefAttr TempAttr in moTargetAttrList)
            {
                WonkaBreSource TempSource =
                    new WonkaBreSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod);

                SourceMap[TempAttr.AttrName] = TempSource;
            }

            // Creating an instance of the rules engine using our rules and the metadata
            WonkaBreRulesEngine RulesEngine = null;

            if (psOrchestrationTestAddress == null)
            {
                RulesEngine = new WonkaBreRulesEngine(new StringBuilder(msRulesContents), moMetadataSource);
            }
            else
            {
                RulesEngine = new WonkaBreRulesEngine(new StringBuilder(msRulesContents), SourceMap, moMetadataSource);
                RulesEngine.DefaultSource = sDefaultSource;
            }

            // The contract dictates that the RuleTree (and its other info, like the Source mapping) is serialized
            // to the blockchain before interacting with it
            SerializeRulesEngineToBlockchain(RulesEngine);

            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr RvwFlagAttr    = RefEnv.GetAttributeByAttrName("AuditReviewFlag");

            // Gets a predefined data record that will be our analog for new data coming into the system
            // We are only using this record to test the .NET implementation
            WonkaProduct NewProduct = GetNewProduct();

            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);
            string sFlagValueBefore   = GetAttributeValue(NewProduct, RvwFlagAttr);

            // SerializeProductToBlockchain(NewProduct);

            // Validate that the .NET implementation and the rules markup are both working properly
            WonkaBre.Reporting.WonkaBreRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr);
            string sFlagValueAfter   = GetAttributeValue(NewProduct, RvwFlagAttr);

            if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS)
            {
                // NOTE: This should only be used for further testing
                // Serialize(NewProduct);
            }
            else if (Report.GetRuleSetFailureCount() > 0)
            {
                System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\"");
            }
            else
            {
                System.Console.WriteLine(".NET Engine says \"What in the world is happening?\"");
            }

            // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes
            // to use Orchestration
            if (!String.IsNullOrEmpty(psOrchestrationTestAddress))
            {
                /**
                ** Now execute the rules engine on the blockchain.
                **
                ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly -
                **       If set to 'true', we issue a call() when we execute the rules engine, since we are only
                **       looking to validate here.  However, if the value if 'false', we issue a sendTransaction()
                **       so that we can attempts to set values (i.e., change the blockchain) will take effect.
                **       In that case, we might want to pull back the record afterwards with a subsequent function
                **       call, in order to examine the record here.
                **
                **/
                var BlockchainReport = ExecuteWithReport(RulesEngine, pbValidateWithinTransaction, SourceMap[RvwFlagAttr.AttrName]);

                if (BlockchainReport.NumberOfRuleFailures == 0)
                {
                    // Indication of a success
                }
                else if (BlockchainReport.NumberOfRuleFailures > 0)
                {
                    throw new Exception("Oh heavens to Betsy! Something bad happened!");
                }
                else
                {
                    throw new Exception("Seriously, what in the world is happening?!");
                }
            }
        }
Example #12
0
        public WonkaNoviceNethereumTest(string psSenderAddress, string psPassword, string psContractAddress = null, bool bSerializeMetadataAndEngine = true)
        {
            msSenderAddress = psSenderAddress;
            msPassword      = psPassword;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data records
            moMetadataSource = new WonkaMetadataTestSource();

            var TmpAssembly = Assembly.GetExecutingAssembly();

            // Read the ABI of the Ethereum contract for the Wonka rules engine and holds our data record
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.abi")))
            {
                msAbiWonka = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract for the Wonka rules engine and holds our data record
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.bin")))
            {
                msByteCodeWonka = ByteCodeReader.ReadToEnd();
            }

            // Read the XML markup that lists the business rules
            using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.SimpleAccountCheck.xml")))
            {
                msRulesContents = RulesReader.ReadToEnd();
            }

            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment WonkaRefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr AccountIDAttr       = WonkaRefEnv.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr AccountNameAttr     = WonkaRefEnv.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr AccountStsAttr      = WonkaRefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AccountCurrValAttr  = WonkaRefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr AccountTypeAttr     = WonkaRefEnv.GetAttributeByAttrName("AccountType");
            WonkaRefAttr AccountCurrencyAttr = WonkaRefEnv.GetAttributeByAttrName("AccountCurrency");

            // We create a target list of the Attributes of the old (i.e., existing) record that currently exists on the blockchain
            // and which we want to pull back during the engine's execution
            moTargetAttrList = new List <WonkaRefAttr>();

            moTargetAttrList =
                new List <WonkaRefAttr>()
            {
                AccountIDAttr, AccountNameAttr, AccountStsAttr, AccountCurrValAttr, AccountTypeAttr, AccountCurrencyAttr
            };

            if (psContractAddress == null)
            {
                msContractAddress = DeployContract();
            }
            else
            {
                msContractAddress = psContractAddress;
            }

            if (bSerializeMetadataAndEngine)
            {
                // Now we serialize the data domain to the blockchain
                SerializeMetadataToBlockchain();

                // And serialize the rules engine to the blockchain
                SerializeRulesEngineToBlockchain();
            }
        }
Example #13
0
        public void Execute()
        {
            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment RefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            var sWeb3Url       = "https://mainnet.infura.io/v3/7238211010344719ad14a89db874158c";
            var sSenderAddress = "0x12890D2cce102216644c59daE5baed380d84830c";
            var sPassword      = "******";
            var sERC20Address  = "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2";

            // To test whether the data domain has been created, we pull back one attribute
            WonkaRefAttr AccountStsAttr   = RefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AuditRvwFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag");

            Dictionary <string, WonkaBizSource> SourceMap = new Dictionary <string, WonkaBizSource>();

            /*
             * WonkaBizSource DefaultSource =
             *  new WonkaBizSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod);
             */

            WonkaBizSource DefaultSource =
                new WonkaBizSource("", "", "", "", null);

            // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods
            // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type
            foreach (WonkaRefAttr TempAttr in RefEnv.AttrCache)
            {
                SourceMap[TempAttr.AttrName] = DefaultSource;
            }

            var WonkaEthEngInit =
                new WonkaEthEngineInitialization()
            {
                EthSenderAddress      = sSenderAddress,
                EthPassword           = sPassword,
                ERC20ContractAddress  = sERC20Address,
                ERC721ContractAddress = "",
                Web3HttpUrl           = sWeb3Url
            };

            // Creating an instance of the rules engine using our rules and the metadata
            WonkaBizRulesEngine RulesEngine =
                new WonkaEthRulesEngine(new StringBuilder(msRulesContents), SourceMap, WonkaEthEngInit, moMetadataSource);

            // Gets a predefined data record that will be our analog for new data coming into the system
            WonkaProduct NewProduct = GetNewProduct();

            // Check that the data has been populated correctly on the "new" record
            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);

            // RulesEngine.GetCurrentProductDelegate = GetOldProduct;

            // Validate the new record using our rules engine and its initialized RuleTree
            Wonka.BizRulesEngine.Reporting.WonkaBizRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            // Now retrieve the AccountStatus value and see if the rules have altered it (which should
            // not be the case)
            string sStatusValueAfter  = GetAttributeValue(NewProduct, AccountStsAttr);
            string sAuditRvwFlagAfter = GetAttributeValue(NewProduct, AuditRvwFlagAttr);

            if (Report.GetRuleSetFailureCount() > 0)
            {
                throw new Exception("Oh heavens to Betsy! Something bad happened!");
            }
        }