/// <summary> /// Cryptonight Hash (Monero, Monero v7, v8 etc.) /// </summary> /// <param name="variant">Algorithm variant</param> public static void Cryptonight(ReadOnlySpan <byte> data, Span <byte> result, CryptonightVariant variant, ulong height) { Contract.Requires <ArgumentException>(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); var ctx = ctxs.Lease(); try { fixed(byte *input = data) { fixed(byte *output = result) { cryptonight(ctx.Value, input, output, (uint)data.Length, variant, height); } } } finally { ctxs.Return(ctx); } }
public (Share Share, string BlobHex) ProcessShare(string nonce, uint workerExtraNonce, string workerHash, StratumClient worker) { Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(nonce), $"{nameof(nonce)} must not be empty"); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(workerHash), $"{nameof(workerHash)} must not be empty"); Contract.Requires <ArgumentException>(workerExtraNonce != 0, $"{nameof(workerExtraNonce)} must not be empty"); var context = worker.ContextAs <CryptonoteWorkerContext>(); // validate nonce if (!CryptonoteConstants.RegexValidNonce.IsMatch(nonce)) { throw new StratumException(StratumError.MinusOne, "malformed nonce"); } // clone template Span <byte> blob = stackalloc byte[blobTemplate.Length]; blobTemplate.CopyTo(blob); // inject extranonce var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian()); extraNonceBytes.CopyTo(blob.Slice(BlockTemplate.ReservedOffset, extraNonceBytes.Length)); // inject nonce var nonceBytes = nonce.HexToByteArray(); nonceBytes.CopyTo(blob.Slice(CryptonoteConstants.BlobNonceOffset, nonceBytes.Length)); // convert var blobConverted = LibCryptonote.ConvertBlob(blob, blobTemplate.Length); if (blobConverted == null) { throw new StratumException(StratumError.MinusOne, "malformed blob"); } Console.WriteLine($"Coin: {coin.Name} Symbol: {coin.Symbol} Family: {coin.Family} Hash: {coin.Hash} Variant: {coin.HashVariant}"); Console.WriteLine("------------------------------------------------------------------------------------------------------------"); Console.WriteLine($"blob Converted: {blobConverted[0]}"); // -------- NEED TO CHANGE ---------->> // determine variant CryptonightVariant variant = CryptonightVariant.VARIANT_0; if (coin.HashVariant != 0) { variant = (CryptonightVariant)coin.HashVariant; } else { switch (coin.Hash) { case CryptonightHashType.Normal: variant = (blobConverted[0] >= 10) ? CryptonightVariant.VARIANT_4 : ((blobConverted[0] >= 8) ? CryptonightVariant.VARIANT_2 : ((blobConverted[0] == 7) ? CryptonightVariant.VARIANT_1 : CryptonightVariant.VARIANT_0)); break; case CryptonightHashType.Lite: variant = CryptonightVariant.VARIANT_1; break; case CryptonightHashType.Heavy: variant = CryptonightVariant.VARIANT_0; break; case CryptonightHashType.RandomX: variant = CryptonightVariant.VARIANT_0; break; default: break; } } // <<------------- Console.WriteLine($""); // hash it Span <byte> headerHash = stackalloc byte[32]; hashFunc(blobConverted, BlockTemplate.SeedHash, headerHash, variant, BlockTemplate.Height); var headerHashString = headerHash.ToHexString(); if (headerHashString != workerHash) { throw new StratumException(StratumError.MinusOne, "bad hash"); } // check difficulty var headerValue = headerHash.ToBigInteger(); var shareDiff = (double)new BigRational(CryptonoteConstants.Diff1b, headerValue); var stratumDifficulty = context.Difficulty; var ratio = shareDiff / stratumDifficulty; var isBlockCandidate = shareDiff >= BlockTemplate.Difficulty; // test if share meets at least workers current difficulty if (!isBlockCandidate && ratio < 0.99) { // check if share matched the previous difficulty from before a vardiff retarget if (context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue) { ratio = shareDiff / context.PreviousDifficulty.Value; if (ratio < 0.99) { throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); } // use previous difficulty stratumDifficulty = context.PreviousDifficulty.Value; } else { throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); } } var result = new Share { BlockHeight = BlockTemplate.Height, Difficulty = stratumDifficulty, }; if (isBlockCandidate) { // Compute block hash Span <byte> blockHash = stackalloc byte[32]; ComputeBlockHash(blobConverted, blockHash); // Fill in block-relevant fields result.IsBlockCandidate = true; result.BlockHash = blockHash.ToHexString(); } return(result, blob.ToHexString()); }
private static extern int cryptonight_pico(IntPtr ctx, byte *input, byte *output, uint inputLength, CryptonightVariant variant, ulong height);
private static extern int cryptonight_heavy(IntPtr ctx, byte *input, byte *output, uint inputLength, CryptonightVariant variant);