Beispiel #1
0
        public void Crytonote_ConvertBlob()
        {
            var blob   = "0106e5b3afd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b421c0300a401d90101ff9d0106d6d6a88702023c62e43372a58cb588147e20be53a27083f5c522f33c722b082ab7518c48cda280b4c4c32102609ec96e2499ee267d70efefc49f26e330526d3ef455314b7b5ba268a6045f8c80c0fc82aa0202fe5cc0fa56c4277d1a47827edce4725571529d57f33c73ada481ef84c323f30a8090cad2c60e02d88bf5e72a611c8b8464ce29e3b1adbfe1ae163886d9150fe511171cada98fcb80e08d84ddcb0102441915aaf9fbaf70ff454c701a6ae2bd59bb94dc0b888bf7e5d06274ee9238ca80c0caf384a302024078526e2132def44bde2806242652f5944e632f7d94290dd6ee5dda1929f5ee2b016e29f25f07ec2a8df59f0e118a6c9a4b769b745dc0c729071f6e0399d2585745020800000000012e7f76000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".HexToByteArray();
            var result = LibCryptonote.ConvertBlob(blob, 330).ToHexString();

            Assert.Equal("0106e5b3afd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b421c0300a4487286e262e95b8d2163a0c8b73527e8c9425adbdc4e532cf0ef4241f9ffbe9e01", result);
        }
Beispiel #2
0
        public void Cryptonote_ConvertBlob_Should_Match()
        {
            var blob     = "0105bfdfcecd05583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b420000000001d90101ff9d0106d6d6a88702020a79e36c5f5ac69abb68daa616b70e4dc911ed2edf50133fc121447cc403cd6780b4c4c32102b3adc5521c68a35e2dd1934e30b5fada872b384dbbf8c4e8130e43bd0097b8b680c0fc82aa0202b186f6745517ec23a87df7811849d71914a222c937da3e3a39c7bde6f27d2dc98090cad2c60e02df3a6eed49d05b0163986888ebe7da3fae808a72f3beec97346e0a18a960a7b180e08d84ddcb0102f37220a0c601e2dfe78cfab584cabeecf59079b3b2ee045561fb83ebf67941ba80c0caf384a30202b5e50c62333f3237d497eac37b26bd1217b6996eeb7d45e099b71b0f0b5399162b011c2515730ca7e8bb9b79e177557a1fa8b41e9aee544b25d69dc46f12f66b13f102080000000001ff0d7500".HexToByteArray();
            var result   = LibCryptonote.ConvertBlob(blob, blob.Length).ToHexString();
            var expected = "0105bfdfcecd05583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b4200000000f262fa431f692fa1d8a6e89fb809487a2133dd6fd999d95c664b964df354ac4701";

            Assert.Equal(expected, result);
        }
        private string EncodeBlob(uint workerExtraNonce)
        {
            Span <byte> blob = stackalloc byte[blobTemplate.Length];

            blobTemplate.CopyTo(blob);

            // inject extranonce (big-endian at the beginning of the reserved area of the blob)
            var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian());

            extraNonceBytes.CopyTo(blob.Slice(BlockTemplate.ReservedOffset, extraNonceBytes.Length));

            return(LibCryptonote.ConvertBlob(blob, blobTemplate.Length).ToHexString());
        }
Beispiel #4
0
        private string EncodeBlob(uint workerExtraNonce)
        {
            // clone template
            using (var blob = new PooledArraySegment <byte>(_blobTemplate.Length))
            {
                Buffer.BlockCopy(_blobTemplate, 0, blob.Array, 0, _blobTemplate.Length);

                // inject extranonce (big-endian at the beginning of the reserved area of the blob)
                var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian());
                Buffer.BlockCopy(extraNonceBytes, 0, blob.Array, (int)BlockTemplate.ReservedOffset, extraNonceBytes.Length);

                return(LibCryptonote.ConvertBlob(blob.Array, _blobTemplate.Length).ToHexString());
            }
        }
Beispiel #5
0
        private string EncodeBlob(uint workerExtraNonce)
        {
            // clone template
            var blob = new byte[blobTemplate.Length];

            Buffer.BlockCopy(blobTemplate, 0, blob, 0, blobTemplate.Length);

            // inject extranonce (big-endian at the beginning of the reserved area of the blob)
            var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian());

            Buffer.BlockCopy(extraNonceBytes, 0, blob, (int)BlockTemplate.ReservedOffset, extraNonceBytes.Length);

            var result = LibCryptonote.ConvertBlob(blob).ToHexString();

            return(result);
        }
        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());
        }
