Beispiel #1
0
        public MoneroJob(GetBlockTemplateResponse blockTemplate, byte[] instanceId, string jobId,
                         PoolConfig poolConfig, ClusterConfig clusterConfig)
        {
            Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate));
            Contract.RequiresNonNull(poolConfig, nameof(poolConfig));
            Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig));
            Contract.RequiresNonNull(instanceId, nameof(instanceId));
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty");

            switch (poolConfig.Coin.Type)
            {
            case CoinType.AEON:
                hashSlow = LibCryptonote.CryptonightHashSlowLite;
                break;

            case CoinType.XMR:
                hashSlow = buf =>
                {
                    // PoW variant
                    var variant = buf[0] >= 7 ? buf[0] - 6 : 0;

                    return(LibCryptonote.CryptonightHashSlow(buf, variant));
                };
                break;

            default:
                hashSlow = buf => LibCryptonote.CryptonightHashSlow(buf, 0);
                break;
            }

            BlockTemplate = blockTemplate;
            PrepareBlobTemplate(instanceId);
        }
Beispiel #2
0
        protected override async Task PostStartInitAsync()
        {
            var infoResponse = await daemon.ExecuteCmdAnyAsync(MC.GetInfo);

            if (infoResponse.Error != null)
            {
                logger.ThrowLogPoolStartupException($"Init RPC failed: {infoResponse.Error.Message} (Code {infoResponse.Error.Code})", LogCat);
            }

            if (clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true)
            {
                var addressResponse = await walletDaemon.ExecuteCmdAnyAsync <GetAddressResponse>(MWC.GetAddress);

                // ensure pool owns wallet
                if (clusterConfig.PaymentProcessing?.Enabled == true && addressResponse.Response?.Address != poolConfig.Address)
                {
                    logger.ThrowLogPoolStartupException($"Wallet-Daemon does not own pool-address '{poolConfig.Address}'", LogCat);
                }
            }

            var info = infoResponse.Response.ToObject <GetInfoResponse>();

            // chain detection
            networkType = info.IsTestnet ? MoneroNetworkType.Test : MoneroNetworkType.Main;

            // address validation
            poolAddressBase58Prefix = LibCryptonote.DecodeAddress(poolConfig.Address);
            if (poolAddressBase58Prefix == 0)
            {
                logger.ThrowLogPoolStartupException("Unable to decode pool-address", LogCat);
            }

            switch (networkType)
            {
            case MoneroNetworkType.Main:
                if (poolAddressBase58Prefix != MoneroConstants.AddressPrefix[poolConfig.Coin.Type])
                {
                    logger.ThrowLogPoolStartupException($"Invalid pool address prefix. Expected {MoneroConstants.AddressPrefix[poolConfig.Coin.Type]}, got {poolAddressBase58Prefix}", LogCat);
                }
                break;

            case MoneroNetworkType.Test:
                if (poolAddressBase58Prefix != MoneroConstants.AddressPrefixTestnet[poolConfig.Coin.Type])
                {
                    logger.ThrowLogPoolStartupException($"Invalid pool address prefix. Expected {MoneroConstants.AddressPrefix[poolConfig.Coin.Type]}, got {poolAddressBase58Prefix}", LogCat);
                }
                break;
            }

//            if (clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true)
//                ConfigureRewards();

            // update stats
            BlockchainStats.RewardType  = "POW";
            BlockchainStats.NetworkType = networkType.ToString();

            await UpdateNetworkStatsAsync();

            SetupJobUpdates();
        }
        public void Crytonote_DecodeIntegratedAddress()
        {
            var address = "4BrL51JCc9NGQ71kWhnYoDRffsDZy7m1HUU7MRU4nUMXAHNFBEJhkTZV9HdaL4gfuNBxLPc3BeMkLGaPbF5vWtANQsGwTGg55Kq4p3ENE7";
            var result  = LibCryptonote.DecodeIntegratedAddress(address);

            Assert.Equal(19ul, result);
        }
        public void Crytonote_ConvertBlob()
        {
            var blob   = "0106e5b3afd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b421c0300a401d90101ff9d0106d6d6a88702023c62e43372a58cb588147e20be53a27083f5c522f33c722b082ab7518c48cda280b4c4c32102609ec96e2499ee267d70efefc49f26e330526d3ef455314b7b5ba268a6045f8c80c0fc82aa0202fe5cc0fa56c4277d1a47827edce4725571529d57f33c73ada481ef84c323f30a8090cad2c60e02d88bf5e72a611c8b8464ce29e3b1adbfe1ae163886d9150fe511171cada98fcb80e08d84ddcb0102441915aaf9fbaf70ff454c701a6ae2bd59bb94dc0b888bf7e5d06274ee9238ca80c0caf384a302024078526e2132def44bde2806242652f5944e632f7d94290dd6ee5dda1929f5ee2b016e29f25f07ec2a8df59f0e118a6c9a4b769b745dc0c729071f6e0399d2585745020800000000012e7f76000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".HexToByteArray();
            var result = LibCryptonote.ConvertBlob(blob, 330).ToHexString();

            Assert.Equal("0106e5b3afd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b421c0300a4487286e262e95b8d2163a0c8b73527e8c9425adbdc4e532cf0ef4241f9ffbe9e01", result);
        }
        public void Crytonote_DecodeAddress()
        {
            var address = "48nhyWcSey31ngSEhV8j8NPm6B8PistCQJBjjDjmTvRSTWYg6iocAw131vE2JPh3ps33vgQDKLrUx3fcErusYWcMJBxpm1d";
            var result  = LibCryptonote.DecodeAddress(address);

            Assert.Equal(18ul, result);
        }
        public void Crytonote_Hash_Fast()
        {
            var blobConverted = "0106a2aaafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42580100a4b1e2f4baf6ab7109071ab59bc52dba740d1de99fa0ae0c4afd6ea9f40c5d87ec01".HexToByteArray();
            var result        = LibCryptonote.CryptonightHashFast(blobConverted).ToHexString();

            Assert.Equal("ddc0e3a33b605ce39fa2d16a98d7634e33399ab1e4b56b3bdd3414b655fe9a98", result);
        }
        public void Crytonote_Hash_Slow_Lite()
        {
            var blobConverted = "0106f1adafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42597710c48c6d885e2622f40f82ecd9b9fd538f28df9b0557e07cd3237a31c76569ada98001".HexToByteArray();
            var result        = LibCryptonote.CryptonightHashSlowLite(blobConverted).ToHexString();

            Assert.Equal("0769caee428a232cffb76fa200f174ff962734f24e7b3bf8d1b0d4e8ba6ceebf", result);
        }
