public void Crytonight_Variant_1() { var blobConverted = "0106a2aaafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42580100a4b1e2f4baf6ab7109071ab59bc52dba740d1de99fa0ae0c4afd6ea9f40c5d87ec01".HexToByteArray(); var buf = new byte[32]; LibCryptonight.Cryptonight(blobConverted, buf, 1); var result = buf.ToHexString(); Assert.Equal("c41ec6434df8b2307ff3105ae15206f3fbdf5a99b35879c0a27b8b85a8e2704f", result); Array.Clear(buf, 0, buf.Length); LibCryptonight.Cryptonight(blobConverted, buf, 1); result = buf.ToHexString(); Assert.Equal("c41ec6434df8b2307ff3105ae15206f3fbdf5a99b35879c0a27b8b85a8e2704f", result); }
public void Crytonight_Variant_4() { var blobConverted = "0106a2aaafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42580100a4b1e2f4baf6ab7109071ab59bc52dba740d1de99fa0ae0c4afd6ea9f40c5d87ec01".HexToByteArray(); var buf = new byte[32]; LibCryptonight.Cryptonight(blobConverted, buf, CryptonightVariant.VARIANT_4, 0); var result = buf.ToHexString(); Assert.Equal("3e69817268c70010f793d53ba1a9f12af21753c723c7d7990a8eefccc6d163ba", result); Array.Clear(buf, 0, buf.Length); LibCryptonight.Cryptonight(blobConverted, buf, CryptonightVariant.VARIANT_4, 0); result = buf.ToHexString(); Assert.Equal("3e69817268c70010f793d53ba1a9f12af21753c723c7d7990a8eefccc6d163ba", result); }
public void Crytonight() { var blobConverted = "0106a2aaafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42580100a4b1e2f4baf6ab7109071ab59bc52dba740d1de99fa0ae0c4afd6ea9f40c5d87ec01".HexToByteArray(); var buf = new byte[32]; LibCryptonight.Cryptonight(blobConverted, buf, 0); var result = buf.ToHexString(); Assert.Equal("a845ffbdf83ae9a8ffa504a1011efbd5ed2294bb9da591d3b583740568402c00", result); Array.Clear(buf, 0, buf.Length); LibCryptonight.Cryptonight(blobConverted, buf, 0); result = buf.ToHexString(); Assert.Equal("a845ffbdf83ae9a8ffa504a1011efbd5ed2294bb9da591d3b583740568402c00", result); }
public (Share Share, string BlobHex, string BlobHash) 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 <MoneroWorkerContext>(); // validate nonce if (!MoneroConstants.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(MoneroConstants.BlobNonceOffset, nonceBytes.Length)); // convert var blobConverted = LibCryptonote.ConvertBlob(blob, blobTemplate.Length); if (blobConverted == null) { throw new StratumException(StratumError.MinusOne, "malformed blob"); } // hash it Span <byte> headerHash = stackalloc byte[32]; switch (coin) { case CoinType.AEON: LibCryptonight.CryptonightLight(blobConverted, headerHash, 0); break; case CoinType.XMR: var variant = blobConverted[0] >= 7 ? blobConverted[0] - 6 : 0; LibCryptonight.Cryptonight(blobConverted, headerHash, variant); break; default: LibCryptonight.Cryptonight(blobConverted, headerHash, 0); break; } 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(MoneroConstants.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})"); } } // Compute block hash Span <byte> blockHash = stackalloc byte[32]; ComputeBlockHash(blobConverted, blockHash); var result = new Share { BlockHeight = BlockTemplate.Height, IsBlockCandidate = isBlockCandidate, BlockHash = blockHash.ToHexString(), Difficulty = stratumDifficulty, }; var blobHex = blob.ToHexString(); var blobHash = blockHash.ToHexString(); return(result, blobHex, blobHash); }