Line data Source code
1 : // Copyright (c) 2018-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/zip32.h"
7 :
8 : #include "hash.h"
9 : #include "random.h"
10 : #include "sapling/prf.h"
11 : #include "streams.h"
12 : #include "version.h"
13 :
14 : #include <librustzcash.h>
15 : #include <sodium.h>
16 :
17 : const unsigned char PIVX_HD_SEED_FP_PERSONAL[crypto_generichash_blake2b_PERSONALBYTES] =
18 : {'P', 'I', 'V', 'X', '_', '_', 'H', 'D', '_', 'S', 'e', 'e', 'd', '_', 'F', 'P'};
19 :
20 : const unsigned char PIVX_TADDR_OVK_PERSONAL[crypto_generichash_blake2b_PERSONALBYTES] =
21 : {'P', 'x', 'T', 'a', 'd', 'd', 'r', 'T', 'o', 'S', 'a', 'p', 'l', 'i', 'n', 'g'};
22 :
23 0 : HDSeed HDSeed::Random(size_t len)
24 : {
25 0 : assert(len >= 32);
26 0 : CPrivKey rawSeed(len, 0);
27 0 : GetRandBytes(rawSeed.data(), len);
28 0 : return HDSeed(rawSeed);
29 : }
30 :
31 0 : uint256 HDSeed::Fingerprint() const
32 : {
33 0 : CBLAKE2bWriter h(SER_GETHASH, 0, PIVX_HD_SEED_FP_PERSONAL);
34 0 : h << seed;
35 0 : return h.GetHash();
36 : }
37 :
38 241 : uint256 ovkForShieldingFromTaddr(HDSeed& seed) {
39 241 : auto rawSeed = seed.RawSeed();
40 :
41 : // I = BLAKE2b-512("ZcTaddrToSapling", seed)
42 241 : crypto_generichash_blake2b_state state;
43 241 : assert(crypto_generichash_blake2b_init_salt_personal(
44 : &state,
45 : nullptr, 0, // No key.
46 : 64,
47 : nullptr, // No salt.
48 : PIVX_TADDR_OVK_PERSONAL) == 0);
49 241 : crypto_generichash_blake2b_update(&state, rawSeed.data(), rawSeed.size());
50 241 : auto intermediate = std::array<unsigned char, 64>();
51 241 : crypto_generichash_blake2b_final(&state, intermediate.data(), 64);
52 :
53 : // I_L = I[0..32]
54 241 : uint256 intermediate_L;
55 241 : memcpy(intermediate_L.begin(), intermediate.data(), 32);
56 :
57 : // ovk = truncate_32(PRF^expand(I_L, [0x02]))
58 482 : return PRF_ovk(intermediate_L);
59 : }
60 :
61 : namespace libzcash {
62 :
63 2 : Optional<SaplingExtendedFullViewingKey> SaplingExtendedFullViewingKey::Derive(uint32_t i) const
64 : {
65 4 : CDataStream ss_p(SER_NETWORK, PROTOCOL_VERSION);
66 2 : ss_p << *this;
67 4 : CSerializeData p_bytes(ss_p.begin(), ss_p.end());
68 :
69 4 : CSerializeData i_bytes(ZIP32_XFVK_SIZE);
70 2 : if (librustzcash_zip32_xfvk_derive(
71 2 : reinterpret_cast<unsigned char*>(p_bytes.data()),
72 : i,
73 2 : reinterpret_cast<unsigned char*>(i_bytes.data())
74 : )) {
75 2 : CDataStream ss_i(i_bytes, SER_NETWORK, PROTOCOL_VERSION);
76 1 : SaplingExtendedFullViewingKey xfvk_i;
77 1 : ss_i >> xfvk_i;
78 1 : return xfvk_i;
79 : } else {
80 1 : return nullopt;
81 : }
82 : }
83 :
84 : Optional<std::pair<diversifier_index_t, libzcash::SaplingPaymentAddress>>
85 7816 : SaplingExtendedFullViewingKey::Address(diversifier_index_t j) const
86 : {
87 15632 : CDataStream ss_xfvk(SER_NETWORK, PROTOCOL_VERSION);
88 7816 : ss_xfvk << *this;
89 15632 : CSerializeData xfvk_bytes(ss_xfvk.begin(), ss_xfvk.end());
90 :
91 7816 : diversifier_index_t j_ret;
92 15632 : CSerializeData addr_bytes(libzcash::SerializedSaplingPaymentAddressSize);
93 7816 : if (librustzcash_zip32_xfvk_address(
94 7816 : reinterpret_cast<unsigned char*>(xfvk_bytes.data()),
95 7816 : j.begin(), j_ret.begin(),
96 7816 : reinterpret_cast<unsigned char*>(addr_bytes.data()))) {
97 15632 : CDataStream ss_addr(addr_bytes, SER_NETWORK, PROTOCOL_VERSION);
98 7816 : libzcash::SaplingPaymentAddress addr;
99 7816 : ss_addr >> addr;
100 7816 : return std::make_pair(j_ret, addr);
101 : } else {
102 0 : return nullopt;
103 : }
104 : }
105 :
106 7814 : libzcash::SaplingPaymentAddress SaplingExtendedFullViewingKey::DefaultAddress() const
107 : {
108 7814 : diversifier_index_t j0;
109 15628 : auto addr = Address(j0);
110 : // If we can't obtain a default address, we are *very* unlucky...
111 7814 : if (!addr) {
112 0 : throw std::runtime_error("SaplingExtendedFullViewingKey::DefaultAddress(): No valid diversifiers out of 2^88!");
113 : }
114 7814 : return addr.get().second;
115 : }
116 :
117 1268 : SaplingExtendedSpendingKey SaplingExtendedSpendingKey::Master(const HDSeed& seed)
118 : {
119 1268 : auto rawSeed = seed.RawSeed();
120 2536 : CSerializeData m_bytes(ZIP32_XSK_SIZE);
121 1268 : librustzcash_zip32_xsk_master(
122 1268 : rawSeed.data(),
123 : rawSeed.size(),
124 1268 : reinterpret_cast<unsigned char*>(m_bytes.data()));
125 :
126 2536 : CDataStream ss(m_bytes, SER_NETWORK, PROTOCOL_VERSION);
127 1268 : SaplingExtendedSpendingKey xsk_m;
128 1268 : ss >> xsk_m;
129 2536 : return xsk_m;
130 : }
131 :
132 6741 : SaplingExtendedSpendingKey SaplingExtendedSpendingKey::Derive(uint32_t i) const
133 : {
134 6741 : CDataStream ss_p(SER_NETWORK, PROTOCOL_VERSION);
135 6741 : ss_p << *this;
136 13482 : CSerializeData p_bytes(ss_p.begin(), ss_p.end());
137 :
138 13482 : CSerializeData i_bytes(ZIP32_XSK_SIZE);
139 6741 : librustzcash_zip32_xsk_derive(
140 6741 : reinterpret_cast<unsigned char*>(p_bytes.data()),
141 : i,
142 6741 : reinterpret_cast<unsigned char*>(i_bytes.data()));
143 :
144 13482 : CDataStream ss_i(i_bytes, SER_NETWORK, PROTOCOL_VERSION);
145 6741 : SaplingExtendedSpendingKey xsk_i;
146 6741 : ss_i >> xsk_i;
147 13482 : return xsk_i;
148 : }
149 :
150 11071 : SaplingExtendedFullViewingKey SaplingExtendedSpendingKey::ToXFVK() const
151 : {
152 11071 : SaplingExtendedFullViewingKey ret;
153 11071 : ret.depth = depth;
154 11071 : ret.parentFVKTag = parentFVKTag;
155 11071 : ret.childIndex = childIndex;
156 11071 : ret.chaincode = chaincode;
157 11071 : ret.fvk = expsk.full_viewing_key();
158 11071 : ret.dk = dk;
159 11071 : return ret;
160 : }
161 :
162 5395 : libzcash::SaplingPaymentAddress SaplingExtendedSpendingKey::DefaultAddress() const
163 : {
164 5395 : return ToXFVK().DefaultAddress();
165 : }
166 :
167 : } // End namespace
168 :
169 3941 : bool IsValidSpendingKey(const libzcash::SpendingKey& zkey) {
170 3941 : return zkey.which() != 0;
171 : }
172 :
173 1003 : bool IsValidViewingKey(const libzcash::ViewingKey& vk) {
174 1003 : return vk.which() != 0;
175 : }
|