Beispiel #8
0
        public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig)
        {
            Contract.RequiresNonNull(poolConfig, nameof(poolConfig));
            Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig));

            logger             = LogUtil.GetPoolScopedLogger(typeof(JobManagerBase <MoneroJob>), poolConfig);
            this.poolConfig    = poolConfig;
            this.clusterConfig = clusterConfig;

            poolAddressBase58Prefix = LibCryptonote.DecodeAddress(poolConfig.Address);
            if (poolAddressBase58Prefix == 0)
            {
                logger.ThrowLogPoolStartupException("Unable to decode pool-address", LogCat);
            }

            // extract standard daemon endpoints
            daemonEndpoints = poolConfig.Daemons
                              .Where(x => string.IsNullOrEmpty(x.Category))
                              .ToArray();

            // extract wallet daemon endpoints
            walletDaemonEndpoints = poolConfig.Daemons
                                    .Where(x => x.Category?.ToLower() == MoneroConstants.WalletDaemonCategory)
                                    .ToArray();

            if (walletDaemonEndpoints.Length == 0)
            {
                logger.ThrowLogPoolStartupException("Wallet-RPC daemon is not configured (Daemon configuration for monero-pools require an additional entry of category \'wallet' pointing to the wallet daemon)", LogCat);
            }

            ConfigureDaemons();
        }
Beispiel #9
0
        public void Crytonote_Hash_Slow()
        {
            var blobConverted = "0106a2aaafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42580100a4b1e2f4baf6ab7109071ab59bc52dba740d1de99fa0ae0c4afd6ea9f40c5d87ec01".HexToByteArray();
            var result        = LibCryptonote.CryptonightHashSlow(blobConverted, 0).ToHexString();

            Assert.Equal("a845ffbdf83ae9a8ffa504a1011efbd5ed2294bb9da591d3b583740568402c00", result);
        }
