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() { 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); } }
static int Main(string[] args) { System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; int threads = 1; int count = 1000; long seed = DateTime.UtcNow.Ticks; bool objective = false; bool useCustomOptions = false; double runtimeTarget = 0.01; //10 ms double runtimeWeight = 3e+7; double percentileWeight = 500.0; double entropyWeight = 1000.0; double linesOfCodeWeight = 0.05; double halsteadDifficultyWeight = 0.5; double percentile = 0.999; double entropyLimit = 512; double evalTestWeightValidity = 20.0; double evalTestWeightRuntime = 40.0; bool verbose = false; int timeout = -1; bool evalTest = false; bool help = false; Uri runnerUri = new Uri("http://localhost:18111"); bool debug = false; string outfile = null; ProgramOptions customOptions = new ProgramOptions(); customOptions.Initialize(); Action <string> coValidate = (string s) => { if (!useCustomOptions) { throw new InvalidOperationException($"The option {s} must be preceded by --customOptions"); } }; OptionSet p = new OptionSet() .Add("threads=", (int i) => threads = i) .Add("count=", (int i) => count = i) .Add("seed=", (long i) => seed = i) .Add("timeout=", (int i) => timeout = 1000 * i) .Add("objective", s => objective = true) .Add("customOptions", s => useCustomOptions = true) .Add("verbose", s => verbose = true) .Add("runtimeTarget=", (double d) => runtimeTarget = d) .Add("runtimeWeight=", (double d) => runtimeWeight = d) .Add("percentileWeight=", (double d) => percentileWeight = d) .Add("percentile=", (double d) => percentile = d) .Add("entropyWeight=", (double d) => entropyWeight = d) .Add("entropyLimit=", (double d) => entropyLimit = d) .Add("linesOfCodeWeight=", (double d) => linesOfCodeWeight = d) .Add("halsteadDifficultyWeight=", (double d) => halsteadDifficultyWeight = d) .Add("evalTest", s => evalTest = true) .Add("evalTestWeightValidity=", (double d) => evalTestWeightValidity = d) .Add("evalTestWeightRuntime=", (double d) => evalTestWeightRuntime = d) .Add("help|h", s => help = true) .Add("runnerUri=", s => runnerUri = new Uri(s)) .Add("debug", s => debug = true) .Add("outfile=", s => outfile = s); foreach (var prop in typeof(ProgramOptions).GetProperties()) { var pt = prop.PropertyType; if (pt.BaseType != null && pt.BaseType.IsGenericType && pt.BaseType.GetGenericTypeDefinition() == typeof(RandomTable <>)) { var itemType = pt.BaseType.GetGenericArguments()[0]; var instance = prop.GetValue(customOptions); var addMethod = pt.BaseType.GetMethod("Add", new Type[] { itemType, typeof(double) }); foreach (var fld in itemType.GetFields(BindingFlags.Static | BindingFlags.Public)) { string optionName = "XML_" + prop.Name + "_" + fld.Name; //Console.WriteLine($"Adding option --{optionName}"); p.Add(optionName + "=", (double w) => { coValidate(optionName); addMethod.Invoke(instance, new object[] { fld.GetValue(null), w }); }); } } else if (pt == typeof(Interval)) { var instance = prop.GetValue(customOptions); var minProp = pt.GetProperty(nameof(Interval.Min)); string optionNameMin = "XML_" + prop.Name + "_" + nameof(Interval.Min); //Console.WriteLine($"Adding option --{optionNameMin}"); p.Add(optionNameMin + "=", (int i) => { coValidate(optionNameMin); minProp.SetValue(instance, i); }); var rangeProp = pt.GetProperty(nameof(Interval.Span)); string optionNameRange = "XML_" + prop.Name + "_" + nameof(Interval.Span); //Console.WriteLine($"Adding option --{optionNameRange}"); p.Add(optionNameRange + "=", (int i) => { coValidate(optionNameRange); rangeProp.SetValue(instance, i); }); } else { string optionName = "XML_" + prop.Name; //Console.WriteLine($"Adding option --{optionName}"); if (pt == typeof(int)) { p.Add(optionName + "=", (int i) => { coValidate(optionName); prop.SetValue(customOptions, i); }); } if (pt == typeof(double)) { p.Add(optionName + "=", (double d) => { coValidate(optionName); prop.SetValue(customOptions, d); }); } if (pt == typeof(bool)) { p.Add(optionName + "=", (bool b) => { coValidate(optionName); prop.SetValue(customOptions, b); }); } } } var unknown = p.Parse(args); if (help) { p.WriteOptionDescriptions(Console.Out); return(0); } /*if (unknown.Any()) * { * Console.WriteLine($"Unknown option '{unknown.First()}'"); * return 1; * }*/ var options = useCustomOptions ? customOptions : ProgramOptions.FromXml(); if (count == 1 && outfile != null && outfile.Length == 64 && outfile.All(c => "0123456789abcdef".Contains(c))) { var factory = new ProgramFactory(options); var pr = factory.GenProgram(BinaryUtils.StringToByteArray(outfile)); using (var file = System.IO.File.CreateText(outfile + ".js")) pr.WriteTo(file); var runner = Run.ProgramRunnerBase.FromUri(runnerUri); runner.WriteProgram(pr); var ri = runner.ExecuteProgram(); Console.WriteLine(ri.Output); Console.WriteLine($"Success = {ri.Success}"); return(0); } var stats = MakeStats(threads, count, timeout, seed, options, objective, evalTest, runnerUri); if (objective) { if (stats != null && stats.IsComplete) { var runtime1 = runtimeWeight * (stats.Runtime.Average - runtimeTarget) * (stats.Runtime.Average - runtimeTarget); var runtime2 = percentileWeight * stats.Runtime.GetPercentile(percentile); var entropy = entropyWeight / Math.Max(1, stats.OutputEntropy - entropyLimit); var loc = -linesOfCodeWeight * stats.LinesOfCode.Average; var halstead = -halsteadDifficultyWeight * stats.HalsteadDifficulty.Average; var evalWeakness = 0.0; if (evalTest) { evalWeakness = evalTestWeightValidity / Math.Max(0.05, 1.0 - stats.SyntaxErrorValidity) - evalTestWeightRuntime * stats.SyntaxErrorRuntime; } if (verbose) { Console.WriteLine($"Runtime: {runtime1:0.000}"); Console.WriteLine($"Percentile: {runtime2:0.000}"); Console.WriteLine($"Entropy: {entropy:0.000}"); Console.WriteLine($"Lines of code: {loc:0.000}"); Console.WriteLine($"Halstead: {halstead:0.000}"); if (evalTest) { Console.WriteLine($"EvalWeakness: {evalWeakness:0.000}"); } } Console.WriteLine(runtime1 + runtime2 + entropy + loc + halstead + evalWeakness); } else { Console.WriteLine(int.MaxValue); } return(0); } else if (stats != null && stats.IsComplete) { Console.WriteLine(stats.ToString(verbose, debug)); return(0); } else { return(1); } }
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); } }