Exemple #1
0
        /// <summary>
        /// Builds the receiver.
        /// </summary>
        /// <returns>The receiver.</returns>
        public TaskResult <bool> Receiver(SecureString secret, ulong input, out CoinDto coin, out byte[] blind, out byte[] salt)
        {
            using (var pedersen = new Pedersen())
            {
                salt  = Cryptography.RandomBytes(16);
                coin  = MakeSingleCoin(secret, salt.ToHex().ToSecureString(), NewStamp(), -1);
                blind = DeriveKey(input, coin.Stamp, coin.Version, secret, salt.ToHex().ToSecureString());

                try
                {
                    var blindSum = pedersen.BlindSum(new List <byte[]> {
                        blind
                    }, new List <byte[]> {
                    });
                    var commitPos = pedersen.Commit(input, blind);
                    var commitSum = pedersen.CommitSum(new List <byte[]> {
                        commitPos
                    }, new List <byte[]> {
                    });

                    AttachEnvelope(blindSum, commitSum, input, secret, salt.ToHex().ToSecureString(), ref coin);
                }
                catch (Exception ex)
                {
                    logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}");
                    return(TaskResult <bool> .CreateFailure(ex));
                }
            }

            return(TaskResult <bool> .CreateSuccess(true));
        }
Exemple #2
0
 /// <summary>
 /// Clears the change, imputs, minted coin, outputs, secret, receiver output, stamp and version cache.
 /// </summary>
 public void ClearCache()
 {
     mintedCoin      = null;
     stamp           = null;
     version         = 0;
     transactionCoin = null;
 }
Exemple #3
0
        /// <summary>
        /// Change partial ownership.
        /// </summary>
        /// <returns>The partial one.</returns>
        /// <param name="password">Password.</param>
        /// <param name="coin">Coin.</param>
        /// <param name="redemptionKey">Redemption key.</param>
        public CoinDto SwapPartialOne(SecureString password, CoinDto coin, RedemptionKeyDto redemptionKey)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            if (coin == null)
            {
                throw new ArgumentNullException(nameof(coin));
            }

            if (redemptionKey == null)
            {
                throw new ArgumentNullException(nameof(redemptionKey));
            }

            var v1 = coin.Version + 1;
            var v2 = coin.Version + 2;
            var v3 = coin.Version + 3;

            coin.Keeper    = DeriveKey(v2, coin.Stamp, DeriveKey(v3, coin.Stamp, DeriveKey(v3, coin.Stamp, password).ToSecureString()).ToSecureString());
            coin.Version   = v1;
            coin.Principle = redemptionKey.Key1;
            coin.Stamp     = coin.Stamp;
            coin.Envelope  = coin.Envelope;
            coin.Hint      = redemptionKey.Key2;

            return(coin);
        }
Exemple #4
0
        /// <summary>
        /// Builds the receiver.
        /// </summary>
        /// <returns>The receiver.</returns>
        public (ReceiverOutput, CoinDto) BuildReceiver()
        {
            ReceiverOutput receiver = null;
            CoinDto        coin     = null;

            using (var secp256k1 = new Secp256k1())
                using (var pedersen = new Pedersen())
                {
                    var blind    = DeriveKey(Output());
                    var blindSum = pedersen.BlindSum(new List <byte[]> {
                        blind, blind
                    }, new List <byte[]> {
                    });
                    var commitPos = Commit((ulong)Output(), blind);
                    var commitNeg = Commit(0, blind);

                    Stamp(GetNewStamp());
                    Version(-1);

                    coin     = BuildCoin(blindSum, commitPos, commitNeg, true);
                    receiver = new ReceiverOutput(Output(), commitPos, blindSum);
                }

            return(receiver, coin);
        }
Exemple #5
0
        /// <summary>
        /// Builds the receiver.
        /// </summary>
        /// <returns>The receiver.</returns>
        public CoinService BuildReceiver()
        {
            using (var secp256k1 = new Secp256k1())
                using (var pedersen = new Pedersen())
                {
                    var naTOutput = NaT(Output());
                    var blind     = DeriveKey(naTOutput);

                    byte[] blindSum = new byte[32];

                    try
                    {
                        blindSum = pedersen.BlindSum(new List <byte[]> {
                            blind, blind
                        }, new List <byte[]> {
                        });
                    }
                    catch (Exception ex)
                    {
                        logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}");
                        throw ex;
                    }

                    var commitPos = Commit(naTOutput, blind);
                    var commitNeg = Commit(0, blind);

                    Stamp(GetNewStamp());
                    Version(-1);

                    mintedCoin     = BuildCoin(blindSum, commitPos, commitNeg, true);
                    receiverOutput = new ReceiverOutput(Output(), commitPos, blindSum);
                }

            return(this);
        }
