Merge pull request #5400 from nuttycom/feature/wallet_orchard-ufvks
Add types & FFI for serialization of unified full viewing keys.
This commit is contained in:
commit
87eeee0607
|
@ -521,7 +521,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
|||
[[package]]
|
||||
name = "equihash"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -530,7 +530,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "f4jumble"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
]
|
||||
|
@ -1885,7 +1885,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_address"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"blake2b_simd",
|
||||
|
@ -1897,7 +1897,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_encoding"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"nonempty",
|
||||
|
@ -1906,7 +1906,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_history"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"bigint",
|
||||
"blake2b_simd",
|
||||
|
@ -1916,7 +1916,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_note_encryption"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -1931,7 +1931,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_primitives"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bip0039",
|
||||
|
@ -1965,7 +1965,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_proofs"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=69c3b4b5e143bb349cca76c677b7cd0a8556b28f#69c3b4b5e143bb349cca76c677b7cd0a8556b28f"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"blake2b_simd",
|
||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -73,8 +73,8 @@ codegen-units = 1
|
|||
ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" }
|
||||
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" }
|
||||
orchard = { git = "https://github.com/zcash/orchard.git", rev = "68b790c7dadade049f44ad4aafa0ff71a3a10e91" }
|
||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "69c3b4b5e143bb349cca76c677b7cd0a8556b28f" }
|
||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "69c3b4b5e143bb349cca76c677b7cd0a8556b28f" }
|
||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "69c3b4b5e143bb349cca76c677b7cd0a8556b28f" }
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "69c3b4b5e143bb349cca76c677b7cd0a8556b28f" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "69c3b4b5e143bb349cca76c677b7cd0a8556b28f" }
|
||||
|
|
|
@ -44,6 +44,7 @@ JSON_TEST_FILES = \
|
|||
test/data/merkle_commitments_sapling.json \
|
||||
test/data/sapling_key_components.json \
|
||||
test/data/unified_addrs.json \
|
||||
test/data/unified_full_viewing_keys.json \
|
||||
test/data/zip0244.json
|
||||
|
||||
RAW_TEST_FILES = test/data/alertTests.raw
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "json_test_vectors.h"
|
||||
#include "test/data/unified_addrs.json.h"
|
||||
#include "test/data/unified_full_viewing_keys.json.h"
|
||||
|
||||
TEST(Keys, EncodeAndDecodeSapling)
|
||||
{
|
||||
|
@ -102,7 +103,7 @@ namespace libzcash {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(Keys, EncodeAndDecodeUnified)
|
||||
TEST(Keys, EncodeAndDecodeUnifiedAddresses)
|
||||
{
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
KeyIO keyIO(Params());
|
||||
|
@ -131,8 +132,7 @@ TEST(Keys, EncodeAndDecodeUnified)
|
|||
if (!test[2].isNull()) {
|
||||
auto data = ParseHex(test[2].get_str());
|
||||
CDataStream ss(
|
||||
reinterpret_cast<const char*>(data.data()),
|
||||
reinterpret_cast<const char*>(data.data() + data.size()),
|
||||
data,
|
||||
SER_NETWORK,
|
||||
PROTOCOL_VERSION);
|
||||
libzcash::SaplingPaymentAddress r;
|
||||
|
@ -164,3 +164,60 @@ TEST(Keys, EncodeAndDecodeUnified)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Keys, EncodeAndDecodeUnifiedFullViewingKeys)
|
||||
{
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
KeyIO keyIO(Params());
|
||||
|
||||
UniValue ua_tests = read_json(MAKE_STRING(json_tests::unified_full_viewing_keys));
|
||||
|
||||
for (size_t idx = 0; idx < ua_tests.size(); idx++) {
|
||||
UniValue test = ua_tests[idx];
|
||||
std::string strTest = test.write();
|
||||
if (test.size() < 1) // Allow for extra stuff (useful for comments)
|
||||
{
|
||||
FAIL() << "Bad test: " << strTest;
|
||||
continue;
|
||||
}
|
||||
if (test.size() == 1) continue; // comment
|
||||
|
||||
libzcash::UnifiedFullViewingKeyBuilder builder;
|
||||
// ["t_key_bytes, sapling_fvk_bytes, orchard_fvk_bytes, unknown_fvk_typecode, unknown_fvk_bytes, unified_fvk"]
|
||||
// These were added to the UA in preference order by the Python test vectors.
|
||||
if (!test[0].isNull()) {
|
||||
auto data = ParseHex(test[0].get_str());
|
||||
ASSERT_EQ(data.size(), 65);
|
||||
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
|
||||
auto decoded = CChainablePubKey::Read(ss);
|
||||
ASSERT_TRUE(builder.AddTransparentKey(decoded));
|
||||
}
|
||||
if (!test[1].isNull()) {
|
||||
auto data = ParseHex(test[1].get_str());
|
||||
ASSERT_EQ(data.size(), 128);
|
||||
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
|
||||
auto key = libzcash::SaplingDiversifiableFullViewingKey::Read(ss);
|
||||
ASSERT_TRUE(builder.AddSaplingKey(key));
|
||||
}
|
||||
|
||||
// Orchard keys and unknown items are not yet supported; instead,
|
||||
// we just test that we're able to parse the unified key string
|
||||
// and that the constituent items match the elements; if no Sapling
|
||||
// key is present then UFVK construction would fail because it might
|
||||
// presume the UFVK to be transparent-only.
|
||||
if (test[1].isNull())
|
||||
continue;
|
||||
|
||||
auto built = builder.build();
|
||||
ASSERT_TRUE(built.has_value());
|
||||
|
||||
auto keystrBytes = ParseHex(test[5].get_str());
|
||||
std::string keystr(keystrBytes.begin(), keystrBytes.end());
|
||||
|
||||
auto decoded = libzcash::UnifiedFullViewingKey::Decode(keystr, Params());
|
||||
ASSERT_TRUE(decoded.has_value());
|
||||
|
||||
EXPECT_EQ(decoded.value().GetTransparentKey(), built.value().GetTransparentKey());
|
||||
EXPECT_EQ(decoded.value().GetSaplingKey(), built.value().GetSaplingKey());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef ZCASH_KEY_CONSTANTS_H
|
||||
#define ZCASH_KEY_CONSTANTS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class KeyConstants
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -190,6 +190,10 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string operator()(const libzcash::UnifiedFullViewingKey& ufvk) const {
|
||||
return ufvk.Encode(keyConstants);
|
||||
}
|
||||
|
||||
std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
|
||||
};
|
||||
|
||||
|
@ -485,6 +489,13 @@ std::string KeyIO::EncodeViewingKey(const libzcash::ViewingKey& vk)
|
|||
|
||||
libzcash::ViewingKey KeyIO::DecodeViewingKey(const std::string& str)
|
||||
{
|
||||
// Try parsing as a Unified full viewing key
|
||||
auto ufvk = libzcash::UnifiedFullViewingKey::Decode(str, keyConstants);
|
||||
if (ufvk.has_value()) {
|
||||
return ufvk.value();
|
||||
}
|
||||
|
||||
// Fall back on trying Sprout or Sapling.
|
||||
return DecodeAny<libzcash::ViewingKey,
|
||||
libzcash::SproutViewingKey,
|
||||
libzcash::SaplingExtendedFullViewingKey>(
|
||||
|
|
|
@ -134,6 +134,14 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
|
|||
return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
|
||||
}
|
||||
|
||||
/* static */ std::optional<CChainablePubKey> CChainablePubKey::FromParts(ChainCode chaincode, CPubKey pubkey) {
|
||||
if (pubkey.IsCompressed()) {
|
||||
return CChainablePubKey(chaincode, pubkey);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ int ECCVerifyHandle::refcount = 0;
|
||||
|
||||
ECCVerifyHandle::ECCVerifyHandle()
|
||||
|
|
49
src/pubkey.h
49
src/pubkey.h
|
@ -203,6 +203,55 @@ public:
|
|||
bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
|
||||
};
|
||||
|
||||
class CChainablePubKey {
|
||||
private:
|
||||
ChainCode chaincode;
|
||||
CPubKey pubkey;
|
||||
|
||||
CChainablePubKey() {}
|
||||
CChainablePubKey(ChainCode chaincode, CPubKey pubkey): chaincode(chaincode), pubkey(pubkey) {}
|
||||
public:
|
||||
static std::optional<CChainablePubKey> FromParts(ChainCode chaincode, CPubKey pubkey);
|
||||
|
||||
const ChainCode& GetChainCode() const {
|
||||
return chaincode;
|
||||
}
|
||||
|
||||
const CPubKey& GetPubKey() const {
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(chaincode);
|
||||
if (ser_action.ForRead()) {
|
||||
std::array<uint8_t, CPubKey::COMPRESSED_PUBLIC_KEY_SIZE> pubkeyBytes;
|
||||
READWRITE(pubkeyBytes);
|
||||
pubkey = CPubKey(pubkeyBytes.begin(), pubkeyBytes.end());
|
||||
assert(pubkey.IsCompressed());
|
||||
} else {
|
||||
assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
|
||||
std::array<uint8_t, CPubKey::COMPRESSED_PUBLIC_KEY_SIZE> pubkeyBytes;
|
||||
std::copy(pubkey.begin(), pubkey.end(), pubkeyBytes.begin());
|
||||
READWRITE(pubkeyBytes);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
static CChainablePubKey Read(Stream& stream) {
|
||||
CChainablePubKey key;
|
||||
stream >> key;
|
||||
return key;
|
||||
}
|
||||
|
||||
friend bool operator==(const CChainablePubKey &a, const CChainablePubKey &b)
|
||||
{
|
||||
return a.chaincode == b.chaincode && a.pubkey == b.pubkey;
|
||||
}
|
||||
};
|
||||
|
||||
struct CExtPubKey {
|
||||
unsigned char nDepth;
|
||||
unsigned char vchFingerprint[4];
|
||||
|
|
|
@ -307,39 +307,47 @@ extern "C" {
|
|||
);
|
||||
|
||||
/**
|
||||
* Derive a PaymentAddress from an ExtendedFullViewingKey. Returns 'false'
|
||||
* if no valid address can be derived for the specified diversifier index.
|
||||
* Derive a PaymentAddress from a (SaplingFullViewingKey, DiversifierKey)
|
||||
* pair. Returns 'false' if no valid address can be derived for the
|
||||
* specified diversifier index.
|
||||
*
|
||||
* Arguments:
|
||||
* - xfvk: [c_uchar; 169] the serialized form of a Sapling extended full viewing key
|
||||
* - j: [c_uchar; 11] the 88-bit diversifier address at which to start searching,
|
||||
* encoded in little-endian order
|
||||
* - addr_ret: [c_uchar; 43] array to which the returned address will be written,
|
||||
* if the specified diversifier index `j` produces a valid address.
|
||||
* - fvk: [c_uchar; 96] the serialized form of a Sapling full viewing key
|
||||
* - dk: [c_uchar; 32] the byte representation of a Sapling diversifier key
|
||||
* - j: [c_uchar; 11] the 88-bit diversifier index, encoded in little-endian
|
||||
* order
|
||||
* - addr_ret: [c_uchar; 43] array to which the returned address will be
|
||||
* written, if the specified diversifier index `j` produces a valid
|
||||
* address.
|
||||
*/
|
||||
bool librustzcash_zip32_xfvk_address(
|
||||
const unsigned char *xfvk,
|
||||
bool librustzcash_zip32_sapling_address(
|
||||
const unsigned char *fvk,
|
||||
const unsigned char *dk,
|
||||
const unsigned char *j,
|
||||
unsigned char *addr_ret
|
||||
);
|
||||
|
||||
/**
|
||||
* Derive a PaymentAddress from an ExtendedFullViewingKey by searching the
|
||||
* space of valid diversifiers starting at diversifier index `j`. This will
|
||||
* always return a valid address along with the diversifier index that produced
|
||||
* the address unless no addresses can be derived at any diversifier index >= `j`,
|
||||
* in which case this function will return `false`.
|
||||
* Derive a PaymentAddress from a (SaplingFullViewingKey, DiversifierKey)
|
||||
* pair by searching the space of valid diversifiers starting at
|
||||
* diversifier index `j`. This will always return a valid address along
|
||||
* with the diversifier index that produced the address unless no addresses
|
||||
* can be derived at any diversifier index >= `j`, in which case this
|
||||
* function will return `false`.
|
||||
*
|
||||
* Arguments:
|
||||
* - xfvk: [c_uchar; 169] the serialized form of a Sapling extended full viewing key
|
||||
* - j: [c_uchar; 11] the 88-bit diversifier address at which to start searching,
|
||||
* encoded in little-endian order
|
||||
* - j_ret: [c_uchar; 11] array that will store the diversifier index at which the
|
||||
* returned address was found
|
||||
* - addr_ret: [c_uchar; 43] array to which the returned address will be written
|
||||
* - fvk: [c_uchar; 96] the serialized form of a Sapling full viewing key
|
||||
* - dk: [c_uchar; 32] the byte representation of a Sapling diversifier key
|
||||
* - j: [c_uchar; 11] the 88-bit diversifier index at which to start
|
||||
* searching, encoded in little-endian order
|
||||
* - j_ret: [c_uchar; 11] array that will store the diversifier index at
|
||||
* which the returned address was found
|
||||
* - addr_ret: [c_uchar; 43] array to which the returned address will be
|
||||
* written
|
||||
*/
|
||||
bool librustzcash_zip32_find_xfvk_address(
|
||||
const unsigned char *xfvk,
|
||||
bool librustzcash_zip32_find_sapling_address(
|
||||
const unsigned char *fvk,
|
||||
const unsigned char *dk,
|
||||
const unsigned char *j,
|
||||
unsigned char *j_ret,
|
||||
unsigned char *addr_ret
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright (c) 2021 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_RUST_INCLUDE_RUST_UNIFIED_KEYS_H
|
||||
#define ZCASH_RUST_INCLUDE_RUST_UNIFIED_KEYS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// Unified full viewing keys
|
||||
//
|
||||
|
||||
/**
|
||||
* Void pointer type representing a reference to a Rust-allocated
|
||||
* unified::Ufvk value
|
||||
*/
|
||||
struct UnifiedFullViewingKeyPtr;
|
||||
typedef struct UnifiedFullViewingKeyPtr UnifiedFullViewingKeyPtr;
|
||||
|
||||
/**
|
||||
* Free the memory allocated for the given address::unified::Ufvk;
|
||||
*/
|
||||
void unified_full_viewing_key_free(UnifiedFullViewingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Clones the given Unified full viewing key and returns
|
||||
* a pointer to the newly created value. Both the original
|
||||
* one's memory and the newly allocated one need to be freed
|
||||
* independently.
|
||||
*/
|
||||
UnifiedFullViewingKeyPtr* unified_full_viewing_key_clone(
|
||||
const UnifiedFullViewingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Parses a unified full viewing key from the given string.
|
||||
*
|
||||
* - If the key does not parse correctly, or the network for which the
|
||||
* key was encoded does not match the specified network the returned
|
||||
* pointer will be null.
|
||||
*/
|
||||
UnifiedFullViewingKeyPtr* unified_full_viewing_key_parse(
|
||||
const char* network,
|
||||
const char* str);
|
||||
|
||||
/**
|
||||
* Serializes a unified full viewing key and returns its string representation.
|
||||
*
|
||||
* The returned string's memory must be freed by the caller using
|
||||
* `zcash_address_string_free`.
|
||||
*/
|
||||
char* unified_full_viewing_key_serialize(
|
||||
const char* network,
|
||||
const UnifiedFullViewingKeyPtr* full_viewing_key);
|
||||
|
||||
/**
|
||||
* Reads the transparent component of a unified full viewing key.
|
||||
*
|
||||
* `tkeyout` must be of length 65.
|
||||
*
|
||||
* Returns `true` if the UFVK contained a transparent component, `false`
|
||||
* otherwise. If this returns `true`, the transparent key will be copied to
|
||||
* `tkeyout` as the byte representation of the `(ChainCode, CPubKey)` pair.
|
||||
* If it returns `false` then `tkeyout` will be unchanged.
|
||||
*/
|
||||
bool unified_full_viewing_key_read_transparent(
|
||||
const UnifiedFullViewingKeyPtr* full_viewing_key,
|
||||
unsigned char* tkeyout);
|
||||
|
||||
/**
|
||||
* Reads the Sapling component of a unified full viewing key.
|
||||
*
|
||||
* `skeyout` must be of length 128.
|
||||
*
|
||||
* Returns `true` if the UFVK contained a Sapling component,
|
||||
* `false` otherwise. The bytes of the `(ak, nk, ovk, dk)` fields
|
||||
* of the viewing key, in the encoding given by `EncodeExtFVKParts`
|
||||
* defined in ZIP 32, will be copied to `skeyout` if `true` is returned.
|
||||
* If `false` is returned then `skeyout` will be unchanged.
|
||||
*/
|
||||
bool unified_full_viewing_key_read_sapling(
|
||||
const UnifiedFullViewingKeyPtr* full_viewing_key,
|
||||
unsigned char* skeyout);
|
||||
|
||||
/**
|
||||
* Constructs a unified full viewing key from the binary encodings
|
||||
* of its constituent parts.
|
||||
*
|
||||
* If `t_key` is not `null`, it must be of length 65 and must be the concatenated
|
||||
* bytes of the serialized `(ChainCode, CPubKey)` pair.
|
||||
*
|
||||
* If `sapling_key` is not `null`, it must be of length 128 and must be the concatenated
|
||||
* bytes of the `(ak, nk, ovk, dk)` fields in the encoding given by
|
||||
* `EncodeExtFVKParts` defined in ZIP 32.
|
||||
*
|
||||
* Returns a pointer to newly allocated UFVK if the operation succeeds,
|
||||
* or the null pointer otherwise. The pointer returned by this function
|
||||
* must be freed by the caller with `unified_full_viewing_key_free`.
|
||||
*/
|
||||
UnifiedFullViewingKeyPtr* unified_full_viewing_key_from_components(
|
||||
const unsigned char* t_key,
|
||||
const unsigned char* sapling_key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZCASH_RUST_INCLUDE_RUST_UNIFIED_KEYS_H
|
||||
|
|
@ -5,7 +5,10 @@ use std::{
|
|||
};
|
||||
|
||||
use libc::{c_char, c_void};
|
||||
use zcash_address::{unified, FromAddress, Network, ToAddress, ZcashAddress};
|
||||
use zcash_address::{
|
||||
unified::{self, Container, Encoding},
|
||||
FromAddress, Network, ToAddress, ZcashAddress,
|
||||
};
|
||||
use zcash_primitives::sapling;
|
||||
|
||||
pub type UnifiedAddressObj = NonNull<c_void>;
|
||||
|
@ -23,7 +26,7 @@ pub type GetReceiverLenCb =
|
|||
pub type GetReceiverDataCb =
|
||||
unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, index: usize, data: *mut u8, length: usize);
|
||||
|
||||
fn network_from_cstr(network: *const c_char) -> Option<Network> {
|
||||
pub(crate) fn network_from_cstr(network: *const c_char) -> Option<Network> {
|
||||
match unsafe { CStr::from_ptr(network) }.to_str().unwrap() {
|
||||
"main" => Some(Network::Main),
|
||||
"test" => Some(Network::Test),
|
||||
|
@ -69,7 +72,7 @@ impl UnifiedAddressHelper {
|
|||
}
|
||||
|
||||
self.ua
|
||||
.receivers()
|
||||
.items()
|
||||
.into_iter()
|
||||
.map(|receiver| match receiver {
|
||||
unified::Receiver::Orchard(data) => {
|
||||
|
@ -209,7 +212,7 @@ pub extern "C" fn zcash_address_serialize_unified(
|
|||
}
|
||||
};
|
||||
|
||||
let ua: unified::Address = match receivers.try_into() {
|
||||
let ua = match unified::Address::try_from_items_preserving_order(receivers) {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => {
|
||||
tracing::error!("{}", e);
|
||||
|
|
|
@ -46,14 +46,15 @@ use zcash_primitives::{
|
|||
block::equihash,
|
||||
constants::{CRH_IVK_PERSONALIZATION, PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
|
||||
merkle_tree::MerklePath,
|
||||
sapling::{merkle_hash, spend_sig},
|
||||
sapling::{
|
||||
keys::FullViewingKey,
|
||||
note_encryption::sapling_ka_agree,
|
||||
redjubjub::{self, Signature},
|
||||
Diversifier, Note, PaymentAddress, ProofGenerationKey, Rseed, ViewingKey,
|
||||
},
|
||||
sapling::{merkle_hash, spend_sig},
|
||||
transaction::components::Amount,
|
||||
zip32,
|
||||
zip32::{self, sapling_address, sapling_find_address},
|
||||
};
|
||||
use zcash_proofs::{
|
||||
circuit::sapling::TREE_DEPTH as SAPLING_TREE_DEPTH,
|
||||
|
@ -74,6 +75,7 @@ mod incremental_merkle_tree_ffi;
|
|||
mod orchard_ffi;
|
||||
mod orchard_keys_ffi;
|
||||
mod transaction_ffi;
|
||||
mod unified_keys_ffi;
|
||||
mod zip339_ffi;
|
||||
|
||||
mod test_harness_ffi;
|
||||
|
@ -1080,16 +1082,17 @@ pub extern "C" fn librustzcash_zip32_xfvk_derive(
|
|||
|
||||
/// Derive a PaymentAddress from an ExtendedFullViewingKey.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn librustzcash_zip32_xfvk_address(
|
||||
xfvk: *const [c_uchar; 169],
|
||||
pub extern "C" fn librustzcash_zip32_sapling_address(
|
||||
fvk: *const [c_uchar; 96],
|
||||
dk: *const [c_uchar; 32],
|
||||
j: *const [c_uchar; 11],
|
||||
addr_ret: *mut [c_uchar; 43],
|
||||
) -> bool {
|
||||
let xfvk = zip32::ExtendedFullViewingKey::read(&unsafe { *xfvk }[..])
|
||||
.expect("valid ExtendedFullViewingKey");
|
||||
let fvk = FullViewingKey::read(&unsafe { *fvk }[..]).expect("valid Sapling FullViewingKey");
|
||||
let dk = zip32::DiversifierKey(unsafe { *dk });
|
||||
let j = zip32::DiversifierIndex(unsafe { *j });
|
||||
|
||||
match xfvk.address(j) {
|
||||
match sapling_address(&fvk, &dk, j) {
|
||||
Some(addr) => {
|
||||
let addr_ret = unsafe { &mut *addr_ret };
|
||||
addr_ret.copy_from_slice(&addr.to_bytes());
|
||||
|
@ -1102,17 +1105,18 @@ pub extern "C" fn librustzcash_zip32_xfvk_address(
|
|||
|
||||
/// Derive a PaymentAddress from an ExtendedFullViewingKey.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn librustzcash_zip32_find_xfvk_address(
|
||||
xfvk: *const [c_uchar; 169],
|
||||
pub extern "C" fn librustzcash_zip32_find_sapling_address(
|
||||
fvk: *const [c_uchar; 96],
|
||||
dk: *const [c_uchar; 32],
|
||||
j: *const [c_uchar; 11],
|
||||
j_ret: *mut [c_uchar; 11],
|
||||
addr_ret: *mut [c_uchar; 43],
|
||||
) -> bool {
|
||||
let xfvk = zip32::ExtendedFullViewingKey::read(&unsafe { *xfvk }[..])
|
||||
.expect("valid ExtendedFullViewingKey");
|
||||
let fvk = FullViewingKey::read(&unsafe { *fvk }[..]).expect("valid Sapling FullViewingKey");
|
||||
let dk = zip32::DiversifierKey(unsafe { *dk });
|
||||
let j = zip32::DiversifierIndex(unsafe { *j });
|
||||
|
||||
match xfvk.find_address(j) {
|
||||
match sapling_find_address(&fvk, &dk, j) {
|
||||
Some((j, addr)) => {
|
||||
let j_ret = unsafe { &mut *j_ret };
|
||||
let addr_ret = unsafe { &mut *addr_ret };
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
use libc::c_char;
|
||||
use std::ffi::{CStr, CString};
|
||||
use tracing::error;
|
||||
|
||||
use zcash_address::unified::{Container, Encoding, Fvk, Ufvk};
|
||||
|
||||
use crate::address_ffi::network_from_cstr;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_free(key: *mut Ufvk) {
|
||||
if !key.is_null() {
|
||||
drop(unsafe { Box::from_raw(key) });
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_clone(key: *const Ufvk) -> *mut Ufvk {
|
||||
unsafe { key.as_ref() }
|
||||
.map(|key| Box::into_raw(Box::new(key.clone())))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_parse(
|
||||
network: *const c_char,
|
||||
encoded: *const c_char,
|
||||
) -> *mut Ufvk {
|
||||
let network = match network_from_cstr(network) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
};
|
||||
|
||||
match unsafe { CStr::from_ptr(encoded) }.to_str() {
|
||||
Ok(encoded) => match Ufvk::decode(encoded) {
|
||||
Ok((parsed_network, fvk)) if parsed_network == network => Box::into_raw(Box::new(fvk)),
|
||||
Ok((parsed_network, _)) => {
|
||||
error!(
|
||||
"Key was encoded for a different network ({:?}) than what was requested ({:?})",
|
||||
parsed_network, network,
|
||||
);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failure decoding unified full viewing key: {}", e);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Failure reading bytes of unified full viewing key: {}", e);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_serialize(
|
||||
network: *const c_char,
|
||||
key: *const Ufvk,
|
||||
) -> *mut c_char {
|
||||
let key = unsafe { key.as_ref() }.expect("Unified full viewing key pointer may not be null.");
|
||||
match network_from_cstr(network) {
|
||||
Some(n) => CString::new(key.encode(&n)).unwrap().into_raw(),
|
||||
None => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_read_transparent(
|
||||
key: *const Ufvk,
|
||||
out: *mut [u8; 65],
|
||||
) -> bool {
|
||||
let key = unsafe { key.as_ref() }.expect("Unified full viewing key pointer may not be null.");
|
||||
let out = unsafe { &mut *out };
|
||||
|
||||
for r in &key.items() {
|
||||
if let Fvk::P2pkh(data) = r {
|
||||
*out = *data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_read_sapling(
|
||||
key: *const Ufvk,
|
||||
out: *mut [u8; 128],
|
||||
) -> bool {
|
||||
let key = unsafe { key.as_ref() }.expect("Unified full viewing key pointer may not be null.");
|
||||
let out = unsafe { &mut *out };
|
||||
|
||||
for r in &key.items() {
|
||||
if let Fvk::Sapling(data) = r {
|
||||
*out = *data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unified_full_viewing_key_from_components(
|
||||
t_key: *const [u8; 65],
|
||||
sapling_key: *const [u8; 128],
|
||||
) -> *mut Ufvk {
|
||||
let t_key = unsafe { t_key.as_ref() };
|
||||
let sapling_key = unsafe { sapling_key.as_ref() };
|
||||
|
||||
let mut items = vec![];
|
||||
if let Some(t_bytes) = t_key {
|
||||
items.push(Fvk::P2pkh(*t_bytes));
|
||||
}
|
||||
if let Some(sapling_bytes) = sapling_key {
|
||||
items.push(Fvk::Sapling(*sapling_bytes));
|
||||
}
|
||||
|
||||
match Ufvk::try_from_items(items) {
|
||||
Ok(ufvk) => Box::into_raw(Box::new(ufvk)),
|
||||
Err(e) => {
|
||||
error!(
|
||||
"An error occurred constructing the unified full viewing key: {:?}",
|
||||
e
|
||||
);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/unified_full_viewing_keys.py"],
|
||||
["t_key_bytes, sapling_fvk_bytes, orchard_fvk_bytes, unknown_fvk_typecode, unknown_fvk_bytes, unified_fvk"],
|
||||
[null, "cfb835e7c05c80c2a15a58702bc529a44e1a815ef79124f23709214cf0167ac4e6340b493dca8e4bee114259dc35edc4c296ffd53869885531d1bdb27008bbcd6fec092ad5c4d1f68819f41ae447db96df4a5f110018f47060916ec54884f1cc27a0d4c0bca90984cdf39fb4cc61ceee78ddaa2a45af871f49f04e98b02fb16b", null, 65535, null, "757669657731747878783339707833736a676478796c6d6636666876706e6878667966717376756e3863737330723678717830726b3974767a3076727a74756a74683474716e7534367877657035367279396a643537687972726c36757467657a356a717232716466737a79787265686b64686774757964376d78756e6e6133327732356d396b7771387163687377673476686632796d736b376c6e7637786a3864356b347a7272343370756e746b6d666b396e346a636b66763237677063376e747765726c6c756439307a346c356c71786a68366333356b376135786c6d663563726467677537366c307572657475787333386839"],
|
||||
[null, "04da0d94cb0a6397067a81a88ef422e56678e0ba232eb4dd6b05b98bc5e3461cd4a52b366a7df1f3a871854bfe1492711dc5130b35441748caa2742959279ce31e2b3604995d4ccedc4618ad16cdd2c0d42a6d36fb3a0610054cedef30beca20d187f32ce02f8ca357b575e705cda7ef8e1c68b9110381bd3958e0659a084205", "9bf5e479a60cfa3893a2a7693488b3fa016402851263e63c48540b3daff13814cd71a2ab1f78c561c768a3641dcf7a7d6b473393a629841c81f93afa87689035a119c9f7dac6fb9e7cf8fd6aa40f5f7f9e75b161d5f7269d28a4211ab84a8408", 65532, null, "75766965773135797678377477766a376a726a67766d6e6c797474683632396e7861746c7837686e79727a707a3468337a74776a79786c7733793770657a737671397276643470726779326474726a6c736d6c326c76366c6a7575306a7274766b6d6d366c6a32793768706c70686b383978656b66636565687a637a6777773237756538763272376e3077727339636b78376134756c6365766b777830363077667139613379357932746d337132777163756c796d3232396668387474386a6d376c683863367639707a67613274396e6c78673630377478353673303775757177337673336d78663676716b68353071636a33677678347664367a367379356e3039387565636c396a707968737178333934677337323539786b33796c376764326e333370767371707979377064393734347271786e73343073327a323963796b3435766a763765756b713976777a3879306163383539707a7166386b6d6c6b767678723930716b326e30376c6e7264393061363467376b6472336366356a637665726c7173667134366e6e71777137386b68"],
|
||||
["546c1fe01f7e9c8e36d6a5e29d4e30a73594bf5098421c69378af1e40f64e12503f4e4887b87079d7b7647f01a93a73c7a7d517840575c3246710adbdd752ed2d6", "fc02759ff2853b5e9e15842bef22c76023d43db7c265f120ed175713195f1240f63aee02ec23f146e9e25d25605fbae5472cdedc3b4c31c66b76fe9e6e47eeca79d5fb6a84d152820daaf89e99551d068d99cdf9be065007bc25f245ea62631d17b3bc77f62f35bd4205e6f682b1f9e824ecea53e271b80ff6bc79ef68a20ab5", "c36559ed79d1fecbe1de93d57698e915802f0ccd097adb4e448caef8c48d6c1e439482a1e5636131cba024f891b3bb1dfe333773415eeecf7a42e37dbd934e3a97d92dc90afa0ec3e96eeed9238dfcb6da23799cff14d477368d9ddc330afe39", 65532, null, "757669657731796e727935646c356c676b6733656a61326b386d777779646661357a363465726674657936383365776561326e3068333436636134326e6d7561347170636b63787565707073366e326d656a6c6b64363930333772766d7a61343677306c6d3035676a7070686566756a7a6d6734663876366d7130746b676766376667727138307a6d6d6b756467737739397465687363396d6a65773966367238366b6463646a7a666e66773065326b6d713567646b6866617175797167676b64616d68727a726e6a756663777739386e6577647a7479726d353775757037673338383730703932763776787a727377336c6366797a37616e326473616637757733663672716b32747a6a396c66356371376378346a77767667776a3078787064723433786a6d63646b366b6c6668773379663672617168383676676c61706a636d6b6879776a67366b687161777561667077716a6b776a75756c6a646e756b68646c6b6e726c3878307674727075727335636b7a357734683030397674657165646478786e63666e736c6e6830687074723665766566366e7a393268723838766c616a79366b6378366d306a67613267706b7773736b347277773373766d6e61683437656b64687430713964647467666e7a6736736d6b656c66336a723834707473706c376e37646575397a306d65616b756b336b3867707768703532"],
|
||||
[null, null, "13a3e9649004641d3fc4da1cdefc4c5c6c457b0aee6e668d1d57a58bc48b0e1501a9e2572d16a3cb72c7b539582a46d8f67823da02235d41d49c12788bceeb334500fef8adfc1bcbaa0eede5b48ea7d3e9ec2a774986aac43050c50aa24f1d0f", 65533, null, "757669657731686d3672366e6434747463707137786e326a307367796a336d63726e6633336b796b3574797271666c70663774327266336a6c6530713839616a6870327764746164397533646e76356b6c746171767576647a6c7770397679726378666535676b763078646a6578326e68707839336e65367876307770386130676c6e36746a6b76796b7174686166726e686e6b6633676138656a766676717636386735633974386a75656e7a6833396766776a64637238786d7476677937656d7465"],
|
||||
[null, null, "33ca395730a107b148032a999349f6dc9983daab9d01ffb1180b56ba7038221d1bf174c534ae1adb7a61a30ad0e3b36c52cf90957491ed84f90b5bd42c76833ef0cf897fe579461bc8db0b37e2da35766f2ee00712416c87f0a679fc55d4791f", 65531, null, "7576696577316478386a3774756b7473686678737930336167706a68633878326d716137343338353861343274736c327335786b78647a706534617664677363647978366163676c35736c656a3978616e33307479616735707333706a6a7375677075307276343237656b6c336c78616c6738637378726568667670717635306672617772687868716b38766a387975353270336875333872786c3772726e6c766a663374776b7467336b67323667656765636d30786873726d673671667036327563"],
|
||||
["9db6990ed83dd64af3597c04323ea51b0052ad8084a8b9da948d320dadd64f540215761b6d5155ba66df44f224e914e4a8bb6f2fee6820a865ac9fbfb327c11507", null, "a71cccc7d3f4fd389ba45bc4dc4e9b3d91d1fdc70eb15ab92aced578409e272f15181f6ae4b8412caf1044dab7749111cdba8c43a4ffad1de39bb22d2dd150077e9343b886179115512836623a664e3125d2faf44a1308e3dbd525da73e46523", 65534, null, "75766965773166326d6d6a783867786e376a716a796a397872776c6b32656d61617770393561326e716a3366373574766b37737a766d6430686e6d7a6d79637732336773343870646a37676d326c36637573763464733935666d656d723972723966787838333370776a63336c7a353330376c787a7632366630757132756b70776167717730786c7a6a746838386476776536616a3339686d6e7661307561716b6a656c73373268386563757539753273636c30756c373239687a397437793537656b617978777375326638366164306c3536727237653374353378736333787333347075766167667564787734766a377039336c346377303232747238706b746567716d386e32737835687061747a3776357130636d3865767032356d77776b6767657568677366737a357078"],
|
||||
["1ebd931de518856878f73476f21a482ec9378365c8f7393c94e2885315eb4671021c3e1aa400191c4609ba93df32612f46dfa68aebcfb80778b7fb59bb563e0a7a", null, "3d301cbf5f38ad466992b6466c3377d9f314e6e0e456cd8879f9f9a2db838232c3c801b93141a1ddc29f1079a9b3b46126ed23aeabc4007912798cadf9cfc00e800540cf11186e253036ae5a53f875c50a4a7940021523a92d8b359c140acb31", 65534, null, "7576696577317237386b6434393237373270396371646165336a396a6a647572637a76357a75633632706b366b3371756674776339396735666c7a6366356470737a676b6d6574307a6533726d38746c33356d63647a686564616a74386e7a397877377676656c673275397137756a373876736372666d383466703937633770753867326e78376a3476346c3966633530637671756b396d37673536306d386e3468707972726e6c6a39726b377537726d657578303265723876727a727167326136767535766b786d6b66753368326834666b30777a336c337735657173676c393374777037616d6d3936726b6b30356d6e326b7970677a3863636e6c3778786e3973616b35787a6c65617072736c3630653573323870346e796875356b6a32776b35726c6676766e3434396d35"],
|
||||
["26c1039586a7afcf4a0d9c731e985d99589c8bb838e8aaf745533ed9e8ae3a1c02ca6a53e13c134c1fb70013b1c3c7f59788b28df32fac5c220f565bd926dca633", null, "ffdffc7112cf550135fa5476272b24289fcabc5401b16db739d1df8f4493f1143c3cc90b837152144de475182209b0c169559f4a91fb788403b3b7642cc99c0d519abc658bfae98e12c9878d9e16c22937cc8182ebac54f15e307a2e639da239", 65535, null, "75766965773139706d666b617678647639777a6867766670653070753678727366373967616e613832396c3277667537713833336e63667a71657732656c637579643674757139683770656472397871763068713461637768396e647332776436677474357633776530777964336374736463336866676b7968637779776d753733323076666b30636b6e70326e65706a64686d756b3375746365613267796d78306630327a6d6c61386a706137656c6d7768796b7434637371333739717a356133386579346b79353077373064353330797a6a6d686c7473637a32673832766a7479616b65737366323776397177736b79713734786c6a63333530663767793036306a686b6c673871727671746535656c6d637374336e6b30766b6d6c6e6d6d7437367337657363656a707263"],
|
||||
[null, "deb352b3dfeb09d42a96e77ce38e8a6bd00a1052e565215e1325e0712703368c8dbc0cd5eb82701bbd5903e60d488ef8f8944940ca7d87efbbd6c1eacf9ede8019a3b8fde82c151e11321e54a49aaf6de8b9d6515816a5104fb6ea54ed33873dc4a6ba5a80c1ee0f78378db0052388372aecdde7f53fb35320bec33763ddaa51", "37e5d0367502f509f94f077449cbd07473b9d2b630a5b4f8cefa689543d27028b01e4b736cc5620dc82093b4077b12fab582f225f3a5e58a76921cdad17dd70d458aee1ef78af37e9aadfffbd95db1046ad5b9f29ea4297050cadf9825721632", 65533, "857deecc40a98d5f2935395ee4762dd21afdbb5d47fa9a6dd984d567db2857b927b7fae2db587105415d4642789d38f50b8dbcc129cab3d17d19f3355bcf73cecb8cb8a5da01307152f13936a270572670dc82d39026c6cb4cd4b0f7f5aa2a4f5a", "757669657731756d6b78787175716e7377307a73717a6175327235376d3863706a75363576787865636d6437686c726d677367326c63653932396c6a3563776c636e65707973636577306371353577646d657072767476337a707665356465727976716d726c7035796770346c733264716d796764636738636d6132763878656e6e7a637575326132736c6c7938646c646479757a717573677064736e7a61717933747332736c70746b6d386a737567766a333938766e336b7472643975757167336b3376737a33687a7a6361736c3765646e676868366c78707477746e6468377961616665796c6372353870686b66636635307a6b64666d6b36736133366e36646a687536636e68347278663530766b79396a767663663075707a346479713876367465687732673661616b737730747873336530646b3973763336613371797874356d68636373366768387265336736757633327a3370737879767133617930776e7332616b756666376a333833677130757036706d6e3467366c763937666a646d73397a336735777261383338786668657a776361363574796174333078637933326a76357279356e37613363306d3036713763616e71736e72366133673330716b387265616b717a716d64366b656338667663336d7a6a6e6d39653564376564686a6c36357a67636c743272756e6a34337a6d6d73327665636b7176366e3338716477303863736d7378746b643068796666366a6e3266377732376434726a7168326c7a637638386d30383763393839"],
|
||||
["d715406f2fdd2afa733f5f641c8c21862a1bafce2609d9eecfa158cfb5cd79f803ff3f19851764670df1660c9cb56918abc2a0691eb8b89e705eb8e65b0f4e0dcb", "068d407022db8e5dd0730882bd54851ca0797a00dff60e358d28a04df20793838ba1618a6871da256cdbf7d8ad2ce81d9ce01df64765bc7c14ac74e7ed60129090fcb061b3e672a742aa0f5db728265947355b6375f3d2226b25129dced2e0991d02f739d2d822df5d41edc122b2330916ba36ca09e80cf07f99be4a45fce8e7", "d0e5967a78a4ba305dc8c47ad6ea668d2e88e11575d2ec1f082c740b5fdc050ddb57fa080007c5d868dd8670904b76a82959e8482795ab3ba4cbdc7bb37b1822d2f3ccda83c005fe5c571dbec5074f159f345ad2f60edf8364e4ddf983f91235", 65533, "ad03bc0cda4a44946c00e1b1a1df0e5b87b5bece477a709649e950060591394812951e1fe3895b8cc3d14d2cf6556df6ed4b4ddd3d9a69f53357d7767f4f5ccbdbc596631277f8fecd08cb056b95e3025b9792fff7f244fc716269b926d62e95", "757669657731666b6e393734747468686363306b71796d726a7467637370646c7170613768346e356e7439386b76773761326a676a686174706a713478656a76673879646e747074706e327a6c64707471386371716e646a6c67336c6b786b66776a7635726e39767638636a3666783567307a387a66746e6470726b7073387937656d34737a79327679386a70336832653678386b64717170656e356865387272326466797072767763713563756e7639396c67306a6b397233796c777064617a723779757a357938756a773071366e333939756d643236366a37396a7371776d6c7967767533776e666b797a3335647964687861706c63327578713572613237396e77396e73776379326837676873673930376d70733279686578666876323576776c343461383833376a63777336766365776a7434347a357333336e71756c396d35737a6d6e6179346476763364777568377a796871687732376d753777376a736b30756e6b73787363617a3372616d7973386579667a7a6475636e6765657764357738707433687478666a66786b657a65757130326d6c6333646b636163716b736c716761356b33656c3064746775796771686a3976793572646b70746d7274633432776c3336667676346b6d6b66793735677377776b72796e3835656e6e32396d75396a6c35326e7730717a7967747a366879347a653535756e707071647133346371767237766374777132657a676c716432666b79676161657072746c66376b65707277763871307571383865657771746a756b6c6a3973713933323675717a76786b727837773772716e7a68633361777138367938796a3371386868633472356a6e3864637a7766613934763367307572716173706334727132636878767a3772776e6872683332386168326c6168707776656134747771"]
|
||||
]
|
|
@ -80,7 +80,7 @@ static SaplingPaymentAddress DefaultSaplingAddress(CWallet* pwallet) {
|
|||
|
||||
return usk.value()
|
||||
.ToFullViewingKey()
|
||||
.GetSaplingExtendedFullViewingKey().value()
|
||||
.GetSaplingKey().value()
|
||||
.FindAddress(libzcash::diversifier_index_t(0)).first;
|
||||
}
|
||||
|
||||
|
|
|
@ -5506,6 +5506,10 @@ KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SaplingExtendedFu
|
|||
}
|
||||
}
|
||||
|
||||
KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::UnifiedFullViewingKey& no) const {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unified full viewing key import is not yet supported.");
|
||||
}
|
||||
|
||||
KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid viewing key");
|
||||
}
|
||||
|
|
|
@ -1481,6 +1481,7 @@ public:
|
|||
|
||||
KeyAddResult operator()(const libzcash::SproutViewingKey &sk) const;
|
||||
KeyAddResult operator()(const libzcash::SaplingExtendedFullViewingKey &sk) const;
|
||||
KeyAddResult operator()(const libzcash::UnifiedFullViewingKey &sk) const;
|
||||
KeyAddResult operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "Address.hpp"
|
||||
#include "zcash/address/unified.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <rust/address.h>
|
||||
|
||||
const uint8_t ZCASH_UA_TYPECODE_P2PKH = 0x00;
|
||||
const uint8_t ZCASH_UA_TYPECODE_P2SH = 0x01;
|
||||
|
@ -51,6 +55,14 @@ std::pair<std::string, PaymentAddress> AddressInfoFromViewingKey::operator()(con
|
|||
std::pair<std::string, PaymentAddress> AddressInfoFromViewingKey::operator()(const SaplingExtendedFullViewingKey &xfvk) const {
|
||||
return std::make_pair("sapling", xfvk.DefaultAddress());
|
||||
}
|
||||
std::pair<std::string, PaymentAddress> AddressInfoFromViewingKey::operator()(const UnifiedFullViewingKey &ufvk) const {
|
||||
return std::make_pair(
|
||||
"unified",
|
||||
ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(ufvk)
|
||||
.FindAddress(diversifier_index_t(0))
|
||||
.first
|
||||
);
|
||||
}
|
||||
std::pair<std::string, PaymentAddress> AddressInfoFromViewingKey::operator()(const InvalidEncoding&) const {
|
||||
throw std::invalid_argument("Cannot derive default address from invalid viewing key");
|
||||
}
|
||||
|
@ -176,3 +188,95 @@ std::set<libzcash::RawAddress> GetRawAddresses::operator()(
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<libzcash::UnifiedFullViewingKey> libzcash::UnifiedFullViewingKey::Decode(
|
||||
const std::string& str,
|
||||
const KeyConstants& keyConstants) {
|
||||
UnifiedFullViewingKeyPtr* ptr = unified_full_viewing_key_parse(
|
||||
keyConstants.NetworkIDString().c_str(),
|
||||
str.c_str());
|
||||
if (ptr == nullptr) {
|
||||
return std::nullopt;
|
||||
} else {
|
||||
return UnifiedFullViewingKey(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::string libzcash::UnifiedFullViewingKey::Encode(const KeyConstants& keyConstants) const {
|
||||
auto encoded = unified_full_viewing_key_serialize(
|
||||
keyConstants.NetworkIDString().c_str(),
|
||||
inner.get());
|
||||
// Copy the C-string into C++.
|
||||
std::string res(encoded);
|
||||
// Free the C-string.
|
||||
zcash_address_string_free(encoded);
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<libzcash::SaplingDiversifiableFullViewingKey> libzcash::UnifiedFullViewingKey::GetSaplingKey() const {
|
||||
std::vector<uint8_t> buffer(128);
|
||||
if (unified_full_viewing_key_read_sapling(inner.get(), buffer.data())) {
|
||||
CDataStream ss(buffer, SER_NETWORK, PROTOCOL_VERSION);
|
||||
return SaplingDiversifiableFullViewingKey::Read(ss);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<CChainablePubKey> libzcash::UnifiedFullViewingKey::GetTransparentKey() const {
|
||||
std::vector<uint8_t> buffer(65);
|
||||
if (unified_full_viewing_key_read_transparent(inner.get(), buffer.data())) {
|
||||
CDataStream ss(buffer, SER_NETWORK, PROTOCOL_VERSION);
|
||||
return CChainablePubKey::Read(ss);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
bool libzcash::UnifiedFullViewingKeyBuilder::AddTransparentKey(const CChainablePubKey& key) {
|
||||
if (t_bytes.has_value()) return false;
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << key;
|
||||
assert(ss.size() == 65);
|
||||
std::vector<uint8_t> ss_bytes(ss.begin(), ss.end());
|
||||
t_bytes = ss_bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libzcash::UnifiedFullViewingKeyBuilder::AddSaplingKey(const SaplingDiversifiableFullViewingKey& key) {
|
||||
if (sapling_bytes.has_value()) return false;
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << key;
|
||||
assert(ss.size() == 128);
|
||||
std::vector<uint8_t> ss_bytes(ss.begin(), ss.end());
|
||||
sapling_bytes = ss_bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<libzcash::UnifiedFullViewingKey> libzcash::UnifiedFullViewingKeyBuilder::build() const {
|
||||
UnifiedFullViewingKeyPtr* ptr = unified_full_viewing_key_from_components(
|
||||
t_bytes.has_value() ? t_bytes.value().data() : nullptr,
|
||||
sapling_bytes.has_value() ? sapling_bytes.value().data() : nullptr);
|
||||
|
||||
if (ptr == nullptr) {
|
||||
return std::nullopt;
|
||||
} else {
|
||||
return UnifiedFullViewingKey(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
libzcash::UnifiedFullViewingKey libzcash::UnifiedFullViewingKey::FromZcashdUFVK(const ZcashdUnifiedFullViewingKey& key) {
|
||||
UnifiedFullViewingKeyBuilder builder;
|
||||
if (key.GetTransparentKey().has_value()) {
|
||||
builder.AddTransparentKey(key.GetTransparentKey().value());
|
||||
}
|
||||
if (key.GetSaplingKey().has_value()) {
|
||||
builder.AddSaplingKey(key.GetSaplingKey().value());
|
||||
}
|
||||
|
||||
auto result = builder.build();
|
||||
if (!result.has_value()) {
|
||||
throw std::invalid_argument("Cannot convert from invalid viewing key.");
|
||||
}
|
||||
return result.value();
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
#ifndef ZC_ADDRESS_H_
|
||||
#define ZC_ADDRESS_H_
|
||||
|
||||
#include "uint256.h"
|
||||
#include "key_constants.h"
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "uint256.h"
|
||||
#include "zcash/address/orchard.hpp"
|
||||
#include "zcash/address/sapling.hpp"
|
||||
#include "zcash/address/sprout.hpp"
|
||||
#include "zcash/address/unified.h"
|
||||
#include "zcash/address/zip32.h"
|
||||
|
||||
#include <variant>
|
||||
#include <rust/unified_keys.h>
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
|
@ -127,14 +130,95 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class UnifiedFullViewingKeyBuilder;
|
||||
|
||||
/**
|
||||
* Wrapper for a zcash_address::unified::Ufvk.
|
||||
*/
|
||||
class UnifiedFullViewingKey {
|
||||
private:
|
||||
std::unique_ptr<UnifiedFullViewingKeyPtr, decltype(&unified_full_viewing_key_free)> inner;
|
||||
|
||||
UnifiedFullViewingKey() :
|
||||
inner(nullptr, unified_full_viewing_key_free) {}
|
||||
|
||||
UnifiedFullViewingKey(UnifiedFullViewingKeyPtr* ptr) :
|
||||
inner(ptr, unified_full_viewing_key_free) {}
|
||||
|
||||
friend class UnifiedFullViewingKeyBuilder;
|
||||
public:
|
||||
static std::optional<UnifiedFullViewingKey> Decode(
|
||||
const std::string& str,
|
||||
const KeyConstants& keyConstants);
|
||||
|
||||
/**
|
||||
* This method should only be used for serialization of unified full
|
||||
* viewing keys that have been generated internally from unified spending
|
||||
* keys by Zcashd. It is not suitable for use in any case where the
|
||||
* ZcashdUnifiedFullViewingKey value may have been produced by a
|
||||
* potentially-lossy conversion from a UnifiedFullViewingKey value that
|
||||
* originated outside of zcashd.
|
||||
*/
|
||||
static UnifiedFullViewingKey FromZcashdUFVK(const ZcashdUnifiedFullViewingKey&);
|
||||
|
||||
std::string Encode(const KeyConstants& keyConstants) const;
|
||||
|
||||
std::optional<SaplingDiversifiableFullViewingKey> GetSaplingKey() const;
|
||||
|
||||
std::optional<CChainablePubKey> GetTransparentKey() const;
|
||||
|
||||
UnifiedFullViewingKey(UnifiedFullViewingKey&& key) : inner(std::move(key.inner)) {}
|
||||
|
||||
UnifiedFullViewingKey(const UnifiedFullViewingKey& key) :
|
||||
inner(unified_full_viewing_key_clone(key.inner.get()), unified_full_viewing_key_free) {}
|
||||
|
||||
UnifiedFullViewingKey& operator=(UnifiedFullViewingKey&& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner = std::move(key.inner);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnifiedFullViewingKey& operator=(const UnifiedFullViewingKey& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner.reset(unified_full_viewing_key_clone(key.inner.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class UnifiedFullViewingKeyBuilder {
|
||||
private:
|
||||
std::optional<std::vector<uint8_t>> t_bytes;
|
||||
std::optional<std::vector<uint8_t>> sapling_bytes;
|
||||
public:
|
||||
UnifiedFullViewingKeyBuilder(): t_bytes(std::nullopt), sapling_bytes(std::nullopt) {}
|
||||
|
||||
bool AddTransparentKey(const CChainablePubKey&);
|
||||
bool AddSaplingKey(const SaplingDiversifiableFullViewingKey&);
|
||||
|
||||
std::optional<UnifiedFullViewingKey> build() const;
|
||||
};
|
||||
|
||||
/** Addresses that can appear in a string encoding. */
|
||||
typedef std::variant<
|
||||
InvalidEncoding,
|
||||
SproutPaymentAddress,
|
||||
SaplingPaymentAddress,
|
||||
UnifiedAddress> PaymentAddress;
|
||||
typedef std::variant<InvalidEncoding, SproutViewingKey, SaplingExtendedFullViewingKey> ViewingKey;
|
||||
typedef std::variant<InvalidEncoding, SproutSpendingKey, SaplingExtendedSpendingKey> SpendingKey;
|
||||
/** Viewing keys that can have a string encoding. */
|
||||
typedef std::variant<
|
||||
InvalidEncoding,
|
||||
SproutViewingKey,
|
||||
SaplingExtendedFullViewingKey,
|
||||
UnifiedFullViewingKey> ViewingKey;
|
||||
/** Spending keys that can have a string encoding. */
|
||||
typedef std::variant<
|
||||
InvalidEncoding,
|
||||
SproutSpendingKey,
|
||||
SaplingExtendedSpendingKey> SpendingKey;
|
||||
|
||||
class AddressInfoFromSpendingKey {
|
||||
public:
|
||||
|
@ -147,10 +231,11 @@ class AddressInfoFromViewingKey {
|
|||
public:
|
||||
std::pair<std::string, PaymentAddress> operator()(const SproutViewingKey&) const;
|
||||
std::pair<std::string, PaymentAddress> operator()(const struct SaplingExtendedFullViewingKey&) const;
|
||||
std::pair<std::string, PaymentAddress> operator()(const UnifiedFullViewingKey&) const;
|
||||
std::pair<std::string, PaymentAddress> operator()(const InvalidEncoding&) const;
|
||||
};
|
||||
|
||||
}
|
||||
} //namespace libzcash
|
||||
|
||||
/** Check whether a PaymentAddress is not an InvalidEncoding. */
|
||||
bool IsValidPaymentAddress(const libzcash::PaymentAddress& zaddr);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#include "zcash/Address.hpp"
|
||||
#include "unified.h"
|
||||
#include "bip44.h"
|
||||
|
||||
|
@ -29,7 +30,11 @@ ZcashdUnifiedFullViewingKey ZcashdUnifiedSpendingKey::ToFullViewingKey() const {
|
|||
ZcashdUnifiedFullViewingKey ufvk;
|
||||
|
||||
if (transparentKey.has_value()) {
|
||||
ufvk.transparentKey = transparentKey.value().Neuter();
|
||||
auto extPubKey = transparentKey.value().Neuter();
|
||||
|
||||
// TODO: how to ensure that the pubkey is in its compressed representation?
|
||||
// Is that already guaranteed?
|
||||
ufvk.transparentKey = CChainablePubKey::FromParts(extPubKey.chaincode, extPubKey.pubkey).value();
|
||||
}
|
||||
|
||||
if (saplingKey.has_value()) {
|
||||
|
@ -39,6 +44,23 @@ ZcashdUnifiedFullViewingKey ZcashdUnifiedSpendingKey::ToFullViewingKey() const {
|
|||
return ufvk;
|
||||
}
|
||||
|
||||
ZcashdUnifiedFullViewingKey ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(
|
||||
const UnifiedFullViewingKey& ufvk) {
|
||||
ZcashdUnifiedFullViewingKey result;
|
||||
|
||||
auto transparentKey = ufvk.GetTransparentKey();
|
||||
if (transparentKey.has_value()) {
|
||||
result.transparentKey = transparentKey.value();
|
||||
}
|
||||
|
||||
auto saplingKey = ufvk.GetSaplingKey();
|
||||
if (saplingKey.has_value()) {
|
||||
result.saplingKey = saplingKey.value();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<UnifiedAddress> ZcashdUnifiedFullViewingKey::Address(diversifier_index_t j) const {
|
||||
UnifiedAddress ua;
|
||||
|
||||
|
@ -52,17 +74,20 @@ std::optional<UnifiedAddress> ZcashdUnifiedFullViewingKey::Address(diversifier_i
|
|||
}
|
||||
|
||||
if (transparentKey.has_value()) {
|
||||
const auto& tkey = transparentKey.value();
|
||||
auto childIndex = j.ToTransparentChildIndex();
|
||||
if (!childIndex.has_value()) return std::nullopt;
|
||||
|
||||
CExtPubKey externalKey;
|
||||
if (!transparentKey.value().Derive(externalKey, 0)) {
|
||||
CPubKey externalKey;
|
||||
ChainCode externalChainCode;
|
||||
if (!tkey.GetPubKey().Derive(externalKey, externalChainCode, 0, tkey.GetChainCode())) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
CExtPubKey childKey;
|
||||
if (externalKey.Derive(childKey, childIndex.value())) {
|
||||
ua.AddReceiver(childKey.pubkey.GetID());
|
||||
CPubKey childKey;
|
||||
ChainCode childChainCode;
|
||||
if (externalKey.Derive(childKey, childChainCode, childIndex.value(), externalChainCode)) {
|
||||
ua.AddReceiver(childKey.GetID());
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -71,3 +96,13 @@ std::optional<UnifiedAddress> ZcashdUnifiedFullViewingKey::Address(diversifier_i
|
|||
return ua;
|
||||
}
|
||||
|
||||
std::pair<UnifiedAddress, diversifier_index_t> ZcashdUnifiedFullViewingKey::FindAddress(diversifier_index_t j) const {
|
||||
auto addr = Address(j);
|
||||
while (!addr.has_value()) {
|
||||
if (!j.increment())
|
||||
throw std::runtime_error(std::string(__func__) + ": diversifier index overflow.");;
|
||||
addr = Address(j);
|
||||
}
|
||||
return std::make_pair(addr.value(), j);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,43 +7,52 @@
|
|||
|
||||
#include "zip32.h"
|
||||
#include "bip44.h"
|
||||
#include "zcash/Address.hpp"
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
class ZcashdUnifiedSpendingKey;
|
||||
class ZcashdUnifiedFullViewingKey;
|
||||
|
||||
// prototypes for the classes handling ZIP-316 encoding (in Address.hpp)
|
||||
class UnifiedAddress;
|
||||
class UnifiedFullViewingKey;
|
||||
|
||||
/**
|
||||
* An internal-only type for unified full viewing keys that represents only the
|
||||
* set of receiver types that are supported by zcashd. This type does not
|
||||
* support round-trip serialization to and from the UnifiedFullViewingKey type,
|
||||
* which should be used in most cases.
|
||||
*/
|
||||
class ZcashdUnifiedFullViewingKey {
|
||||
private:
|
||||
std::optional<CExtPubKey> transparentKey;
|
||||
std::optional<SaplingExtendedFullViewingKey> saplingKey;
|
||||
std::optional<CChainablePubKey> transparentKey;
|
||||
std::optional<SaplingDiversifiableFullViewingKey> saplingKey;
|
||||
|
||||
ZcashdUnifiedFullViewingKey() {}
|
||||
|
||||
friend class ZcashdUnifiedSpendingKey;
|
||||
public:
|
||||
const std::optional<CExtPubKey>& GetTransparentKey() const {
|
||||
/**
|
||||
* This constructor is lossy, and does not support round-trip transformations.
|
||||
*/
|
||||
static ZcashdUnifiedFullViewingKey FromUnifiedFullViewingKey(const UnifiedFullViewingKey& ufvk);
|
||||
|
||||
const std::optional<CChainablePubKey>& GetTransparentKey() const {
|
||||
return transparentKey;
|
||||
}
|
||||
|
||||
const std::optional<SaplingExtendedFullViewingKey>& GetSaplingExtendedFullViewingKey() const {
|
||||
const std::optional<SaplingDiversifiableFullViewingKey>& GetSaplingKey() const {
|
||||
return saplingKey;
|
||||
}
|
||||
|
||||
std::optional<UnifiedAddress> Address(diversifier_index_t j) const;
|
||||
|
||||
std::pair<UnifiedAddress, diversifier_index_t> FindAddress(diversifier_index_t j) const {
|
||||
auto addr = Address(j);
|
||||
while (!addr.has_value()) {
|
||||
if (!j.increment())
|
||||
throw std::runtime_error(std::string(__func__) + ": diversifier index overflow.");;
|
||||
addr = Address(j);
|
||||
}
|
||||
return std::make_pair(addr.value(), j);
|
||||
}
|
||||
std::pair<UnifiedAddress, diversifier_index_t> FindAddress(diversifier_index_t j) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of unified spending keys supported by zcashd.
|
||||
*/
|
||||
class ZcashdUnifiedSpendingKey {
|
||||
private:
|
||||
libzcash::AccountId accountId;
|
||||
|
|
|
@ -83,15 +83,16 @@ std::optional<SaplingExtendedFullViewingKey> SaplingExtendedFullViewingKey::Deri
|
|||
}
|
||||
|
||||
std::optional<libzcash::SaplingPaymentAddress>
|
||||
SaplingExtendedFullViewingKey::Address(diversifier_index_t j) const
|
||||
SaplingDiversifiableFullViewingKey::Address(diversifier_index_t j) const
|
||||
{
|
||||
CDataStream ss_xfvk(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss_xfvk << *this;
|
||||
CSerializeData xfvk_bytes(ss_xfvk.begin(), ss_xfvk.end());
|
||||
CDataStream ss_fvk(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss_fvk << fvk;
|
||||
CSerializeData fvk_bytes(ss_fvk.begin(), ss_fvk.end());
|
||||
|
||||
CSerializeData addr_bytes(libzcash::SerializedSaplingPaymentAddressSize);
|
||||
if (librustzcash_zip32_xfvk_address(
|
||||
reinterpret_cast<unsigned char*>(xfvk_bytes.data()),
|
||||
if (librustzcash_zip32_sapling_address(
|
||||
reinterpret_cast<unsigned char*>(fvk_bytes.data()),
|
||||
dk.begin(),
|
||||
j.begin(),
|
||||
reinterpret_cast<unsigned char*>(addr_bytes.data()))) {
|
||||
CDataStream ss_addr(addr_bytes, SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -103,17 +104,18 @@ std::optional<libzcash::SaplingPaymentAddress>
|
|||
}
|
||||
}
|
||||
|
||||
libzcash::SaplingPaymentAddress SaplingExtendedFullViewingKey::DefaultAddress() const
|
||||
libzcash::SaplingPaymentAddress SaplingDiversifiableFullViewingKey::DefaultAddress() const
|
||||
{
|
||||
CDataStream ss_xfvk(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss_xfvk << *this;
|
||||
CSerializeData xfvk_bytes(ss_xfvk.begin(), ss_xfvk.end());
|
||||
CDataStream ss_fvk(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss_fvk << fvk;
|
||||
CSerializeData fvk_bytes(ss_fvk.begin(), ss_fvk.end());
|
||||
|
||||
diversifier_index_t j_default;
|
||||
diversifier_index_t j_ret;
|
||||
CSerializeData addr_bytes_ret(libzcash::SerializedSaplingPaymentAddressSize);
|
||||
if (librustzcash_zip32_find_xfvk_address(
|
||||
reinterpret_cast<unsigned char*>(xfvk_bytes.data()),
|
||||
if (librustzcash_zip32_find_sapling_address(
|
||||
reinterpret_cast<unsigned char*>(fvk_bytes.data()),
|
||||
dk.begin(),
|
||||
j_default.begin(), j_ret.begin(),
|
||||
reinterpret_cast<unsigned char*>(addr_bytes_ret.data()))) {
|
||||
CDataStream ss_addr(addr_bytes_ret, SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -122,7 +124,7 @@ libzcash::SaplingPaymentAddress SaplingExtendedFullViewingKey::DefaultAddress()
|
|||
return addr;
|
||||
} else {
|
||||
// If we can't obtain a default address, we are *very* unlucky...
|
||||
throw std::runtime_error("SaplingExtendedFullViewingKey::DefaultAddress(): No valid diversifiers out of 2^88!");
|
||||
throw std::runtime_error("SaplingDiversifiableFullViewingKey::DefaultAddress(): No valid diversifiers out of 2^88!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,28 +117,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct SaplingExtendedFullViewingKey {
|
||||
uint8_t depth;
|
||||
uint32_t parentFVKTag;
|
||||
uint32_t childIndex;
|
||||
uint256 chaincode;
|
||||
class SaplingDiversifiableFullViewingKey {
|
||||
public:
|
||||
libzcash::SaplingFullViewingKey fvk;
|
||||
uint256 dk;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(depth);
|
||||
READWRITE(parentFVKTag);
|
||||
READWRITE(childIndex);
|
||||
READWRITE(chaincode);
|
||||
READWRITE(fvk);
|
||||
READWRITE(dk);
|
||||
}
|
||||
|
||||
std::optional<SaplingExtendedFullViewingKey> Derive(uint32_t i) const;
|
||||
|
||||
// Attempts to construct a valid payment address with diversifier index
|
||||
// `j`; returns std::nullopt if `j` does not result in a valid diversifier
|
||||
// given this xfvk.
|
||||
|
@ -159,6 +142,48 @@ struct SaplingExtendedFullViewingKey {
|
|||
|
||||
libzcash::SaplingPaymentAddress DefaultAddress() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(fvk);
|
||||
READWRITE(dk);
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
static SaplingDiversifiableFullViewingKey Read(Stream& stream) {
|
||||
SaplingDiversifiableFullViewingKey key;
|
||||
stream >> key;
|
||||
return key;
|
||||
}
|
||||
|
||||
friend inline bool operator==(const SaplingDiversifiableFullViewingKey& a, const SaplingDiversifiableFullViewingKey& b) {
|
||||
return (a.fvk == b.fvk && a.dk == b.dk);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class SaplingExtendedFullViewingKey: public SaplingDiversifiableFullViewingKey {
|
||||
public:
|
||||
uint8_t depth;
|
||||
uint32_t parentFVKTag;
|
||||
uint32_t childIndex;
|
||||
uint256 chaincode;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(depth);
|
||||
READWRITE(parentFVKTag);
|
||||
READWRITE(childIndex);
|
||||
READWRITE(chaincode);
|
||||
READWRITE(fvk);
|
||||
READWRITE(dk);
|
||||
}
|
||||
|
||||
std::optional<SaplingExtendedFullViewingKey> Derive(uint32_t i) const;
|
||||
|
||||
friend inline bool operator==(const SaplingExtendedFullViewingKey& a, const SaplingExtendedFullViewingKey& b) {
|
||||
return (
|
||||
a.depth == b.depth &&
|
||||
|
|
Loading…
Reference in New Issue