/// <summary>
        /// Verify a proof that a committed value is within a range.
        /// </summary>
        /// <returns>The verify.</returns>
        /// <param name="commit">Commit.</param>
        /// <param name="struct">Proof.</param>
        public bool Verify(byte[] commit, ProofStruct @struct)
        {
            if (commit.Length < Constant.PEDERSEN_COMMITMENT_SIZE)
            {
                throw new ArgumentException($"{nameof(commit)} must be {Constant.PEDERSEN_COMMITMENT_SIZE} bytes");
            }

            bool  success;
            ulong min = 0, max = 0;

            byte[] extraCommit = new byte[33];

            using (var pedersen = new Pedersen())
            {
                commit = pedersen.CommitParse(commit);

                success = secp256k1_rangeproof_verify(
                    Context,
                    ref min,
                    ref max,
                    commit,
                    @struct.proof,
                    @struct.plen,
                    extraCommit,
                    0,
                    Constant.GENERATOR_H) == 1;
            }

            return(success);
        }
        /// <summary>
        /// Verify a range proof and rewind the proof to recover information
        /// sent by its author.
        /// </summary>
        /// <returns>The rewind.</returns>
        /// <param name="commit">Commit.</param>
        /// <param name="struct">Proof.</param>
        /// <param name="nonce">Nonce.</param>
        public ProofInfoStruct Rewind(byte[] commit, ProofStruct @struct, byte[] nonce)
        {
            if (commit.Length < Constant.PEDERSEN_COMMITMENT_SIZE)
            {
                throw new ArgumentException($"{nameof(commit)} must be {Constant.PEDERSEN_COMMITMENT_SIZE} bytes");
            }

            if (nonce.Length < Constant.SECRET_KEY_SIZE)
            {
                throw new ArgumentException($"{nameof(nonce)} must be {Constant.SECRET_KEY_SIZE} bytes");
            }

            ulong value = 0, min = 0, max = 0;

            byte[] blindOut = new byte[32];
            byte[] message  = new byte[Constant.PROOF_MSG_SIZE];
            uint   mlen     = Constant.PROOF_MSG_SIZE;

            byte[] extraCommit = new byte[33];

            using (var pedersen = new Pedersen())
            {
                commit = pedersen.CommitParse(commit);

                var success = secp256k1_rangeproof_rewind(
                    Context,
                    blindOut,
                    ref value,
                    message,
                    ref mlen,
                    nonce,
                    ref min,
                    ref max,
                    commit,
                    @struct.proof,
                    @struct.plen,
                    extraCommit,
                    0,
                    Constant.GENERATOR_H
                    ) == 1;

                return(new ProofInfoStruct(
                           success,
                           value,
                           message,
                           blindOut,
                           mlen,
                           min,
                           max,
                           0,
                           0));
            }
        }
        /// <summary>
        /// Produces a range proof for the provided value, using min and max.
        /// </summary>
        /// <returns>The proof.</returns>
        /// <param name="min">Minimum.</param>
        /// <param name="value">Value.</param>
        /// <param name="blind">Blind.</param>
        /// <param name="commit">Commit.</param>
        /// <param name="msg">Message.</param>
        public ProofStruct Proof(ulong min, ulong value, byte[] blind, byte[] commit, byte[] msg)
        {
            if (blind.Length != Constant.BLIND_LENGTH)
            {
                throw new ArgumentException($"{nameof(blind)} must be {Constant.BLIND_LENGTH} bytes");
            }

            if (commit.Length != Constant.PEDERSEN_COMMITMENT_SIZE)
            {
                throw new ArgumentException($"{nameof(commit)} must be {Constant.PEDERSEN_COMMITMENT_SIZE} bytes");
            }

            bool success = false;

            byte[] proof = new byte[Constant.MAX_PROOF_SIZE];
            uint   plen  = Constant.MAX_PROOF_SIZE;

            byte[] nonce       = (byte[])blind.Clone();
            byte[] extraCommit = new byte[33];

            using (var pedersen = new Pedersen())
            {
                commit = pedersen.CommitParse(commit);

                while (success == false)
                {
                    success = secp256k1_rangeproof_sign(
                        Context,
                        proof,
                        ref plen,
                        min,
                        commit,
                        blind,
                        nonce,
                        0,
                        64,
                        value,
                        msg,
                        (uint)msg.Length,
                        extraCommit,
                        0,
                        Constant.GENERATOR_H) == 1;
                }

                return(new ProofStruct(proof, plen));
            }
        }