Exemple #6
0
        /// <summary>
        /// Derives the coin.
        /// </summary>
        /// <returns>The coin.</returns>
        /// <param name="coin">Coin.</param>
        public CoinDto DeriveCoin(CoinDto coin)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            if (coin == null)
            {
                throw new ArgumentNullException(nameof(coin));
            }

            var v0 = +coin.Version;
            var v1 = +coin.Version + 1;
            var v2 = +coin.Version + 2;

            var c = new CoinDto()
            {
                Keeper    = DeriveKey(v1, coin.Stamp, DeriveKey(v2, coin.Stamp, DeriveKey(v2, coin.Stamp, Password()).ToSecureString()).ToSecureString()),
                Version   = v0,
                Principle = DeriveKey(v0, coin.Stamp, Password()),
                Stamp     = coin.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v1, coin.Stamp, DeriveKey(v1, coin.Stamp, Password()).ToSecureString())
            };

            return(c);
        }
Exemple #7
0
 /// <summary>
 /// Clears the change, imputs, minted coin, outputs, password, receiver output, stamp and version cache.
 /// </summary>
 public void ClearCache()
 {
     change = 0;
     Input(0);
     mintedCoin = null;
     Output(0);
     Password(null);
     receiverOutput = null;
     Stamp(string.Empty);
     Version(0);
 }
Exemple #8
0
        /// <summary>
        /// Makes the single coin.
        /// </summary>
        /// <returns>The single coin.</returns>
        public void MakeSingleCoin(SecureString secret)
        {
            Guard.Argument(secret, nameof(secret)).NotNull();

            mintedCoin = DeriveCoin(new CoinDto
            {
                Version  = version + 1,
                Stamp    = stamp,
                Envelope = new EnvelopeDto()
            }, secret);
        }
Exemple #9
0
        /// <summary>
        /// Change ownership.
        /// </summary>
        /// <returns>The swap.</returns>
        /// <param name="password">Password.</param>
        /// <param name="coin">Coin.</param>
        /// <param name="redemptionKey">Redemption key.</param>
        public (CoinDto, CoinDto) CoinSwap(SecureString password, CoinDto coin, RedemptionKeyDto redemptionKey)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            if (coin == null)
            {
                throw new ArgumentNullException(nameof(coin));
            }

            if (redemptionKey == null)
            {
                throw new ArgumentNullException(nameof(redemptionKey));
            }

            if (!redemptionKey.Stamp.Equals(coin.Stamp))
            {
                throw new Exception("Redemption stamp is not equal to the coins stamp!");
            }

            var v1 = coin.Version + 1;
            var v2 = coin.Version + 2;
            var v3 = coin.Version + 3;
            var v4 = coin.Version + 4;

            var c1 = new CoinDto()
            {
                Keeper    = DeriveKey(v2, redemptionKey.Stamp, DeriveKey(v3, redemptionKey.Stamp, DeriveKey(v3, redemptionKey.Stamp, password).ToSecureString()).ToSecureString()),
                Version   = v1,
                Principle = redemptionKey.Key1,
                Stamp     = redemptionKey.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v2, redemptionKey.Stamp, redemptionKey.Key2.ToSecureString())
            };

            c1.Hash = Hash(c1).ToHex();

            var c2 = new CoinDto()
            {
                Keeper    = DeriveKey(v3, redemptionKey.Stamp, DeriveKey(v4, redemptionKey.Stamp, DeriveKey(v4, redemptionKey.Stamp, password).ToSecureString()).ToSecureString()),
                Version   = v2,
                Principle = redemptionKey.Key2,
                Stamp     = redemptionKey.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v3, redemptionKey.Stamp, DeriveKey(v3, redemptionKey.Stamp, password).ToSecureString())
            };

            c2.Hash = Hash(c2).ToHex();

            return(c1, c2);
        }
