/// <summary> /// Attaches the envelope. /// </summary> /// <param name="secp256k1">Secp256k1.</param> /// <param name="pedersen">Pedersen.</param> /// <param name="rangeProof">Range proof.</param> /// <param name="blindSum">Blind sum.</param> /// <param name="commitSum">Commit sum.</param> /// <param name="secret">Secret.</param> private void AttachEnvelope(Secp256k1 secp256k1, Pedersen pedersen, RangeProof rangeProof, byte[] blindSum, byte[] commitSum, ulong balance, SecureString secret) { var(k1, k2) = Split(blindSum, secret); 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(); proofStruct = rangeProof.Proof(0, balance, blindSum, commitSum, Coin().Hash.FromHex()); var isVerified = rangeProof.Verify(commitSum, proofStruct); if (!isVerified) { throw new ArgumentOutOfRangeException(nameof(isVerified), "Range proof failed."); } }
/// <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); }