/// <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);
Beispiel #4
0
 private static extern int cryptonight_heavy(IntPtr ctx, byte *input, byte *output, uint inputLength, CryptonightVariant variant);