Exemple #10
0
        /// <summary>
        /// Builds the sender.
        /// </summary>
        /// <returns>The sender.</returns>
        public async Task <TaskResult <CoinDto> > Sender(Session session, PurchaseDto purchase)
        {
            CoinDto coin = null;

            using (var pedersen = new Pedersen())
            {
                try
                {
                    //TODO: Refactor signature to handle lambda expressions..
                    var txnsAll = await unitOfWork.GetTransactionRepository().All(session);

                    if (txnsAll.Result?.Any() != true)
                    {
                        throw new Exception("No transactions found!");
                    }

                    var txns = txnsAll.Result.Where(tx => purchase.Chain.Any(id => id == Guid.Parse(tx.TransactionId)));

                    var received = txns.FirstOrDefault(tx => tx.TransactionType == TransactionType.Receive);

                    coin = MakeSingleCoin(session.MasterKey, received.Salt.ToSecureString(), purchase.Stamp, purchase.Version);

                    var blindNeg  = DeriveKey(purchase.Input, received.Stamp, coin.Version, session.MasterKey, received.Salt.ToSecureString());
                    var commitNeg = pedersen.Commit(purchase.Input, blindNeg);

                    var commitNegs = txns.Where(tx => tx.TransactionType == TransactionType.Send)
                                     .Select(c => pedersen.Commit(c.Amount, DeriveKey(c.Amount, c.Stamp, c.Version, session.MasterKey, received.Salt.ToSecureString()))).ToList();

                    commitNegs.Add(commitNeg);

                    var blindNegSums = txns.Where(tx => tx.TransactionType == TransactionType.Send)
                                       .Select(c => DeriveKey(c.Amount, c.Stamp, c.Version, session.MasterKey, received.Salt.ToSecureString())).ToList();

                    blindNegSums.Add(blindNeg);

                    var blindSum = pedersen.BlindSum(new List <byte[]> {
                        received.Blind.FromHex()
                    }, blindNegSums);
                    var commitSum = pedersen.CommitSum(new List <byte[]> {
                        received.Commitment.FromHex()
                    }, commitNegs);

                    AttachEnvelope(blindSum, commitSum, purchase.Output, session.MasterKey, received.Salt.ToSecureString(), ref coin);
                }
                catch (Exception ex)
                {
                    logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}");
                    return(TaskResult <CoinDto> .CreateFailure(ex));
                }
            }

            return(TaskResult <CoinDto> .CreateSuccess(coin));
        }
Exemple #11
0
        /// <summary>
        /// Verifies the coin on ownership.
        /// </summary>
        /// <returns>The coin.</returns>
        /// <param name="terminal">Terminal.</param>
        /// <param name="current">Current.</param>
        public int VerifyCoin(CoinDto terminal, CoinDto current)
        {
            Guard.Argument(terminal, nameof(terminal)).NotNull();
            Guard.Argument(current, nameof(current)).NotNull();

            return(terminal.Keeper.Equals(current.Keeper) && terminal.Hint.Equals(current.Hint)
               ? 1
               : terminal.Hint.Equals(current.Hint)
               ? 2
               : terminal.Keeper.Equals(current.Keeper)
               ? 3
               : 4);
        }
Exemple #12
0
        /// <summary>
        /// Hash the specified coin.
        /// </summary>
        /// <returns>The hash.</returns>
        /// <param name="coin">Coin.</param>
        public byte[] Hash(CoinDto coin)
        {
            Guard.Argument(coin, nameof(coin)).NotNull();

            return(Cryptography.GenericHashNoKey(
                       string.Format("{0} {1} {2} {3} {4} {5} {6}",
                                     coin.Envelope.Commitment,
                                     coin.Envelope.Proof,
                                     coin.Envelope.PublicKey,
                                     coin.Hint,
                                     coin.Keeper,
                                     coin.Principle,
                                     coin.Stamp)));
        }
