Example #1
0
        /// <summary>
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public async Task <VerifyResult> VerifyOutputCommitments(Transaction transaction)
        {
            Guard.Argument(transaction, nameof(transaction)).NotNull();
            var offSets = transaction.Vin.Select(v => v.Key).SelectMany(k => k.Offsets.Split(33)).ToArray();
            var list    = offSets.Where((value, index) => index % 2 == 0).ToArray();

            foreach (var commit in list)
            {
                var blocks = await _unitOfWork.HashChainRepository.WhereAsync(x =>
                                                                              new ValueTask <bool>(x.Txs.Any(v => v.Vout.Any(c => c.C.Xor(commit)))));

                if (!blocks.Any())
                {
                    return(VerifyResult.UnableToVerify);
                }
                var outputs = blocks.SelectMany(block => block.Txs).SelectMany(x => x.Vout);
                if (outputs.Where(output => output.T == CoinType.Coinbase && output.T == CoinType.Fee)
                    .Select(output => VerifyLockTime(new LockTime(Utils.UnixTimeToDateTime(output.L)), output.S))
                    .Any(verified => verified != VerifyResult.UnableToVerify))
                {
                    return(VerifyResult.UnableToVerify);
                }
            }

            return(VerifyResult.Succeed);
        }
Example #2
0
        /// <summary>
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public VerifyResult VerifyBulletProof(Transaction transaction)
        {
            Guard.Argument(transaction, nameof(transaction)).NotNull();
            Guard.Argument(transaction.Vout, nameof(transaction)).NotNull();
            try
            {
                if (transaction.Validate().Any())
                {
                    return(VerifyResult.UnableToVerify);
                }
                using var secp256K1   = new Secp256k1();
                using var bulletProof = new BulletProof();
                if (transaction.Bp.Select((t, i) => bulletProof.Verify(transaction.Vout[i + 2].C, t.Proof, null))
                    .Any(verified => !verified))
                {
                    return(VerifyResult.UnableToVerify);
                }
            }
            catch (Exception ex)
            {
                _logger.Here().Error(ex, "Unable to verify the bullet proof");
                return(VerifyResult.UnableToVerify);
            }

            return(VerifyResult.Succeed);
        }
Example #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public async Task <VerifyResult> VerifyTransaction(Transaction transaction)
        {
            Guard.Argument(transaction, nameof(transaction)).NotNull();
            if (transaction.Validate().Any())
            {
                return(VerifyResult.UnableToVerify);
            }
            var verifySum = VerifyCommitSum(transaction);

            if (verifySum == VerifyResult.UnableToVerify)
            {
                return(verifySum);
            }
            var verifyBulletProof = VerifyBulletProof(transaction);

            if (verifyBulletProof == VerifyResult.UnableToVerify)
            {
                return(verifyBulletProof);
            }
            var transactionTypeArray = transaction.Vout.Select(x => x.T.ToString()).ToArray();

            if (transactionTypeArray.Contains(CoinType.Fee.ToString()) &&
                transactionTypeArray.Contains(CoinType.Coin.ToString()))
            {
                var verifyVOutCommits = await VerifyOutputCommitments(transaction);

                if (verifyVOutCommits == VerifyResult.UnableToVerify)
                {
                    return(verifyVOutCommits);
                }
            }

            var verifyKImage = await VerifyKeyImage(transaction);

            if (verifyKImage == VerifyResult.UnableToVerify)
            {
                return(verifyKImage);
            }
            using var mlsag = new MLSAG();
            for (var i = 0; i < transaction.Vin.Length; i++)
            {
                var m = Makemlsag(transaction.Rct[i].M, transaction.Vout, transaction.Vin[i].Key.Offsets,
                                  transaction.Mix, 2);
                var verifymlsag = mlsag.Verify(transaction.Rct[i].I, transaction.Mix, 2, m,
                                               transaction.Vin[i].Key.Image, transaction.Rct[i].P, transaction.Rct[i].S);
                if (verifymlsag)
                {
                    continue;
                }
                _logger.Here()
                .Fatal("Unable to verify the Multilayered Linkable Spontaneous Anonymous Group transaction");
                return(VerifyResult.UnableToVerify);
            }

            return(VerifyResult.Succeed);
        }
Example #4
0
        /// <summary>
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public async Task <VerifyResult> VerifyKeyImage(Transaction transaction)
        {
            Guard.Argument(transaction, nameof(transaction)).NotNull();
            if (transaction.Validate().Any())
            {
                return(VerifyResult.UnableToVerify);
            }
            foreach (var vin in transaction.Vin)
            {
                var blocks = await _unitOfWork.HashChainRepository.WhereAsync(x =>
                                                                              new ValueTask <bool>(x.Txs.Any(t => t.Vin.First().Key.Image.Xor(vin.Key.Image))));

                if (blocks.Count > 1)
                {
                    return(VerifyResult.UnableToVerify);
                }
            }

            return(VerifyResult.Succeed);
        }
Example #5
0
        /// <summary>
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public VerifyResult VerifyCommitSum(Transaction transaction)
        {
            Guard.Argument(transaction, nameof(transaction)).NotNull();
            try
            {
                if (transaction.Validate().Any())
                {
                    return(VerifyResult.UnableToVerify);
                }
                using var pedersen = new Pedersen();
                for (var i = 0; i < transaction.Vout.Length / 3; i++)
                {
                    var fee              = transaction.Vout[i].C;
                    var payment          = transaction.Vout[i + 1].C;
                    var change           = transaction.Vout[i + 2].C;
                    var commitSumBalance = pedersen.CommitSum(new List <byte[]> {
                        fee, payment, change
                    },
                                                              new List <byte[]>());
                    if (!pedersen.VerifyCommitSum(new List <byte[]> {
                        commitSumBalance
                    },
                                                  new List <byte[]> {
                        fee, payment, change
                    }))
                    {
                        return(VerifyResult.UnableToVerify);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Here().Error(ex, "Unable to verify the committed sum");
                return(VerifyResult.UnableToVerify);
            }

            return(VerifyResult.Succeed);
        }
Example #6
0
        /// <summary>
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public VerifyResult VerifyTransactionFee(Transaction transaction)
        {
            Guard.Argument(transaction, nameof(transaction)).NotNull();
            var output = transaction.Vout.First();

            if (output.T != CoinType.Fee)
            {
                return(VerifyResult.UnableToVerify);
            }
            var feeRate = Fee(FeeNByte);

            if (output.A != feeRate)
            {
                return(VerifyResult.UnableToVerify);
            }
            using var pedersen = new Pedersen();
            var commitSum = pedersen.CommitSum(new List <byte[]> {
                output.C
            }, new List <byte[]> {
                output.C
            });

            return(commitSum == null ? VerifyResult.Succeed : VerifyResult.UnableToVerify);
        }