Skip to content

Commit

Permalink
Auto merge of zcash#3234 - str4d:3058-address-polymorphism, r=str4d
Browse files Browse the repository at this point in the history
Use boost::variant to represent shielded addresses and keys

Part of zcash#3058 and zcash#3059.
  • Loading branch information
zkbot committed May 12, 2018
2 parents 1942f7a + e5eab18 commit 75546c6
Show file tree
Hide file tree
Showing 40 changed files with 488 additions and 336 deletions.
18 changes: 9 additions & 9 deletions src/gtest/test_joinsplit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ void test_full_api(ZCJoinSplit* js)
auto verifier = libzcash::ProofVerifier::Strict();

// The recipient's information.
SpendingKey recipient_key = SpendingKey::random();
PaymentAddress recipient_addr = recipient_key.address();
SproutSpendingKey recipient_key = SproutSpendingKey::random();
SproutPaymentAddress recipient_addr = recipient_key.address();

// Create the commitment tree
ZCIncrementalMerkleTree tree;
Expand Down Expand Up @@ -122,8 +122,8 @@ void test_full_api(ZCJoinSplit* js)
JSInput(witness_recipient, decrypted_note, recipient_key)
};

SpendingKey second_recipient = SpendingKey::random();
PaymentAddress second_addr = second_recipient.address();
SproutSpendingKey second_recipient = SproutSpendingKey::random();
SproutPaymentAddress second_addr = second_recipient.address();

boost::array<JSOutput, 2> outputs = {
JSOutput(second_addr, 9),
Expand Down Expand Up @@ -317,8 +317,8 @@ TEST(joinsplit, full_api_test)
std::vector<ZCIncrementalWitness> witnesses;
ZCIncrementalMerkleTree tree;
increment_note_witnesses(uint256(), witnesses, tree);
SpendingKey sk = SpendingKey::random();
PaymentAddress addr = sk.address();
SproutSpendingKey sk = SproutSpendingKey::random();
SproutPaymentAddress addr = sk.address();
SproutNote note1(addr.a_pk, 100, random_uint256(), random_uint256());
increment_note_witnesses(note1.cm(), witnesses, tree);
SproutNote note2(addr.a_pk, 100, random_uint256(), random_uint256());
Expand Down Expand Up @@ -422,7 +422,7 @@ TEST(joinsplit, full_api_test)
// Wrong secret key
invokeAPIFailure(params,
{
JSInput(witnesses[1], note1, SpendingKey::random()),
JSInput(witnesses[1], note1, SproutSpendingKey::random()),
JSInput()
},
{
Expand Down Expand Up @@ -519,7 +519,7 @@ TEST(joinsplit, note_plaintexts)
uint256 a_pk = PRF_addr_a_pk(a_sk);
uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk);
uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc);
PaymentAddress addr_pk(a_pk, pk_enc);
SproutPaymentAddress addr_pk(a_pk, pk_enc);

uint256 h_sig;

Expand Down Expand Up @@ -572,7 +572,7 @@ TEST(joinsplit, note_class)
uint256 a_pk = PRF_addr_a_pk(a_sk);
uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk);
uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc);
PaymentAddress addr_pk(a_pk, pk_enc);
SproutPaymentAddress addr_pk(a_pk, pk_enc);

