Example #1
0
        public void TestKeccakHashing(string expected, string input, bool shouldMatch)
        {
            var result = KeccakHash.FromString(input).ToHexString(hexPrefix: false);

            if (shouldMatch)
            {
                Assert.Equal(expected, result);
            }
            else
            {
                Assert.NotEqual(expected, result);
            }
        }
        void GenerateSources()
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            string[] solFiles;
            if (!string.IsNullOrEmpty(_solSourceSingleFile))
            {
                solFiles = new[] { _solSourceSingleFile };
            }
            else
            {
                solFiles = GetSolContractFiles(_solSourceDirectory);
            }

            var outputFlags = new[]
            {
                OutputType.Abi,
                OutputType.EvmBytecodeObject,
                OutputType.EvmBytecodeOpcodes,
                OutputType.EvmBytecodeSourceMap,
                OutputType.EvmDeployedBytecodeObject,
                OutputType.EvmDeployedBytecodeOpcodes,
                OutputType.EvmDeployedBytecodeSourceMap,
                OutputType.DevDoc,
                OutputType.UserDoc,
                OutputType.Metadata,
                OutputType.Ast
            };

            var solcOptimizerSettings = new Optimizer();

            if (_solcOptimzer > 0)
            {
                solcOptimizerSettings.Enabled = true;
                solcOptimizerSettings.Runs    = _solcOptimzer;
            }

            _logger("Compiling solidity files in " + _solSourceDirectory);
            var soliditySourceContent = new Dictionary <string, string>();
            var solcOutput            = _solcLib.Compile(solFiles, outputFlags, solcOptimizerSettings, soliditySourceFileContent: soliditySourceContent);

            sw.Stop();
            _logger($"Compiling solidity completed in {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");

            #region Generated hashes for solidity sources
            sw.Restart();

            // Calculate a deterministic hash of the solidity source code base, including file paths and the Meadow assembly version.
            var codeBaseHash = KeccakHash.FromString(string.Join('|', soliditySourceContent
                                                                 .OrderBy(k => k.Key)
                                                                 .SelectMany(k => new[] { k.Key, k.Value })
                                                                 .Concat(new[] { _assemblyVersion })));

            _genResults.SolcCodeBaseHash = HexUtil.GetHexFromBytes(codeBaseHash);

            var            flattenedContracts = solcOutput.ContractsFlattened.OrderBy(c => c.SolFile).ToArray();
            ContractInfo[] contractInfos      = new ContractInfo[solcOutput.ContractsFlattened.Length];

            for (var i = 0; i < contractInfos.Length; i++)
            {
                var c = flattenedContracts[i];

                // Check if any previous contracts have the same name as this one.
                int dupNames = 0;
                for (var f = 0; f < i; f++)
                {
                    if (flattenedContracts[f].ContractName == c.ContractName)
                    {
                        dupNames++;
                    }
                }

                string generatedContractName = c.ContractName;

                // If there are duplicate contract names, prepend a unique amount of underscore suffixes.
                if (dupNames > 0)
                {
                    generatedContractName += new string(Enumerable.Repeat('_', dupNames).ToArray());
                }

                contractInfos[i] = new ContractInfo(
                    Util.GetRelativeFilePath(_solSourceDirectory, c.SolFile),
                    generatedContractName,
                    c.Contract,
                    GetSourceHashesXor(c.Contract),
                    c.Contract.Evm.Bytecode.Object);
            }



            _logger($"Generated sol source file hashes in {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");
            sw.Stop();
            #endregion


            _logger("Writing generated output to directory: " + _generatedContractsDirectory);

            #region Output directory cleanup
            if (!Directory.Exists(_generatedContractsDirectory))
            {
                _logger("Creating directory: " + _generatedContractsDirectory);
                Directory.CreateDirectory(_generatedContractsDirectory);
            }
            else
            {
                var expectedFiles = contractInfos
                                    .Select(c => c.ContractName)
                                    .Concat(new[] { EventHelperFile, SolcOutputDataHelperFile })
                                    .Select(c => NormalizePath($"{_generatedContractsDirectory}/{c}{G_CS_FILE_EXT}"))
                                    .ToArray();

                var existingFiles = Directory
                                    .GetFiles(_generatedContractsDirectory, $"*{G_CS_FILE_EXT}", SearchOption.TopDirectoryOnly)
                                    .Where(f => f.EndsWith(".sol.cs", StringComparison.Ordinal) || f.EndsWith(".sol.resx", StringComparison.Ordinal))
                                    .Select(f => NormalizePath(f))
                                    .ToArray();

                // Delete existing files with no corresponding file that can be generated
                foreach (var existingFile in existingFiles)
                {
                    bool found = false;
                    foreach (var expected in expectedFiles)
                    {
                        if (expected.Equals(existingFile, StringComparison.InvariantCultureIgnoreCase))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        _logger("Deleting outdated file: " + existingFile);
                        File.Delete(existingFile);
                    }
                }
            }
            #endregion

            #region AST output generation
            sw.Restart();
            GenerateSolcOutputDataFiles(solcOutput, soliditySourceContent, codeBaseHash);
            sw.Stop();
            _logger($"Resx file for solc output generation took: {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");
            #endregion


            #region
            sw.Restart();
            var generatedEvents = new List <GeneratedEventMetadata>();
            GeneratedContractSourceFiles(contractInfos, generatedEvents);
            GenerateEventHelper(generatedEvents);
            sw.Stop();
            _logger($"Contract and event source code generation took: {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");
            #endregion
        }