Use boost::variant to represent shielded addresses and keys

libzcash::PaymentAddress has been renamed to libzcash::SproutPaymentAddress,
and a new typedef boost::variant is now libzcash::PaymentAddress. Similarly
for ViewingKey and SpendingKey.

A new class InvalidEncoding is introduced as the default boost::variant
option for each address and key type; it is used during decoding instead
of boost::optional.

All address and key storage functions in the wallet have been modified to
refer specifically to the Sprout types, as they are used very precisely.
In most other cases, the more general type is leveraged as much as possible,
and we convert to the Sprout type when necessary. This will be subsequently
wrapped in, or replaced with, context-specific functions once Sapling
types are implemented.
This commit is contained in:
Jack Grigg
2018-04-26 02:51:17 +01:00
parent 1942f7a42b
commit e5eab182b5
40 changed files with 488 additions and 336 deletions

View File

@@ -6,7 +6,7 @@
namespace libzcash {
uint256 PaymentAddress::GetHash() const {
uint256 SproutPaymentAddress::GetHash() const {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << *this;
return Hash(ss.begin(), ss.end());
@@ -16,24 +16,37 @@ uint256 ReceivingKey::pk_enc() const {
return ZCNoteEncryption::generate_pubkey(*this);
}
PaymentAddress ViewingKey::address() const {
return PaymentAddress(a_pk, sk_enc.pk_enc());
SproutPaymentAddress SproutViewingKey::address() const {
return SproutPaymentAddress(a_pk, sk_enc.pk_enc());
}
ReceivingKey SpendingKey::receiving_key() const {
ReceivingKey SproutSpendingKey::receiving_key() const {
return ReceivingKey(ZCNoteEncryption::generate_privkey(*this));
}
ViewingKey SpendingKey::viewing_key() const {
return ViewingKey(PRF_addr_a_pk(*this), receiving_key());
SproutViewingKey SproutSpendingKey::viewing_key() const {
return SproutViewingKey(PRF_addr_a_pk(*this), receiving_key());
}
SpendingKey SpendingKey::random() {
return SpendingKey(random_uint252());
SproutSpendingKey SproutSpendingKey::random() {
return SproutSpendingKey(random_uint252());
}
PaymentAddress SpendingKey::address() const {
SproutPaymentAddress SproutSpendingKey::address() const {
return viewing_key().address();
}
}
bool IsValidPaymentAddress(const libzcash::PaymentAddress& zaddr) {
return zaddr.which() != 0;
}
bool IsValidViewingKey(const libzcash::ViewingKey& vk) {
return vk.which() != 0;
}
bool IsValidSpendingKey(const libzcash::SpendingKey& zkey) {
return zkey.which() != 0;
}

View File

@@ -5,19 +5,26 @@
#include "uint252.h"
#include "serialize.h"
#include <boost/variant.hpp>
namespace libzcash {
class InvalidEncoding {
public:
friend bool operator==(const InvalidEncoding &a, const InvalidEncoding &b) { return true; }
friend bool operator<(const InvalidEncoding &a, const InvalidEncoding &b) { return true; }
};
const size_t SerializedPaymentAddressSize = 64;
const size_t SerializedViewingKeySize = 64;
const size_t SerializedSpendingKeySize = 32;
class PaymentAddress {
class SproutPaymentAddress {
public:
uint256 a_pk;
uint256 pk_enc;
PaymentAddress() : a_pk(), pk_enc() { }
PaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { }
SproutPaymentAddress() : a_pk(), pk_enc() { }
SproutPaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { }
ADD_SERIALIZE_METHODS;
@@ -30,10 +37,10 @@ public:
//! Get the 256-bit SHA256d hash of this payment address.
uint256 GetHash() const;
friend inline bool operator==(const PaymentAddress& a, const PaymentAddress& b) {
friend inline bool operator==(const SproutPaymentAddress& a, const SproutPaymentAddress& b) {
return a.a_pk == b.a_pk && a.pk_enc == b.pk_enc;
}
friend inline bool operator<(const PaymentAddress& a, const PaymentAddress& b) {
friend inline bool operator<(const SproutPaymentAddress& a, const SproutPaymentAddress& b) {
return (a.a_pk < b.a_pk ||
(a.a_pk == b.a_pk && a.pk_enc < b.pk_enc));
}
@@ -47,13 +54,13 @@ public:
uint256 pk_enc() const;
};
class ViewingKey {
class SproutViewingKey {
public:
uint256 a_pk;
ReceivingKey sk_enc;
ViewingKey() : a_pk(), sk_enc() { }
ViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { }
SproutViewingKey() : a_pk(), sk_enc() { }
SproutViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { }
ADD_SERIALIZE_METHODS;
@@ -63,29 +70,42 @@ public:
READWRITE(sk_enc);
}
PaymentAddress address() const;
SproutPaymentAddress address() const;
friend inline bool operator==(const ViewingKey& a, const ViewingKey& b) {
friend inline bool operator==(const SproutViewingKey& a, const SproutViewingKey& b) {
return a.a_pk == b.a_pk && a.sk_enc == b.sk_enc;
}
friend inline bool operator<(const ViewingKey& a, const ViewingKey& b) {
friend inline bool operator<(const SproutViewingKey& a, const SproutViewingKey& b) {
return (a.a_pk < b.a_pk ||
(a.a_pk == b.a_pk && a.sk_enc < b.sk_enc));
}
};
class SpendingKey : public uint252 {
class SproutSpendingKey : public uint252 {
public:
SpendingKey() : uint252() { }
SpendingKey(uint252 a_sk) : uint252(a_sk) { }
SproutSpendingKey() : uint252() { }
SproutSpendingKey(uint252 a_sk) : uint252(a_sk) { }
static SpendingKey random();
static SproutSpendingKey random();
ReceivingKey receiving_key() const;
ViewingKey viewing_key() const;
PaymentAddress address() const;
SproutViewingKey viewing_key() const;
SproutPaymentAddress address() const;
};
typedef boost::variant<InvalidEncoding, SproutPaymentAddress> PaymentAddress;
typedef boost::variant<InvalidEncoding, SproutViewingKey> ViewingKey;
typedef boost::variant<InvalidEncoding, SproutSpendingKey> SpendingKey;
}
/** Check whether a PaymentAddress is not an InvalidEncoding. */
bool IsValidPaymentAddress(const libzcash::PaymentAddress& zaddr);
/** Check whether a ViewingKey is not an InvalidEncoding. */
bool IsValidViewingKey(const libzcash::ViewingKey& vk);
/** Check whether a SpendingKey is not an InvalidEncoding. */
bool IsValidSpendingKey(const libzcash::SpendingKey& zkey);
#endif // ZC_ADDRESS_H_

View File

@@ -370,12 +370,12 @@ SproutNote JSOutput::note(const uint252& phi, const uint256& r, size_t i, const
}
JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) {
SpendingKey a_sk = SpendingKey::random();
SproutSpendingKey a_sk = SproutSpendingKey::random();
addr = a_sk.address();
}
JSInput::JSInput() : witness(ZCIncrementalMerkleTree().witness()),
key(SpendingKey::random()) {
key(SproutSpendingKey::random()) {
note = SproutNote(key.address().a_pk, 0, random_uint256(), random_uint256());
ZCIncrementalMerkleTree dummy_tree;
dummy_tree.append(note.cm());

View File

@@ -19,12 +19,12 @@ class JSInput {
public:
ZCIncrementalWitness witness;
SproutNote note;
SpendingKey key;
SproutSpendingKey key;
JSInput();
JSInput(ZCIncrementalWitness witness,
SproutNote note,
SpendingKey key) : witness(witness), note(note), key(key) { }
SproutSpendingKey key) : witness(witness), note(note), key(key) { }
uint256 nullifier() const {
return note.nullifier(key);
@@ -33,12 +33,12 @@ public:
class JSOutput {
public:
PaymentAddress addr;
SproutPaymentAddress addr;
uint64_t value;
boost::array<unsigned char, ZC_MEMO_SIZE> memo = {{0xF6}}; // 0xF6 is invalid UTF8 as per spec, rest of array is 0x00
JSOutput();
JSOutput(PaymentAddress addr, uint64_t value) : addr(addr), value(value) { }
JSOutput(SproutPaymentAddress addr, uint64_t value) : addr(addr), value(value) { }
SproutNote note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const;
};

View File

@@ -34,7 +34,7 @@ uint256 SproutNote::cm() const {
return result;
}
uint256 SproutNote::nullifier(const SpendingKey& a_sk) const {
uint256 SproutNote::nullifier(const SproutSpendingKey& a_sk) const {
return PRF_nf(a_sk, rho);
}
@@ -46,7 +46,7 @@ SproutNotePlaintext::SproutNotePlaintext(
r = note.r;
}
SproutNote SproutNotePlaintext::note(const PaymentAddress& addr) const
SproutNote SproutNotePlaintext::note(const SproutPaymentAddress& addr) const
{
return SproutNote(addr.a_pk, value_, rho, r);
}

View File

@@ -35,7 +35,7 @@ public:
virtual uint256 cm() const override;
uint256 nullifier(const SpendingKey& a_sk) const;
uint256 nullifier(const SproutSpendingKey& a_sk) const;
};
class BaseNotePlaintext {
@@ -61,7 +61,7 @@ public:
SproutNotePlaintext(const SproutNote& note, boost::array<unsigned char, ZC_MEMO_SIZE> memo);
SproutNote note(const PaymentAddress& addr) const;
SproutNote note(const SproutPaymentAddress& addr) const;
virtual ~SproutNotePlaintext() {}

View File

@@ -118,7 +118,7 @@ public:
void generate_r1cs_witness(
const MerklePath& path,
const SpendingKey& key,
const SproutSpendingKey& key,
const SproutNote& note
) {
note_gadget<FieldT>::generate_r1cs_witness(note);