Beispiel #7
0
 public void Cryptonote_ConvertBlob_Should_Throw_On_Null_Argument()
 {
     Assert.Throws <ArgumentNullException>(() => LibCryptonote.ConvertBlob(null, 0));
 }
Beispiel #8
0
        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.GetContextAs <MoneroWorkerContext>();

            // validate nonce
            if (!MoneroConstants.RegexValidNonce.IsMatch(nonce))
            {
                throw new StratumException(StratumError.MinusOne, "malformed nonce");
            }

            // clone template
            using (var blob = new PooledArraySegment <byte>(blobTemplate.Length))
            {
                Buffer.BlockCopy(blobTemplate, 0, blob.Array, 0, blobTemplate.Length);

                // inject extranonce
                var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian());
                Buffer.BlockCopy(extraNonceBytes, 0, blob.Array, (int)BlockTemplate.ReservedOffset, extraNonceBytes.Length);

                // inject nonce
                var nonceBytes = nonce.HexToByteArray();
                Buffer.BlockCopy(nonceBytes, 0, blob.Array, MoneroConstants.BlobNonceOffset, nonceBytes.Length);

                // convert
                var blobConverted = LibCryptonote.ConvertBlob(blob.Array, blobTemplate.Length);
                if (blobConverted == null)
                {
                    throw new StratumException(StratumError.MinusOne, "malformed blob");
                }

                // hash it
                using (var hashSeg = hashSlow(blobConverted))
                {
                    var hash = hashSeg.ToHexString();
                    if (hash != workerHash)
                    {
                        throw new StratumException(StratumError.MinusOne, "bad hash");
                    }

                    // check difficulty
                    var headerValue       = hashSeg.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})");
                        }
                    }

                    using (var blockHash = ComputeBlockHash(blobConverted))
                    {
                        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);
                    }
                }
            }
        }
Beispiel #9
0
        public MoneroShare ProcessShare(string nonce, uint workerExtraNonce, string workerHash, double stratumDifficulty)
        {
            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>(extraNonce != 0, $"{nameof(extraNonce)} must not be empty");

            // validate nonce
            if (!MoneroConstants.RegexValidNonce.IsMatch(nonce))
            {
                throw new StratumException(StratumError.MinusOne, "malformed nonce");
            }

            // clone template
            var blob = new byte[blobTemplate.Length];

            Buffer.BlockCopy(blobTemplate, 0, blob, 0, blobTemplate.Length);

            // inject extranonce
            var extraNonceBytes = BitConverter.GetBytes(workerExtraNonce.ToBigEndian());

            Buffer.BlockCopy(extraNonceBytes, 0, blob, (int)BlockTemplate.ReservedOffset, extraNonceBytes.Length);

            // inject nonce
            var nonceBytes = nonce.HexToByteArray();

            Buffer.BlockCopy(nonceBytes, 0, blob, MoneroConstants.BlobNonceOffset, nonceBytes.Length);

            // convert
            var blobConverted = LibCryptonote.ConvertBlob(blob);

            if (blobConverted == null)
            {
                throw new StratumException(StratumError.MinusOne, "malformed blob");
            }

            // hash it
            var hashBytes = LibCryptonote.CryptonightHashSlow(blobConverted);
            var hash      = hashBytes.ToHexString();

            if (hash != workerHash)
            {
                throw new StratumException(StratumError.MinusOne, "bad hash");
            }

            // check difficulty
            var headerValue = new System.Numerics.BigInteger(hashBytes);
            var shareDiff   = (double)new BigRational(MoneroConstants.Diff1b, headerValue);
            var ratio       = shareDiff / stratumDifficulty;

            // test if share meets at least workers current difficulty
            if (ratio < 0.99)
            {
                throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
            }

            // valid share, check if the share also meets the much harder block difficulty (block candidate)
            var isBlockCandidate = shareDiff >= BlockTemplate.Difficulty;

            var result = new MoneroShare
            {
                BlockHeight      = BlockTemplate.Height,
                IsBlockCandidate = isBlockCandidate,
                BlobHex          = blob.ToHexString(),
                BlobHash         = ComputeBlockHash(blobConverted).ToHexString()
            };

            return(result);
        }
Beispiel #10
0
        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);
        }