public string ToString(bool withHistogram, bool showHashes) { var sb = new StringBuilder(); using (var writer = new StringWriter(sb)) { writer.WriteLine($"Longest runtimes:"); foreach (var r in _list.OrderByDescending(i => i.Runtime).Take(10)) { writer.WriteLine($"Seed = {r.Seed}, Runtime = {r.Runtime:0.00000} s"); } writer.WriteLine($"Runtime [s] Min: {Runtime.Min:0.00000}; Max: {Runtime.Max:0.00000}; Avg: {Runtime.Average:0.00000}; Stdev: {Runtime.StdDev:0.00000};"); writer.WriteLine($"Runtime [s] 99.99th percentile: {Runtime.GetPercentile(0.9999)}"); writer.WriteLine($"Average entropy of program output (est.): {OutputEntropy:0.00} bits"); writer.WriteLine($"Cyclomatic complexity Min: {CyclomaticComplexity.Min}; Max: {CyclomaticComplexity.Max}; Avg: {CyclomaticComplexity.Average}; Stdev: {CyclomaticComplexity.StdDev};"); writer.WriteLine($"Lines of code Min: {LinesOfCode.Min}; Max: {LinesOfCode.Max}; Avg: {LinesOfCode.Average}; Stdev: {LinesOfCode.StdDev};"); writer.WriteLine($"Halstead difficulty Min: {HalsteadDifficulty.Min}; Max: {HalsteadDifficulty.Max}; Avg: {HalsteadDifficulty.Average}; Stdev: {HalsteadDifficulty.StdDev};"); writer.WriteLine($"Matches 'SyntaxError' optimization: {SyntaxErrorValidity:P2}"); writer.WriteLine($"'SyntaxError' optimization runtime: {SyntaxErrorRuntime:P2}"); writer.WriteLine($"Matches 'XS': {_list.Count(ri => ri.MatchXS) / (double)_list.Count:P2}"); if (withHistogram) { int[] histogram = new int[(int)Math.Ceiling((Runtime.Max - Runtime.Min) / Runtime.StdDev * 10)]; foreach (var run in _list) { var index = (int)(((run.Runtime - Runtime.Min) / Runtime.StdDev * 10)); histogram[index]++; } writer.WriteLine("Runtime histogram:"); for (int j = 0; j < histogram.Length; ++j) { writer.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00000} {1}", j * Runtime.StdDev / 10 + Runtime.Min, histogram[j])); } } using (var sha256 = new SHA256Managed()) { byte[] cumulative = new byte[sha256.HashSize / 8]; foreach (var ri in _list) { var hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(ri.Output)); if (showHashes) { Console.WriteLine($"{ri.Seed}: {BinaryUtils.ByteArrayToString(hash)}"); } for (int i = 0; i < hash.Length; ++i) { cumulative[i] ^= hash[i]; } } writer.WriteLine($"Cumulative output hash: {BinaryUtils.ByteArrayToString(cumulative)}"); } } return(sb.ToString()); }
static void Main(string[] args) { string blockTemplateHex = "0707f7a4f0d605b303260816ba3f10902e1a145ac5fad3aa3af6ea44c11869dc4f853f002b2eea0000000077b206a02ca5b1d4ce6bbfdf0acac38bded34d2dcdeef95cd20cefc12f61d56109"; if (args.Length > 0) { blockTemplateHex = args[0]; } if (blockTemplateHex.Length != 152 || blockTemplateHex.Any(c => !"0123456789abcdef".Contains(c))) { Console.WriteLine("Invalid block template (152 hex characters expected)."); } else { try { var blockTemplate = BinaryUtils.StringToByteArray(blockTemplateHex); var miner = new Miner(); miner.Reset(blockTemplate); TimeSpan period = TimeSpan.FromMinutes(1); List <Solution> solutions = new List <Solution>(100); Stopwatch sw = Stopwatch.StartNew(); while (sw.Elapsed < period) { var solution = miner.Solve(); Console.WriteLine($"Nonce = {solution.Nonce}; PoW = {BinaryUtils.ByteArrayToString(solution.ProofOfWork)}"); solutions.Add(solution); } sw.Stop(); var seconds = sw.Elapsed.TotalSeconds; Console.WriteLine(); Console.WriteLine($"Solving nonces: {string.Join(", ", solutions.Select(s => s.Nonce))}"); Console.WriteLine(); Console.WriteLine($"Found {solutions.Count} solutions in {seconds} seconds. Performance = {solutions.Count / seconds} Sols./s."); sw.Restart(); foreach (var sol in solutions) { if (!miner.Verify(sol)) { Console.WriteLine($"Nonce {sol.Nonce} - verification failed"); return; } } sw.Stop(); Console.WriteLine($"All {solutions.Count} solutions were verified in {sw.Elapsed.TotalSeconds} seconds"); } catch (Exception e) { Console.WriteLine($"ERROR: {e}"); } } }
private void _run() { var factory = new ProgramFactory(_options); var runner = new ProgramRunner(); RuntimeInfo ri; while ((ri = _stats.Add()) != null) { var smallSeed = Interlocked.Increment(ref _seed); var bigSeed = BinaryUtils.GenerateSeed(smallSeed); var p = factory.GenProgram(bigSeed); runner.WriteProgram(p); runner.ExecuteProgram(ri); ri.Seed = BinaryUtils.ByteArrayToString(bigSeed); Progress?.Invoke(this, EventArgs.Empty); } }
public override string ToString() { var sb = new StringBuilder(); using (var writer = new StringWriter(sb)) { writer.WriteLine($"Longest runtimes:"); for (int i = 1; i <= 10; ++i) { var r = _list[_list.Count - i]; writer.WriteLine($"Seed = {r.Seed}, Runtime = {r.Runtime:0.00000} s"); } writer.WriteLine($"Runtime [s] Min: {Runtime.Min:0.00000}; Max: {Runtime.Max:0.00000}; Avg: {Runtime.Average:0.00000}; Stdev: {Runtime.StdDev:0.00000};"); writer.WriteLine($"Runtime [s] 99.99th percentile: {Runtime.GetPercentile(0.9999)}"); writer.WriteLine($"Average entropy of program output (est.): {OutputEntropy:0.00} bits"); writer.WriteLine($"Cyclomatic complexity Min: {CyclomaticComplexity.Min}; Max: {CyclomaticComplexity.Max}; Avg: {CyclomaticComplexity.Average}; Stdev: {CyclomaticComplexity.StdDev};"); writer.WriteLine($"Halstead difficulty Min: {HalsteadDifficulty.Min}; Max: {HalsteadDifficulty.Max}; Avg: {HalsteadDifficulty.Average}; Stdev: {HalsteadDifficulty.StdDev};"); int[] histogram = new int[(int)Math.Ceiling((Runtime.Max - Runtime.Min) / Runtime.StdDev * 10)]; foreach (var run in _list) { var index = (int)(((run.Runtime - Runtime.Min) / Runtime.StdDev * 10)); histogram[index]++; } Console.WriteLine("Runtime histogram:"); for (int j = 0; j < histogram.Length; ++j) { writer.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00000} {1}", j * Runtime.StdDev / 10 + Runtime.Min, histogram[j])); } using (var sha256 = new SHA256Managed()) { byte[] cumulative = new byte[sha256.HashSize / 8]; foreach (var ri in _list) { var hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(ri.Output)); for (int i = 0; i < hash.Length; ++i) { cumulative[i] ^= hash[i]; } } writer.WriteLine($"Cumulative output hash: {BinaryUtils.ByteArrayToString(cumulative)}"); } } return(sb.ToString()); }
public bool Verify(Solution sol) { for (int i = 0; i < 4; ++i) { _blockTemplate[_nonceOffset + i] = (byte)(sol.Nonce >> (8 * i)); } byte[] key = _blake.ComputeHash(_blockTemplate); _blakeKeyed = new Blake2B256(key); var pow = _blakeKeyed.ComputeHash(sol.Result); if (!BinaryUtils.ArraysEqual(pow, sol.ProofOfWork)) { Console.WriteLine("Invalid PoW"); return(false); } var program = _factory.GenProgram(key); _runner.WriteProgram(program); var auxiliary = _blakeKeyed.ComputeHash(_runner.Buffer, 0, _runner.ProgramLength); if ((auxiliary[0] ^ sol.Result[0]) >= _bound) { Console.WriteLine("Invalid Auxiliary"); return(false); } auxiliary[0] &= _clearMask; var ri = _runner.ExecuteProgram(); if (!ri.Success) { throw new Exception(string.Format($"Program execution failed. Nonce value: {(sol.Nonce)}. Seed: {BinaryUtils.ByteArrayToString(key)}, {ri.Output}")); } var result = _blakeKeyed.ComputeHash(Encoding.ASCII.GetBytes(ri.Output)); for (int i = 0; i < result.Length; ++i) { result[i] ^= auxiliary[i]; } if (!BinaryUtils.ArraysEqual(sol.Result, result)) { Console.WriteLine("Invalid Result"); return(false); } return(true); }
public unsafe Solution Solve() { byte[] result = null; byte[] auxiliary = null; uint nonce; fixed(byte *block = _blockTemplate) { uint *noncePtr = (uint *)(block + _nonceOffset); do { (*noncePtr)++; byte[] key = _blake.ComputeHash(_blockTemplate); var program = _factory.GenProgram(key); _runner.WriteProgram(program); _blakeKeyed = new Blake2B256(key); auxiliary = _blakeKeyed.ComputeHash(_runner.Buffer, 0, _runner.ProgramLength); var ri = _runner.ExecuteProgram(); if (!ri.Success) { throw new Exception(string.Format($"Program execution failed. Nonce value: {(*noncePtr)}. Seed: {BinaryUtils.ByteArrayToString(key)}, {ri.Output}")); } result = _blakeKeyed.ComputeHash(Encoding.ASCII.GetBytes(ri.Output)); }while ((result[0] ^ auxiliary[0]) >= _bound); nonce = *noncePtr; } result[0] &= _clearMask; for (int i = 0; i < result.Length; ++i) { result[i] ^= auxiliary[i]; } return(new Solution() { Nonce = nonce, Result = result, ProofOfWork = _blakeKeyed.ComputeHash(result) }); }
private void _run(CancellationToken token) { var factory = new ProgramFactory(_options); //var defaultRunner = new ProgramRunner(); //var runnerNode = new ExternalProgramRunner("node", @"..\fast-eval.js"); //var runnerXS = new ExternalProgramRunner(@"..\moddable\build\bin\win\release\xst.exe"); var runner = ProgramRunnerBase.FromUri(_runnerUri); RuntimeInfo ri; while (!token.IsCancellationRequested && (ri = _stats.Add()) != null) { var smallSeed = Interlocked.Increment(ref _seed); var bigSeed = BinaryUtils.GenerateSeed(smallSeed); ri.Seed = BinaryUtils.ByteArrayToString(bigSeed); var p = factory.GenProgram(bigSeed); runner.WriteProgram(p); runner.ExecuteProgram(ri); if (!ri.Success) { throw new InvalidProgramException(); } /*bool retry = true; * while (!ri.Success && retry) * { * Console.WriteLine($"Error with seed {ri.Seed}"); * retry = false; * runner.WriteProgram(p); * runner.ExecuteProgram(ri); * } * if (ri.Success) * { * Console.WriteLine($"Success with seed {ri.Seed}"); * } * else * { * Console.WriteLine(ri.Output); * }*/ /*runnerXS.WriteProgram(p); * var xs = runnerXS.ExecuteProgram(); * xs.Output = xs.Output.Replace("\r", ""); * if(!(ri.MatchXS = ri.Output == xs.Output)) * { * Console.WriteLine($"Outputs differ with seed {ri.Seed}"); * var xsLines = xs.Output.Split('\n'); * var riLines = ri.Output.Split('\n'); * if(xsLines.Length != riLines.Length) * { * Console.WriteLine("NODE:"); * Console.WriteLine(ri.Output); * Console.WriteLine("--------------------"); * Console.WriteLine("XS:"); * Console.WriteLine(xs.Output); * Console.WriteLine("--------------------"); * throw new InvalidProgramException("Number of lines differ"); * } * for(int i = 0; i < xsLines.Length; ++i) * { * if(xsLines[i] != riLines[i]) * { * Console.WriteLine($"NODE: {riLines[i]}"); * Console.WriteLine($"XS: {xsLines[i]}"); * } * } * }*/ if (_evalTest) { runner.WriteProgram(new SyntaxErrorProgram(p)); var se = new RuntimeInfo() { CyclomaticComplexity = -1 }; runner.ExecuteProgram(se); ri.MatchSyntaxError = (se.Output == ri.Output); ri.SyntaxErrorRuntime = se.Runtime / ri.Runtime; } Progress?.Invoke(this, EventArgs.Empty); } }