Beispiel #10
0
        public bool ValidateAddress(string address)
        {
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(address), $"{nameof(address)} must not be empty");

            var addressPrefix           = LibCryptonote.DecodeAddress(address);
            var addressIntegratedPrefix = LibCryptonote.DecodeIntegratedAddress(address);
            var coin = poolConfig.Template.As <CryptonoteCoinTemplate>();

            switch (networkType)
            {
            case CryptonoteNetworkType.Main:
                if (addressPrefix != coin.AddressPrefix &&
                    addressIntegratedPrefix != coin.AddressPrefixIntegrated)
                {
                    return(false);
                }
                break;

            case CryptonoteNetworkType.Test:
                if (addressPrefix != coin.AddressPrefixTestnet &&
                    addressIntegratedPrefix != coin.AddressPrefixIntegratedTestnet)
                {
                    return(false);
                }
                break;
            }

            return(true);
        }
Beispiel #11
0
        public void Crytonote_Hash_Slow_Variant_1()
        {
            var blobConverted = "0106a2aaafd505583cf50bcc743d04d831d2b119dc94ad88679e359076ee3f18d258ee138b3b42580100a4b1e2f4baf6ab7109071ab59bc52dba740d1de99fa0ae0c4afd6ea9f40c5d87ec01".HexToByteArray();
            var result        = LibCryptonote.CryptonightHashSlow(blobConverted, 1).ToHexString();

            Assert.Equal("c41ec6434df8b2307ff3105ae15206f3fbdf5a99b35879c0a27b8b85a8e2704f", result);
        }
Beispiel #12
0
        public bool ValidateAddress(string address)
        {
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(address), $"{nameof(address)} must not be empty");

            var addressPrefix           = LibCryptonote.DecodeAddress(address);
            var addressIntegratedPrefix = LibCryptonote.DecodeIntegratedAddress(address);

            switch (networkType)
            {
            case MoneroNetworkType.Main:
                if (addressPrefix != MoneroConstants.AddressPrefix[poolConfig.Coin.Type] &&
                    addressIntegratedPrefix != MoneroConstants.AddressPrefixIntegrated[poolConfig.Coin.Type])
                {
                    return(false);
                }
                break;

            case MoneroNetworkType.Test:
                if (addressPrefix != MoneroConstants.AddressPrefixTestnet[poolConfig.Coin.Type] &&
                    addressIntegratedPrefix != MoneroConstants.AddressPrefixIntegratedTestnet[poolConfig.Coin.Type])
                {
                    return(false);
                }
                break;
            }

            return(true);
        }
Beispiel #13
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);
        }
Beispiel #14
0
        private PooledArraySegment <byte> ComputeBlockHash(byte[] blobConverted)
        {
            // blockhash is computed from the converted blob data prefixed with its length
            var bytes = new[] { (byte)blobConverted.Length }
            .Concat(blobConverted)
            .ToArray();

            return(LibCryptonote.CryptonightHashFast(bytes));
        }
Beispiel #15
0
 protected override async Task RunPreInitChecksAsync()
 {
     // decode configured pool address.
     _poolAddressBase58Prefix = LibCryptonote.DecodeAddress(PoolContext.PoolAddress);
     if (_poolAddressBase58Prefix == 0)
     {
         throw new PoolStartupAbortedException("unable to decode configured pool address!");
     }
 }
Beispiel #16
0
        private void ComputeBlockHash(byte[] blobConverted, Span <byte> result)
        {
            // blockhash is computed from the converted blob data prefixed with its length
            var bytes = new[] { (byte)blobConverted.Length }
            .Concat(blobConverted)
            .ToArray();

            LibCryptonote.CryptonightHashFast(bytes, result);
        }
Beispiel #17
0
        private void ComputeBlockHash(ReadOnlySpan <byte> blobConverted, Span <byte> result)
        {
            // blockhash is computed from the converted blob data prefixed with its length
            Span <byte> block = stackalloc byte[blobConverted.Length + 1];

            block[0] = (byte)blobConverted.Length;
            blobConverted.CopyTo(block.Slice(1));

            LibCryptonote.CryptonightHashFast(block, result);
        }
Beispiel #18
0
        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 #19
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 #20
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);
        }
Beispiel #21
0
        private bool ValidateAddress(string address)
        {
            // check address length.
            if (address.Length != MoneroConstants.AddressLength[CoinType.XMR])
            {
                return(false);
            }

            var addressPrefix = LibCryptonote.DecodeAddress(address);

            if (addressPrefix != _poolAddressBase58Prefix)
            {
                return(false);
            }

            return(true);
        }