Exemple #13
0
        /// <summary>
        /// Change ownership.
        /// </summary>
        /// <returns>The swap.</returns>
        /// <param name="secret">secret.</param>
        /// <param name="coin">Coin.</param>
        /// <param name="redemptionKey">Redemption key.</param>
        public (CoinDto, CoinDto) CoinSwap(SecureString secret, SecureString salt, CoinDto coin, RedemptionKeyDto redemptionKey)
        {
            Guard.Argument(secret, nameof(secret)).NotNull();
            Guard.Argument(coin, nameof(coin)).NotNull();
            Guard.Argument(redemptionKey, nameof(redemptionKey)).NotNull();

            try
            { coin = coin.FormatCoinFromBase64(); }
            catch (FormatException) { }

            if (!redemptionKey.Stamp.Equals(coin.Stamp))
            {
                throw new Exception("Redemption stamp is not equal to the coins stamp!");
            }

            var v1 = coin.Version + 1;
            var v2 = coin.Version + 2;
            var v3 = coin.Version + 3;
            var v4 = coin.Version + 4;

            var c1 = new CoinDto
            {
                Keeper    = DeriveKey(v2, redemptionKey.Stamp, DeriveKey(v3, redemptionKey.Stamp, DeriveKey(v3, redemptionKey.Stamp, secret, salt).ToSecureString(), salt).ToSecureString(), salt),
                Version   = v1,
                Principle = redemptionKey.Key1,
                Stamp     = redemptionKey.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v2, redemptionKey.Stamp, redemptionKey.Key2.ToSecureString(), salt)
            };

            c1.Hash = Hash(c1).ToHex();

            var c2 = new CoinDto
            {
                Keeper    = DeriveKey(v3, redemptionKey.Stamp, DeriveKey(v4, redemptionKey.Stamp, DeriveKey(v4, redemptionKey.Stamp, secret, salt).ToSecureString(), salt).ToSecureString(), salt),
                Version   = v2,
                Principle = redemptionKey.Key2,
                Stamp     = redemptionKey.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v3, redemptionKey.Stamp, DeriveKey(v3, redemptionKey.Stamp, secret, salt).ToSecureString(), salt)
            };

            c2.Hash = Hash(c2).ToHex();

            return(c1, c2);
        }
Exemple #14
0
        /// <summary>
        /// Hash the specified coin.
        /// </summary>
        /// <returns>The hash.</returns>
        /// <param name="coin">Coin.</param>
        public byte[] Hash(CoinDto coin)
        {
            if (coin == null)
            {
                throw new ArgumentNullException(nameof(coin));
            }

            return(Cryptography.GenericHashNoKey(
                       string.Format("{0} {1} {2} {3} {4} {5} {6}",
                                     coin.Envelope.Commitment,
                                     coin.Envelope.Proof,
                                     coin.Envelope.PublicKey,
                                     coin.Hint,
                                     coin.Keeper,
                                     coin.Principle,
                                     coin.Stamp)));
        }
Exemple #15
0
        /// <summary>
        /// Change partial ownership.
        /// </summary>
        /// <returns>The partial one.</returns>
        /// <param name="secret">secret.</param>
        /// <param name="coin">Coin.</param>
        /// <param name="redemptionKey">Redemption key.</param>
        public CoinDto SwapPartialOne(SecureString secret, SecureString salt, CoinDto coin, RedemptionKeyDto redemptionKey)
        {
            Guard.Argument(secret, nameof(secret)).NotNull();
            Guard.Argument(coin, nameof(coin)).NotNull();
            Guard.Argument(redemptionKey, nameof(redemptionKey)).NotNull();

            var v1 = coin.Version + 1;
            var v2 = coin.Version + 2;
            var v3 = coin.Version + 3;

            coin.Keeper    = DeriveKey(v2, coin.Stamp, DeriveKey(v3, coin.Stamp, DeriveKey(v3, coin.Stamp, secret, salt).ToSecureString(), salt).ToSecureString(), salt);
            coin.Version   = v1;
            coin.Principle = redemptionKey.Key1;
            coin.Stamp     = coin.Stamp;
            coin.Envelope  = coin.Envelope;
            coin.Hint      = redemptionKey.Key2;

            return(coin);
        }
Exemple #16
0
        /// <summary>
        /// Verifies the coin on ownership.
        /// </summary>
        /// <returns>The coin.</returns>
        /// <param name="terminal">Terminal.</param>
        /// <param name="current">Current.</param>
        public int VerifyCoin(CoinDto terminal, CoinDto current)
        {
            if (terminal == null)
            {
                throw new ArgumentNullException(nameof(terminal));
            }

            if (current == null)
            {
                throw new ArgumentNullException(nameof(current));
            }

            return(terminal.Keeper.Equals(current.Keeper) && terminal.Hint.Equals(current.Hint)
               ? 1
               : terminal.Hint.Equals(current.Hint)
               ? 2
               : terminal.Keeper.Equals(current.Keeper)
               ? 3
               : 4);
        }