SproutNote note(a_pk,
1945813,
Expand Down
24 changes: 12 additions & 12 deletions src/gtest/test_keystore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

TEST(keystore_tests, store_and_retrieve_spending_key) {
CBasicKeyStore keyStore;
libzcash::SpendingKey skOut;
libzcash::SproutSpendingKey skOut;

std::set<libzcash::PaymentAddress> addrs;
std::set<libzcash::SproutPaymentAddress> addrs;
keyStore.GetPaymentAddresses(addrs);
EXPECT_EQ(0, addrs.size());

auto sk = libzcash::SpendingKey::random();
auto sk = libzcash::SproutSpendingKey::random();
auto addr = sk.address();

// Sanity-check: we can't get a key we haven't added
Expand All @@ -36,7 +36,7 @@ TEST(keystore_tests, store_and_retrieve_note_decryptor) {
CBasicKeyStore keyStore;
ZCNoteDecryption decOut;

auto sk = libzcash::SpendingKey::random();
auto sk = libzcash::SproutSpendingKey::random();
auto addr = sk.address();

EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut));
Expand All @@ -48,11 +48,11 @@ TEST(keystore_tests, store_and_retrieve_note_decryptor) {

TEST(keystore_tests, StoreAndRetrieveViewingKey) {
CBasicKeyStore keyStore;
libzcash::ViewingKey vkOut;
libzcash::SpendingKey skOut;
libzcash::SproutViewingKey vkOut;
libzcash::SproutSpendingKey skOut;
ZCNoteDecryption decOut;

auto sk = libzcash::SpendingKey::random();
auto sk = libzcash::SproutSpendingKey::random();
auto vk = sk.viewing_key();
auto addr = sk.address();

Expand All @@ -66,7 +66,7 @@ TEST(keystore_tests, StoreAndRetrieveViewingKey) {
EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut));

// and we can't find it in our list of addresses
std::set<libzcash::PaymentAddress> addresses;
std::set<libzcash::SproutPaymentAddress> addresses;
keyStore.GetPaymentAddresses(addresses);
EXPECT_FALSE(addresses.count(addr));

Expand Down Expand Up @@ -115,12 +115,12 @@ TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) {
TestCCryptoKeyStore keyStore;
uint256 r {GetRandHash()};
CKeyingMaterial vMasterKey (r.begin(), r.end());
libzcash::SpendingKey keyOut;
libzcash::SproutSpendingKey keyOut;
ZCNoteDecryption decOut;
std::set<libzcash::PaymentAddress> addrs;
std::set<libzcash::SproutPaymentAddress> addrs;

// 1) Test adding a key to an unencrypted key store, then encrypting it
auto sk = libzcash::SpendingKey::random();
auto sk = libzcash::SproutSpendingKey::random();
auto addr = sk.address();
EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut));

Expand Down Expand Up @@ -157,7 +157,7 @@ TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) {
ASSERT_EQ(1, addrs.count(addr));

// 2) Test adding a spending key to an already-encrypted key store
auto sk2 = libzcash::SpendingKey::random();
auto sk2 = libzcash::SproutSpendingKey::random();
auto addr2 = sk2.address();
EXPECT_FALSE(keyStore.GetNoteDecryptor(addr2, decOut));

Expand Down
4 changes: 2 additions & 2 deletions src/gtest/test_paymentdisclosure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ TEST(paymentdisclosure, mainnet) {
PaymentDisclosureInfo info;
info.esk = random_uint256();
info.joinSplitPrivKey = joinSplitPrivKey;
info.zaddr = libzcash::SpendingKey::random().address();
info.zaddr = libzcash::SproutSpendingKey::random().address();
ASSERT_TRUE(mydb.Put(key, info));

// Retrieve info from test database into new local variable and test it matches
Expand All @@ -131,7 +131,7 @@ TEST(paymentdisclosure, mainnet) {
// Modify this local variable and confirm it no longer matches
info2.esk = random_uint256();
info2.joinSplitPrivKey = random_uint256();
info2.zaddr = libzcash::SpendingKey::random().address();
info2.zaddr = libzcash::SproutSpendingKey::random().address();
ASSERT_NE(info, info2);

// Using the payment info object, let's create a dummy payload
Expand Down
4 changes: 2 additions & 2 deletions src/gtest/test_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ TEST(Transaction, JSDescriptionRandomized) {
// construct a merkle tree
ZCIncrementalMerkleTree merkleTree;

libzcash::SpendingKey k = libzcash::SpendingKey::random();
libzcash::PaymentAddress addr = k.address();
libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random();
libzcash::SproutPaymentAddress addr = k.address();

libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256());

Expand Down
2 changes: 1 addition & 1 deletion src/gtest/test_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) {
}

TEST(Validation, ReceivedBlockTransactions) {
auto sk = libzcash::SpendingKey::random();
auto sk = libzcash::SproutSpendingKey::random();

// Create a fake genesis block
CBlock block1;
Expand Down
108 changes: 80 additions & 28 deletions src/key_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,70 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
}
return CNoDestination();
}

class PaymentAddressEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;

public:
PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}