Beispiel #22
0
        public bool ValidateAddress(string address)
        {
            Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(address), $"{nameof(address)} must not be empty");

            if (address.Length != MoneroConstants.AddressLength)
            {
                return(false);
            }

            var addressPrefix = LibCryptonote.DecodeAddress(address);

            if (addressPrefix != poolAddressBase58Prefix)
            {
                return(false);
            }

            return(true);
        }
Beispiel #23
0
        public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig)
        {
            poolAddressBase58Prefix = LibCryptonote.DecodeAddress(poolConfig.Address);
            if (poolAddressBase58Prefix == 0)
            {
                logger.ThrowLogPoolStartupException("Unable to decode pool-address)", LogCat);
            }

            // extract standard daemon endpoints
            daemonEndpoints = poolConfig.Daemons
                              .Where(x => string.IsNullOrEmpty(x.Category))
                              .ToArray();

            // extract wallet daemon endpoints
            walletDaemonEndpoints = poolConfig.Daemons
                                    .Where(x => x.Category?.ToLower() == MoneroConstants.WalletDaemonCategory)
                                    .ToArray();

            base.Configure(poolConfig, clusterConfig);
        }
Beispiel #24
0
 private static void TouchNativeLibs()
 {
     Console.WriteLine(LibCryptonote.CryptonightHashSlow(Encoding.UTF8.GetBytes("test"), 0).ToHexString());
     Console.WriteLine(LibCryptonote.CryptonightHashFast(Encoding.UTF8.GetBytes("test")).ToHexString());
     Console.WriteLine(new Blake().Digest(Encoding.UTF8.GetBytes("test"), 0).ToHexString());
 }
Beispiel #25
0
        protected override async Task PostStartInitAsync(CancellationToken ct)
        {
            var coin         = poolConfig.Template.As <CryptonoteCoinTemplate>();
            var infoResponse = await daemon.ExecuteCmdAnyAsync(logger, CryptonoteCommands.GetInfo);

            if (infoResponse.Error != null)
            {
                logger.ThrowLogPoolStartupException($"Init RPC failed: {infoResponse.Error.Message} (Code {infoResponse.Error.Code})");
            }

            if (clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true)
            {
                var addressResponse = await walletDaemon.ExecuteCmdAnyAsync <GetAddressResponse>(logger, ct, CryptonoteWalletCommands.GetAddress);

                // ensure pool owns wallet
                if (clusterConfig.PaymentProcessing?.Enabled == true && addressResponse.Response?.Address != poolConfig.Address)
                {
                    logger.ThrowLogPoolStartupException($"Wallet-Daemon does not own pool-address '{poolConfig.Address}'");
                }
            }

            var info = infoResponse.Response.ToObject <GetInfoResponse>();

            // chain detection
            networkType = info.IsTestnet ? CryptonoteNetworkType.Test : CryptonoteNetworkType.Main;

            // address validation
            poolAddressBase58Prefix = LibCryptonote.DecodeAddress(poolConfig.Address);
            if (poolAddressBase58Prefix == 0)
            {
                logger.ThrowLogPoolStartupException("Unable to decode pool-address");
            }

            switch (networkType)
            {
            case CryptonoteNetworkType.Main:
                if (poolAddressBase58Prefix != coin.AddressPrefix)
                {
                    logger.ThrowLogPoolStartupException($"Invalid pool address prefix. Expected {coin.AddressPrefix}, got {poolAddressBase58Prefix}");
                }
                break;

            case CryptonoteNetworkType.Test:
                if (poolAddressBase58Prefix != coin.AddressPrefixTestnet)
                {
                    logger.ThrowLogPoolStartupException($"Invalid pool address prefix. Expected {coin.AddressPrefix}, got {poolAddressBase58Prefix}");
                }
                break;
            }

            if (clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true)
            {
                ConfigureRewards();
            }

            // update stats
            BlockchainStats.RewardType  = "POW";
            BlockchainStats.NetworkType = networkType.ToString();

            await UpdateNetworkStatsAsync();

            // Periodically update network stats
            Observable.Interval(TimeSpan.FromMinutes(1))
            .Select(via => Observable.FromAsync(async() =>
            {
                try
                {
                    await UpdateNetworkStatsAsync();
                }

                catch (Exception ex)
                {
                    logger.Error(ex);
                }
            }))
            .Concat()
            .Subscribe();

            SetupJobUpdates();
        }