Exemple #17
0
        /// <summary>
        /// Derives the coin.
        /// </summary>
        /// <returns>The coin.</returns>
        /// <param name="coin">Coin.</param>
        public CoinDto DeriveCoin(CoinDto coin, SecureString secret, SecureString salt)
        {
            Guard.Argument(secret, nameof(secret)).NotNull();
            Guard.Argument(coin, nameof(coin)).NotNull();

            var v0 = +coin.Version;
            var v1 = +coin.Version + 1;
            var v2 = +coin.Version + 2;

            var c = new CoinDto
            {
                Keeper    = DeriveKey(v1, coin.Stamp, DeriveKey(v2, coin.Stamp, DeriveKey(v2, coin.Stamp, secret, salt).ToSecureString(), salt).ToSecureString(), salt),
                Version   = v0,
                Principle = DeriveKey(v0, coin.Stamp, secret, salt),
                Stamp     = coin.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v1, coin.Stamp, DeriveKey(v1, coin.Stamp, secret, salt).ToSecureString(), salt)
            };

            return(c);
        }
Exemple #18
0
        /// <summary>
        /// Derives the coin.
        /// </summary>
        /// <returns>The coin.</returns>
        /// <param name="coin">Coin.</param>
        public CoinDto DeriveCoin(CoinDto coin)
        {
            Guard.Argument(password, nameof(password)).NotNull();
            Guard.Argument(coin, nameof(coin)).NotNull();

            var v0 = +coin.Version;
            var v1 = +coin.Version + 1;
            var v2 = +coin.Version + 2;

            var c = new CoinDto()
            {
                Keeper    = DeriveKey(v1, coin.Stamp, DeriveKey(v2, coin.Stamp, DeriveKey(v2, coin.Stamp, Password()).ToSecureString()).ToSecureString()),
                Version   = v0,
                Principle = DeriveKey(v0, coin.Stamp, Password()),
                Stamp     = coin.Stamp,
                Envelope  = coin.Envelope,
                Hint      = DeriveKey(v1, coin.Stamp, DeriveKey(v1, coin.Stamp, Password()).ToSecureString())
            };

            return(c);
        }
Exemple #19
0
        /// <summary>
        /// Builds the sender.
        /// </summary>
        /// <returns>The sender.</returns>
        public CoinDto BuildSender()
        {
            CoinDto coin = null;

            using (var secp256k1 = new Secp256k1())
                using (var pedersen = new Pedersen())
                {
                    var blindPos = pedersen.BlindSwitch((ulong)Input(), DeriveKey(Input()));
                    var blindNeg = pedersen.BlindSwitch((ulong)Output(), DeriveKey(Output()));
                    var blindSum = pedersen.BlindSum(new List <byte[]> {
                        blindPos
                    }, new List <byte[]> {
                        blindNeg
                    });
                    var commitPos = Commit((ulong)Input(), blindPos);
                    var commitNeg = Commit((ulong)Output(), blindNeg);

                    coin = BuildCoin(blindSum, commitPos, commitNeg);
                }

            return(coin);
        }
Exemple #20
0
        /// <summary>
        /// Builds the sender.
        /// </summary>
        /// <returns>The sender.</returns>
        public CoinService BuildSender()
        {
            using (var secp256k1 = new Secp256k1())
                using (var pedersen = new Pedersen())
                {
                    var naTInput  = NaT(Input());
                    var naTOutput = NaT(Output());

                    byte[] blindPos = new byte[32];
                    byte[] blindNeg = new byte[32];
                    byte[] blindSum = new byte[32];

                    try
                    {
                        blindPos = pedersen.BlindSwitch(naTInput, DeriveKey(naTInput));
                        blindNeg = pedersen.BlindSwitch(naTOutput, DeriveKey(naTOutput));
                        blindSum = pedersen.BlindSum(new List <byte[]> {
                            blindPos
                        }, new List <byte[]> {
                            blindNeg
                        });
                    }
                    catch (Exception ex)
                    {
                        logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}");
                        throw ex;
                    }

                    var commitPos = Commit(naTInput, blindPos);
                    var commitNeg = Commit(naTOutput, blindNeg);

                    mintedCoin = BuildCoin(blindSum, commitPos, commitNeg);
                }

            return(this);
        }