std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zaddr;
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
data.insert(data.end(), ss.begin(), ss.end());
return EncodeBase58Check(data);
}

std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
};

class ViewingKeyEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;

public:
ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}

std::string operator()(const libzcash::SproutViewingKey& vk) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << vk;
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}

std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
};

class SpendingKeyEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;

public:
SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}

std::string operator()(const libzcash::SproutSpendingKey& zkey) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zkey;
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}

std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
};
} // namespace

CKey DecodeSecret(const std::string& str)
Expand Down Expand Up @@ -167,14 +231,10 @@ bool IsValidDestinationString(const std::string& str)

std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zaddr;
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
data.insert(data.end(), ss.begin(), ss.end());
return EncodeBase58Check(data);
return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr);
}

boost::optional<libzcash::PaymentAddress> DecodePaymentAddress(const std::string& str)
libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
Expand All @@ -183,26 +243,24 @@ boost::optional<libzcash::PaymentAddress> DecodePaymentAddress(const std::string
std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::PaymentAddress ret;
libzcash::SproutPaymentAddress ret;
ss >> ret;
return ret;
}
}
return boost::none;
return libzcash::InvalidEncoding();
}

bool IsValidPaymentAddressString(const std::string& str) {
return IsValidPaymentAddress(DecodePaymentAddress(str));
}

std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << vk;
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
return boost::apply_visitor(ViewingKeyEncoder(Params()), vk);
}

boost::optional<libzcash::ViewingKey> DecodeViewingKey(const std::string& str)
libzcash::ViewingKey DecodeViewingKey(const std::string& str)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
Expand All @@ -211,29 +269,23 @@ boost::optional<libzcash::ViewingKey> DecodeViewingKey(const std::string& str)
std::equal(vk_prefix.begin(), vk_prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + vk_prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::ViewingKey ret;
libzcash::SproutViewingKey ret;
ss >> ret;
memory_cleanse(serialized.data(), serialized.size());
memory_cleanse(data.data(), data.size());
return ret;
}
}
memory_cleanse(data.data(), data.size());
return boost::none;
return libzcash::InvalidEncoding();
}

std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zkey;
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey);
}

boost::optional<libzcash::SpendingKey> DecodeSpendingKey(const std::string& str)
libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
Expand All @@ -242,13 +294,13 @@ boost::optional<libzcash::SpendingKey> DecodeSpendingKey(const std::string& str)
std::equal(zkey_prefix.begin(), zkey_prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + zkey_prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::SpendingKey ret;
libzcash::SproutSpendingKey ret;
ss >> ret;
memory_cleanse(serialized.data(), serialized.size());
memory_cleanse(data.data(), data.size());
return ret;
}
}
memory_cleanse(data.data(), data.size());
return boost::none;
return libzcash::InvalidEncoding();
}
7 changes: 4 additions & 3 deletions src/key_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ bool IsValidDestinationString(const std::string& str);
bool IsValidDestinationString(const std::string& str, const CChainParams& params);

std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr);
boost::optional<libzcash::PaymentAddress> DecodePaymentAddress(const std::string& str);
libzcash::PaymentAddress DecodePaymentAddress(const std::string& str);
bool IsValidPaymentAddressString(const std::string& str);

std::string EncodeViewingKey(const libzcash::ViewingKey& vk);
boost::optional<libzcash::ViewingKey> DecodeViewingKey(const std::string& str);
libzcash::ViewingKey DecodeViewingKey(const std::string& str);

std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey);
boost::optional<libzcash::SpendingKey> DecodeSpendingKey(const std::string& str);
libzcash::SpendingKey DecodeSpendingKey(const std::string& str);

#endif // BITCOIN_KEYIO_H
Loading

0 comments on commit 75546c6

Please sign in to comment.