Beispiel #26
0
        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 #27
0
 public void Cryptonote_DecodeAddress_Should_Throw_On_Null_Or_Empty_Argument()
 {
     Assert.Throws <ArgumentException>(() => LibCryptonote.DecodeAddress(null));
     Assert.Throws <ArgumentException>(() => LibCryptonote.DecodeAddress(""));
 }
Beispiel #28
0
 public void Cryptonote_ConvertBlob_Should_Throw_On_Null_Argument()
 {
     Assert.Throws <ArgumentNullException>(() => LibCryptonote.ConvertBlob(null, 0));
 }
Beispiel #29
0
 public void Cryptonote_FastHash_Should_Throw_On_Null_Argument()
 {
     Assert.Throws <ArgumentNullException>(() => LibCryptonote.CryptonightHashFast(null));
 }
        public async Task PayoutAsync(Balance[] balances)
        {
            Contract.RequiresNonNull(balances, nameof(balances));

            // ensure we have peers
            var infoResponse = await daemon.ExecuteCmdAnyAsync <GetInfoResponse>(MC.GetInfo);

            if (infoResponse.Error != null || infoResponse.Response == null ||
                infoResponse.Response.IncomingConnectionsCount + infoResponse.Response.OutgoingConnectionsCount < 3)
            {
#if !DEBUG
                logger.Warn(() => $"[{LogCategory}] Payout aborted. Not enough peers (4 required)");
                return;
#endif
            }

            // validate addresses
            balances = balances
                       .Where(x =>
            {
                ExtractAddressAndPaymentId(x.Address, out var address, out var paymentId);

                var addressPrefix           = LibCryptonote.DecodeAddress(address);
                var addressIntegratedPrefix = LibCryptonote.DecodeIntegratedAddress(address);

                switch (networkType)
                {
                case MoneroNetworkType.Main:
                    if (addressPrefix != MoneroConstants.AddressPrefix[poolConfig.Coin.Type] &&
                        addressIntegratedPrefix != MoneroConstants.AddressPrefixIntegrated[poolConfig.Coin.Type])
                    {
                        logger.Warn(() => $"[{LogCategory}] Excluding payment to invalid address {x.Address}");
                        return(false);
                    }
                    break;

                case MoneroNetworkType.Test:
                    if (addressPrefix != MoneroConstants.AddressPrefixTestnet[poolConfig.Coin.Type] &&
                        addressIntegratedPrefix != MoneroConstants.AddressPrefixIntegratedTestnet[poolConfig.Coin.Type])
                    {
                        logger.Warn(() => $"[{LogCategory}] Excluding payment to invalid address {x.Address}");
                        return(false);
                    }
                    break;
                }

                return(true);
            })
                       .ToArray();

            // simple balances first
            var simpleBalances = balances
                                 .Where(x =>
            {
                ExtractAddressAndPaymentId(x.Address, out var address, out var paymentId);

                var hasPaymentId            = paymentId != null;
                var isIntegratedAddress     = false;
                var addressIntegratedPrefix = LibCryptonote.DecodeIntegratedAddress(address);

                switch (networkType)
                {
                case MoneroNetworkType.Main:
                    if (addressIntegratedPrefix == MoneroConstants.AddressPrefixIntegrated[poolConfig.Coin.Type])
                    {
                        isIntegratedAddress = true;
                    }
                    break;

                case MoneroNetworkType.Test:
                    if (addressIntegratedPrefix == MoneroConstants.AddressPrefixIntegratedTestnet[poolConfig.Coin.Type])
                    {
                        isIntegratedAddress = true;
                    }
                    break;
                }

                return(!hasPaymentId && !isIntegratedAddress);
            })
                                 .ToArray();

            if (simpleBalances.Length > 0)
            {
                await PayoutBatch(simpleBalances);
            }

            // balances with paymentIds
            var minimumPaymentToPaymentId = extraConfig?.MinimumPaymentToPaymentId ?? poolConfig.PaymentProcessing.MinimumPayment;

            var paymentIdBalances = balances.Except(simpleBalances)
                                    .Where(x => x.Amount >= minimumPaymentToPaymentId)
                                    .ToArray();

            foreach (var balance in paymentIdBalances)
            {
                await PayoutToPaymentId(balance);
            }
        }