Exemple #21
0
        /// <summary>
        /// Attachs the envelope.
        /// </summary>
        /// <param name="blindSum">Blind sum.</param>
        /// <param name="commitSum">Commit sum.</param>
        /// <param name="balance">Balance.</param>
        /// <param name="secret">Secret.</param>
        /// <param name="coin">Coin.</param>
        private void AttachEnvelope(byte[] blindSum, byte[] commitSum, ulong balance, SecureString secret, SecureString salt, ref CoinDto coin)
        {
            var(k1, k2) = Split(blindSum, secret, salt, coin.Stamp, coin.Version);

            using (var secp256k1 = new Secp256k1())
                using (var pedersen = new Pedersen())
                    using (var bulletProof = new BulletProof())
                    {
                        coin.Envelope.Commitment = commitSum.ToHex();
                        coin.Envelope.Proof      = k2.ToHex();
                        coin.Envelope.PublicKey  = pedersen.ToPublicKey(pedersen.Commit(0, k1)).ToHex();
                        coin.Hash = Hash(coin).ToHex();
                        coin.Envelope.Signature = secp256k1.Sign(coin.Hash.FromHex(), k1).ToHex();

                        var @struct = bulletProof.ProofSingle(balance, blindSum, Cryptography.RandomBytes(), null, null, null);
                        var success = bulletProof.Verify(commitSum, @struct.proof, null);

                        if (!success)
                        {
                            throw new ArgumentOutOfRangeException(nameof(success), "Bullet proof failed.");
                        }

                        coin.Envelope.RangeProof = @struct.proof.ToHex();
                    }
        }
Exemple #22
0
        /// <summary>
        /// Builds the coin.
        /// </summary>
        /// <returns>The coin.</returns>
        /// <param name="blindSum">Blind sum.</param>
        /// <param name="commitPos">Commit position.</param>
        /// <param name="commitNeg">Commit neg.</param>
        private CoinDto BuildCoin(byte[] blindSum, byte[] commitPos, byte[] commitNeg, bool isReceiver = false)
        {
            Guard.Argument(blindSum, nameof(blindSum)).NotNull().MaxCount(32);
            Guard.Argument(commitPos, nameof(commitPos)).NotNull().MaxCount(33);
            Guard.Argument(commitNeg, nameof(commitNeg)).NotNull().MaxCount(33);

            CoinDto coin = null;
            bool    isVerified;

            using (var secp256k1 = new Secp256k1())
                using (var pedersen = new Pedersen())
                    using (var rangeProof = new RangeProof())
                    {
                        try
                        {
                            var commitSum = pedersen.CommitSum(new List <byte[]> {
                                commitPos
                            }, new List <byte[]> {
                                commitNeg
                            });
                            var naTInput  = NaT(Input());
                            var naTOutput = NaT(Output());
                            var naTChange = naTInput - naTOutput;

                            isVerified = isReceiver
                        ? pedersen.VerifyCommitSum(new List <byte[]> {
                                commitPos, commitNeg
                            }, new List <byte[]> {
                                Commit(naTOutput, blindSum)
                            })
                        : pedersen.VerifyCommitSum(new List <byte[]> {
                                commitPos
                            }, new List <byte[]> {
                                commitNeg, commitSum
                            });

                            if (!isVerified)
                            {
                                throw new ArgumentOutOfRangeException(nameof(isVerified), "Verify commit sum failed.");
                            }

                            var(k1, k2) = Split(blindSum, isReceiver);

                            coin = MakeSingleCoin();

                            coin.Envelope.Commitment = isReceiver ? Commit(naTOutput, blindSum).ToHex() : commitSum.ToHex();
                            coin.Envelope.Proof      = k2.ToHex();
                            coin.Envelope.PublicKey  = pedersen.ToPublicKey(Commit(0, k1)).ToHex();
                            coin.Envelope.Signature  = secp256k1.Sign(Hash(coin), k1).ToHex();

                            coin.Hash = Hash(coin).ToHex();

                            proofStruct = isReceiver
                        ? rangeProof.Proof(0, naTOutput, blindSum, coin.Envelope.Commitment.FromHex(), coin.Hash.FromHex())
                        : rangeProof.Proof(0, naTChange, blindSum, coin.Envelope.Commitment.FromHex(), coin.Hash.FromHex());

                            isVerified = rangeProof.Verify(coin.Envelope.Commitment.FromHex(), proofStruct);

                            if (!isVerified)
                            {
                                throw new ArgumentOutOfRangeException(nameof(isVerified), "Range proof failed.");
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogError($"Message: {ex.Message}\n Stack: {ex.StackTrace}");
                        }
                    }

            return(coin);
        }