LCOV - code coverage report
Current view: top level - src/sapling - note.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 90 99 90.9 %
Date: 2025-02-23 09:33:43 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2016-2020 The ZCash developers
       2             : // Copyright (c) 2021 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "sapling/note.h"
       7             : 
       8             : #include "crypto/sha256.h"
       9             : #include "random.h"
      10             : #include "sapling/prf.h"
      11             : #include "sapling/sapling_util.h"
      12             : #include "streams.h"
      13             : #include "version.h"
      14             : 
      15             : #include <librustzcash.h>
      16             : 
      17             : using namespace libzcash;
      18             : 
      19             : // Construct and populate Sapling note for a given payment address and value.
      20        2413 : SaplingNote::SaplingNote(const SaplingPaymentAddress& address, const uint64_t value) :
      21        2413 :         BaseNote(value)
      22             : {
      23        2413 :     d = address.d;
      24        2413 :     pk_d = address.pk_d;
      25        2413 :     librustzcash_sapling_generate_r(r.begin());
      26        2413 : }
      27             : 
      28             : // Call librustzcash to compute the commitment
      29        2737 : Optional<uint256> SaplingNote::cmu() const
      30             : {
      31        2737 :     uint256 result;
      32        2737 :     if (!librustzcash_sapling_compute_cm(
      33             :             d.data(),
      34             :             pk_d.begin(),
      35             :             value(),
      36             :             r.begin(),
      37             :             result.begin()
      38             :         ))
      39             :     {
      40           0 :         return nullopt;
      41             :     }
      42             : 
      43        2737 :     return result;
      44             : }
      45             : 
      46             : // Call librustzcash to compute the nullifier
      47         977 : Optional<uint256> SaplingNote::nullifier(const SaplingFullViewingKey& vk, const uint64_t position) const
      48             : {
      49         977 :     auto ak = vk.ak;
      50         977 :     auto nk = vk.nk;
      51             : 
      52         977 :     uint256 result;
      53         977 :     if (!librustzcash_sapling_compute_nf(
      54             :             d.data(),
      55             :             pk_d.begin(),
      56             :             value(),
      57             :             r.begin(),
      58         977 :             ak.begin(),
      59         977 :             nk.begin(),
      60             :             position,
      61             :             result.begin()
      62             :     ))
      63             :     {
      64           0 :         return nullopt;
      65             :     }
      66             : 
      67         977 :     return result;
      68             : }
      69             : 
      70             : // Construct and populate SaplingNotePlaintext for a given note and memo.
      71        1324 : SaplingNotePlaintext::SaplingNotePlaintext(
      72             :     const SaplingNote& note,
      73        1324 :     const std::array<unsigned char, ZC_MEMO_SIZE>& memo) : BaseNotePlaintext(note, memo)
      74             : {
      75        1324 :     d = note.d;
      76        1324 :     rcm = note.r;
      77        1324 : }
      78             : 
      79             : 
      80        2078 : Optional<SaplingNote> SaplingNotePlaintext::note(const SaplingIncomingViewingKey& ivk) const
      81             : {
      82        2078 :     auto addr = ivk.address(d);
      83        2078 :     if (addr) {
      84        2078 :         return SaplingNote(d, addr.get().pk_d, value_, rcm);
      85             :     } else {
      86           0 :         return nullopt;
      87             :     }
      88             : }
      89             : 
      90         104 : Optional<SaplingOutgoingPlaintext> SaplingOutgoingPlaintext::decrypt(
      91             :     const SaplingOutCiphertext& ciphertext,
      92             :     const uint256& ovk,
      93             :     const uint256& cv,
      94             :     const uint256& cm,
      95             :     const uint256& epk
      96             : )
      97             : {
      98         208 :     auto pt = AttemptSaplingOutDecryption(ciphertext, ovk, cv, cm, epk);
      99         104 :     if (!pt) {
     100           8 :         return nullopt;
     101             :     }
     102             : 
     103             :     // Deserialize from the plaintext
     104         200 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     105          96 :     ss << pt.get();
     106             : 
     107          96 :     SaplingOutgoingPlaintext ret;
     108          96 :     ss >> ret;
     109             : 
     110          96 :     assert(ss.size() == 0);
     111             : 
     112          96 :     return ret;
     113             : }
     114             : 
     115        8905 : Optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
     116             :     const SaplingEncCiphertext& ciphertext,
     117             :     const uint256& ivk,
     118             :     const uint256& epk,
     119             :     const uint256& cmu
     120             : )
     121             : {
     122       17810 :     auto pt = AttemptSaplingEncDecryption(ciphertext, ivk, epk);
     123        8905 :     if (!pt) {
     124        4761 :         return nullopt;
     125             :     }
     126             : 
     127             :     // Deserialize from the plaintext
     128       13049 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     129        4144 :     ss << pt.get();
     130             : 
     131        8288 :     SaplingNotePlaintext ret;
     132        4144 :     ss >> ret;
     133             : 
     134        4144 :     assert(ss.size() == 0);
     135             : 
     136        4144 :     uint256 pk_d;
     137        4144 :     if (!librustzcash_ivk_to_pkd(ivk.begin(), ret.d.data(), pk_d.begin())) {
     138           0 :         return nullopt;
     139             :     }
     140             : 
     141        4144 :     uint256 cmu_expected;
     142        4144 :     if (!librustzcash_sapling_compute_cm(
     143        4144 :         ret.d.data(),
     144        4144 :         pk_d.begin(),
     145             :         ret.value(),
     146        4144 :         ret.rcm.begin(),
     147             :         cmu_expected.begin()
     148             :     ))
     149             :     {
     150           0 :         return nullopt;
     151             :     }
     152             : 
     153        4144 :     if (cmu_expected != cmu) {
     154           1 :         return nullopt;
     155             :     }
     156             : 
     157        4144 :     return ret;
     158             : }
     159             : 
     160          97 : Optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
     161             :     const SaplingEncCiphertext& ciphertext,
     162             :     const uint256& epk,
     163             :     const uint256& esk,
     164             :     const uint256& pk_d,
     165             :     const uint256& cmu
     166             : )
     167             : {
     168         194 :     auto pt = AttemptSaplingEncDecryption(ciphertext, epk, esk, pk_d);
     169          97 :     if (!pt) {
     170           0 :         return nullopt;
     171             :     }
     172             : 
     173             :     // Deserialize from the plaintext
     174         194 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     175          97 :     ss << pt.get();
     176             : 
     177         194 :     SaplingNotePlaintext ret;
     178          97 :     ss >> ret;
     179             : 
     180          97 :     uint256 cmu_expected;
     181          97 :     if (!librustzcash_sapling_compute_cm(
     182          97 :         ret.d.data(),
     183             :         pk_d.begin(),
     184             :         ret.value(),
     185          97 :         ret.rcm.begin(),
     186             :         cmu_expected.begin()
     187             :     ))
     188             :     {
     189           0 :         return nullopt;
     190             :     }
     191             : 
     192          97 :     if (cmu_expected != cmu) {
     193           1 :         return nullopt;
     194             :     }
     195             : 
     196          96 :     assert(ss.size() == 0);
     197             : 
     198          97 :     return ret;
     199             : }
     200             : 
     201        1324 : Optional<SaplingNotePlaintextEncryptionResult> SaplingNotePlaintext::encrypt(const uint256& pk_d) const
     202             : {
     203             :     // Get the encryptor
     204        2648 :     auto sne = SaplingNoteEncryption::FromDiversifier(d);
     205        1324 :     if (!sne) {
     206           0 :         return nullopt;
     207             :     }
     208        1324 :     auto enc = sne.get();
     209             : 
     210             :     // Create the plaintext
     211        2648 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     212        1324 :     ss << (*this);
     213        1324 :     SaplingEncPlaintext pt;
     214        1324 :     assert(pt.size() == ss.size());
     215        1324 :     memcpy(&pt[0], &ss[0], pt.size());
     216             : 
     217             :     // Encrypt the plaintext
     218        2648 :     auto encciphertext = enc.encrypt_to_recipient(pk_d, pt);
     219        1324 :     if (!encciphertext) {
     220           0 :         return nullopt;
     221             :     }
     222        1324 :     return SaplingNotePlaintextEncryptionResult(encciphertext.get(), enc);
     223             : }
     224             : 
     225             : 
     226        1324 : SaplingOutCiphertext SaplingOutgoingPlaintext::encrypt(
     227             :         const uint256& ovk,
     228             :         const uint256& cv,
     229             :         const uint256& cm,
     230             :         SaplingNoteEncryption& enc
     231             :     ) const
     232             : {
     233             :     // Create the plaintext
     234        1324 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     235        1324 :     ss << (*this);
     236        1324 :     SaplingOutPlaintext pt;
     237        1324 :     assert(pt.size() == ss.size());
     238        1324 :     memcpy(&pt[0], &ss[0], pt.size());
     239             : 
     240        2648 :     return enc.encrypt_to_ourselves(ovk, cv, cm, pt);
     241             : }

Generated by: LCOV version 1.14