From 34bf166e5fd50fdd87135095d14c7ef19c1252c7 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 11 Jul 2018 22:03:04 -0700 Subject: [PATCH] Add encryption of SaplingNotePlaintext and SaplingOutgoingPlaintext classes. This is part of #3061 to add Sapling note functionality. --- src/zcash/Note.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/zcash/Note.hpp | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index d84a98067..7e776c756 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -137,3 +137,68 @@ ZCNoteEncryption::Ciphertext SproutNotePlaintext::encrypt(ZCNoteEncryption& encr return encryptor.encrypt(pk_enc, pt); } + + + +// Construct and populate SaplingNotePlaintext for a given note and memo. +SaplingNotePlaintext::SaplingNotePlaintext( + const SaplingNote& note, + std::array memo) : BaseNotePlaintext(note, memo) +{ + d = note.d; + rcm = note.r; +} + + +boost::optional SaplingNotePlaintext::note(const SaplingIncomingViewingKey& ivk) const +{ + auto addr = ivk.address( d ); + if (addr) { + return SaplingNote(addr.get(), value_); + } else { + return boost::none; + } +} + + +boost::optional SaplingNotePlaintext::encrypt(const uint256& pk_d) const +{ + // Get the encryptor + auto sne = SaplingNoteEncryption::FromDiversifier(d); + if (!sne) { + return boost::none; + } + auto enc = sne.get(); + + // Create the plaintext + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << (*this); + SaplingEncPlaintext pt; + assert(pt.size() == ss.size()); + memcpy(&pt[0], &ss[0], pt.size()); + + // Encrypt the plaintext + auto encciphertext = enc.encrypt_to_recipient(pk_d, pt); + if (!encciphertext) { + return boost::none; + } + return SaplingNotePlaintextEncryptionResult(encciphertext.get(), enc); +} + + +SaplingOutCiphertext SaplingOutgoingPlaintext::encrypt( + const uint256& ovk, + const uint256& cv, + const uint256& cm, + SaplingNoteEncryption& enc + ) const +{ + // Create the plaintext + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << (*this); + SaplingOutPlaintext pt; + assert(pt.size() == ss.size()); + memcpy(&pt[0], &ss[0], pt.size()); + + return enc.encrypt_to_ourselves(ovk, cv, cm, pt); +} diff --git a/src/zcash/Note.hpp b/src/zcash/Note.hpp index 39610fce0..8bdc2de3b 100644 --- a/src/zcash/Note.hpp +++ b/src/zcash/Note.hpp @@ -116,6 +116,68 @@ public: ) const; }; +typedef std::pair, std::reference_wrapper> SaplingNotePlaintextEncryptionResult; + +class SaplingNotePlaintext : public BaseNotePlaintext { +public: + diversifier_t d; + uint256 rcm; + + SaplingNotePlaintext() {} + + SaplingNotePlaintext(const SaplingNote& note, std::array memo); + + boost::optional note(const SaplingIncomingViewingKey& ivk) const; + + virtual ~SaplingNotePlaintext() {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + unsigned char leadingByte = 0x01; + READWRITE(leadingByte); + + if (leadingByte != 0x01) { + throw std::ios_base::failure("lead byte of SaplingNotePlaintext is not recognized"); + } + + READWRITE(d); // 11 bytes + READWRITE(value_); // 8 bytes + READWRITE(rcm); // 32 bytes + READWRITE(memo_); // 512 bytes + } + + boost::optional encrypt(const uint256& pk_d) const; +}; + +class SaplingOutgoingPlaintext +{ +public: + uint256 pk_d; + uint256 esk; + + SaplingOutgoingPlaintext() {}; + + SaplingOutgoingPlaintext(uint256 pk_d, uint256 esk) : pk_d(pk_d), esk(esk) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(pk_d); // 8 bytes + READWRITE(esk); // 8 bytes + } + + SaplingOutCiphertext encrypt( + const uint256& ovk, + const uint256& cv, + const uint256& cm, + SaplingNoteEncryption& enc + ) const; +}; + + } #endif // ZC_NOTE_H_