]> Git Repo - VerusCoin.git/blob - src/key_io.cpp
Set vrsctest rewards to 12 to match mainnet
[VerusCoin.git] / src / key_io.cpp
1 // Copyright (c) 2014-2016 The Bitcoin Core developers
2 // Copyright (c) 2016-2018 The Zcash 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 <key_io.h>
7
8 #include <base58.h>
9 #include <bech32.h>
10 #include <script/script.h>
11 #include <utilstrencodings.h>
12
13 #include <boost/variant/apply_visitor.hpp>
14 #include <boost/variant/static_visitor.hpp>
15
16 #include "pbaas/identity.h"
17 #include "cc/CCinclude.h"
18 #include "boost/algorithm/string.hpp"
19
20 #include <assert.h>
21 #include <string.h>
22 #include <algorithm>
23
24 extern uint160 VERUS_CHAINID;
25 extern std::string VERUS_CHAINNAME;
26
27 CIdentityID VERUS_DEFAULTID;
28 CIdentityID VERUS_NOTARYID;
29 int32_t MAX_OUR_UTXOS_ID_RESCAN = 1000; // this can be set with "-maxourutxosidrescan=n"
30 int32_t MAX_UTXOS_ID_RESCAN = 100;      // this can be set with "-maxutxosidrescan=n"
31 uint160 VERUS_NODEID;
32 bool VERUS_PRIVATECHANGE;
33 std::string VERUS_DEFAULT_ZADDR;
34
35 namespace
36 {
37 class DestinationEncoder : public boost::static_visitor<std::string>
38 {
39 private:
40     const CChainParams& m_params;
41
42 public:
43     DestinationEncoder(const CChainParams& params) : m_params(params) {}
44
45     std::string operator()(const CKeyID& id) const
46     {
47         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
48         data.insert(data.end(), id.begin(), id.end());
49         return EncodeBase58Check(data);
50     }
51
52     std::string operator()(const CPubKey& key) const
53     {
54         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
55         CKeyID id = key.GetID();
56         data.insert(data.end(), id.begin(), id.end());
57         return EncodeBase58Check(data);
58     }
59
60     std::string operator()(const CScriptID& id) const
61     {
62         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
63         data.insert(data.end(), id.begin(), id.end());
64         return EncodeBase58Check(data);
65     }
66
67     std::string operator()(const CIdentityID& id) const
68     {
69         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::IDENTITY_ADDRESS);
70         data.insert(data.end(), id.begin(), id.end());
71         return EncodeBase58Check(data);
72     }
73
74     std::string operator()(const CIndexID& id) const
75     {
76         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::INDEX_ADDRESS);
77         data.insert(data.end(), id.begin(), id.end());
78         return EncodeBase58Check(data);
79     }
80
81     std::string operator()(const CQuantumID& id) const
82     {
83         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::QUANTUM_ADDRESS);
84         data.insert(data.end(), id.begin(), id.end());
85         return EncodeBase58Check(data);
86     }
87
88     std::string operator()(const CNoDestination& no) const { return {}; }
89 };
90
91 class DestinationBytes : public boost::static_visitor<std::vector<unsigned char>>
92 {
93 public:
94     DestinationBytes() {}
95
96     std::vector<unsigned char> operator()(const CKeyID& id) const
97     {
98         return std::vector<unsigned char>(id.begin(), id.end());
99     }
100
101     std::vector<unsigned char> operator()(const CPubKey& key) const
102     {
103         return std::vector<unsigned char>(key.begin(), key.end());
104     }
105
106     std::vector<unsigned char> operator()(const CScriptID& id) const
107     {
108         return std::vector<unsigned char>(id.begin(), id.end());
109     }
110
111     std::vector<unsigned char> operator()(const CIdentityID& id) const
112     {
113         return std::vector<unsigned char>(id.begin(), id.end());
114     }
115
116     std::vector<unsigned char> operator()(const CIndexID& id) const
117     {
118         return std::vector<unsigned char>(id.begin(), id.end());
119     }
120
121     std::vector<unsigned char> operator()(const CQuantumID& id) const
122     {
123         return std::vector<unsigned char>(id.begin(), id.end());
124     }
125
126     std::vector<unsigned char> operator()(const CNoDestination& no) const { return {}; }
127 };
128
129 class DestinationID : public boost::static_visitor<uint160>
130 {
131 public:
132     DestinationID() {}
133
134     uint160 operator()(const CKeyID& id) const
135     {
136         return (uint160)id;
137     }
138
139     uint160 operator()(const CPubKey& key) const
140     {
141         return (uint160)key.GetID();
142     }
143
144     uint160 operator()(const CScriptID& id) const
145     {
146         return (uint160)id;
147     }
148
149     uint160 operator()(const CIdentityID& id) const
150     {
151         return (uint160)id;
152     }
153
154     uint160 operator()(const CIndexID& id) const
155     {
156         return (uint160)id;
157     }
158
159     uint160 operator()(const CQuantumID& id) const
160     {
161         return (uint160)id;
162     }
163
164     uint160 operator()(const CNoDestination& no) const { return CKeyID(); }
165 };
166
167 CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
168 {
169     std::vector<unsigned char> data;
170     uint160 hash;
171     if (DecodeBase58Check(str, data)) {
172         // base58-encoded Bitcoin addresses.
173         // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
174         const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
175         if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
176             std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
177             return CKeyID(hash);
178         }
179
180         // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
181         const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
182         if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
183             std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
184             return CScriptID(hash);
185         }
186
187         const std::vector<unsigned char>& identity_prefix = params.Base58Prefix(CChainParams::IDENTITY_ADDRESS);
188         if (data.size() == hash.size() + identity_prefix.size() && std::equal(identity_prefix.begin(), identity_prefix.end(), data.begin())) {
189             std::copy(data.begin() + identity_prefix.size(), data.end(), hash.begin());
190             return CIdentityID(hash);
191         }
192
193         const std::vector<unsigned char>& index_prefix = params.Base58Prefix(CChainParams::INDEX_ADDRESS);
194         if (data.size() == hash.size() + index_prefix.size() && std::equal(index_prefix.begin(), index_prefix.end(), data.begin())) {
195             std::copy(data.begin() + index_prefix.size(), data.end(), hash.begin());
196             return CIndexID(hash);
197         }
198
199         const std::vector<unsigned char>& quantum_prefix = params.Base58Prefix(CChainParams::QUANTUM_ADDRESS);
200         if (data.size() == hash.size() + quantum_prefix.size() && std::equal(quantum_prefix.begin(), quantum_prefix.end(), data.begin())) {
201             std::copy(data.begin() + quantum_prefix.size(), data.end(), hash.begin());
202             return CQuantumID(hash);
203         }
204     }
205     else if (std::count(str.begin(), str.end(), '@') == 1)
206     {
207         uint160 parent;
208         std::string cleanName = CleanName(str, parent);
209         if (cleanName != "")
210         {
211             return CIdentityID(CIdentity::GetID(cleanName, parent));
212         }
213     }
214
215     return CNoDestination();
216 }
217
218 class PaymentAddressEncoder : public boost::static_visitor<std::string>
219 {
220 private:
221     const CChainParams& m_params;
222
223 public:
224     PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}
225
226     std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
227     {
228         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
229         ss << zaddr;
230         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
231         data.insert(data.end(), ss.begin(), ss.end());
232         return EncodeBase58Check(data);
233     }
234
235     std::string operator()(const libzcash::SaplingPaymentAddress& zaddr) const
236     {
237         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
238         ss << zaddr;
239         // ConvertBits requires unsigned char, but CDataStream uses char
240         std::vector<unsigned char> seraddr(ss.begin(), ss.end());
241         std::vector<unsigned char> data;
242         // See calculation comment below
243         data.reserve((seraddr.size() * 8 + 4) / 5);
244         ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, seraddr.begin(), seraddr.end());
245         return bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS), data);
246     }
247
248     std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
249 };
250
251 class ViewingKeyEncoder : public boost::static_visitor<std::string>
252 {
253 private:
254     const CChainParams& m_params;
255
256 public:
257     ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}
258
259     std::string operator()(const libzcash::SproutViewingKey& vk) const
260     {
261         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
262         ss << vk;
263         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY);
264         data.insert(data.end(), ss.begin(), ss.end());
265         std::string ret = EncodeBase58Check(data);
266         memory_cleanse(data.data(), data.size());
267         return ret;
268     }
269
270     std::string operator()(const libzcash::SaplingIncomingViewingKey& vk) const
271     {
272         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
273         ss << vk;
274         std::vector<unsigned char> serkey(ss.begin(), ss.end());
275         std::vector<unsigned char> data;
276         ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
277         std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY), data);
278         memory_cleanse(serkey.data(), serkey.size());
279         memory_cleanse(data.data(), data.size());
280         return ret;
281     }
282
283     std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
284 };
285
286 class SpendingKeyEncoder : public boost::static_visitor<std::string>
287 {
288 private:
289     const CChainParams& m_params;
290
291 public:
292     SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}
293
294     std::string operator()(const libzcash::SproutSpendingKey& zkey) const
295     {
296         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
297         ss << zkey;
298         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY);
299         data.insert(data.end(), ss.begin(), ss.end());
300         std::string ret = EncodeBase58Check(data);
301         memory_cleanse(data.data(), data.size());
302         return ret;
303     }
304
305     std::string operator()(const libzcash::SaplingExtendedSpendingKey& zkey) const
306     {
307         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
308         ss << zkey;
309         // ConvertBits requires unsigned char, but CDataStream uses char
310         std::vector<unsigned char> serkey(ss.begin(), ss.end());
311         std::vector<unsigned char> data;
312         // See calculation comment below
313         data.reserve((serkey.size() * 8 + 4) / 5);
314         ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
315         std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY), data);
316         memory_cleanse(serkey.data(), serkey.size());
317         memory_cleanse(data.data(), data.size());
318         return ret;
319     }
320
321     std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
322 };
323
324 // Sizes of SaplingPaymentAddress and SaplingSpendingKey after
325 // ConvertBits<8, 5, true>(). The calculations below take the
326 // regular serialized size in bytes, convert to bits, and then
327 // perform ceiling division to get the number of 5-bit clusters.
328 const size_t ConvertedSaplingPaymentAddressSize = ((32 + 11) * 8 + 4) / 5;
329 const size_t ConvertedSaplingExtendedSpendingKeySize = (ZIP32_XSK_SIZE * 8 + 4) / 5;
330 const size_t ConvertedSaplingIncomingViewingKeySize = (32 * 8 + 4) / 5;
331 } // namespace
332
333 CKey DecodeSecret(const std::string& str)
334 {
335     CKey key;
336     std::vector<unsigned char> data;
337     if (DecodeBase58Check(str, data)) {
338         const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
339         if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
340             std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
341             bool compressed = data.size() == 33 + privkey_prefix.size();
342             key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
343         }
344     }
345     memory_cleanse(data.data(), data.size());
346     return key;
347 }
348
349 std::string EncodeSecret(const CKey& key)
350 {
351     assert(key.IsValid());
352     std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
353     data.insert(data.end(), key.begin(), key.end());
354     if (key.IsCompressed()) {
355         data.push_back(1);
356     }
357     std::string ret = EncodeBase58Check(data);
358     memory_cleanse(data.data(), data.size());
359     return ret;
360 }
361
362 CExtPubKey DecodeExtPubKey(const std::string& str)
363 {
364     CExtPubKey key;
365     std::vector<unsigned char> data;
366     if (DecodeBase58Check(str, data)) {
367         const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
368         if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
369             key.Decode(data.data() + prefix.size());
370         }
371     }
372     return key;
373 }
374
375 std::string EncodeExtPubKey(const CExtPubKey& key)
376 {
377     std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
378     size_t size = data.size();
379     data.resize(size + BIP32_EXTKEY_SIZE);
380     key.Encode(data.data() + size);
381     std::string ret = EncodeBase58Check(data);
382     return ret;
383 }
384
385 CExtKey DecodeExtKey(const std::string& str)
386 {
387     CExtKey key;
388     std::vector<unsigned char> data;
389     if (DecodeBase58Check(str, data)) {
390         const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
391         if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
392             key.Decode(data.data() + prefix.size());
393         }
394     }
395     return key;
396 }
397
398 std::string EncodeExtKey(const CExtKey& key)
399 {
400     std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
401     size_t size = data.size();
402     data.resize(size + BIP32_EXTKEY_SIZE);
403     key.Encode(data.data() + size);
404     std::string ret = EncodeBase58Check(data);
405     memory_cleanse(data.data(), data.size());
406     return ret;
407 }
408
409 std::string EncodeDestination(const CTxDestination& dest)
410 {
411     return boost::apply_visitor(DestinationEncoder(Params()), dest);
412 }
413
414 std::vector<unsigned char> GetDestinationBytes(const CTxDestination& dest)
415 {
416     return boost::apply_visitor(DestinationBytes(), dest);
417 }
418
419 uint160 GetDestinationID(const CTxDestination dest)
420 {
421     return boost::apply_visitor(DestinationID(), dest);
422 }
423
424 CTxDestination DecodeDestination(const std::string& str)
425 {
426     return DecodeDestination(str, Params());
427 }
428
429 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
430 {
431     return IsValidDestination(DecodeDestination(str, params));
432 }
433
434 bool IsValidDestinationString(const std::string& str)
435 {
436     return IsValidDestinationString(str, Params());
437 }
438
439 std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
440 {
441     return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr);
442 }
443
444 libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
445 {
446     std::vector<unsigned char> data;
447     if (DecodeBase58Check(str, data)) {
448         const std::vector<unsigned char>& zaddr_prefix = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
449         if ((data.size() == libzcash::SerializedSproutPaymentAddressSize + zaddr_prefix.size()) &&
450             std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) {
451             CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end());
452             CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
453             libzcash::SproutPaymentAddress ret;
454             ss >> ret;
455             return ret;
456         }
457     }
458     data.clear();
459     auto bech = bech32::Decode(str);
460     if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
461         bech.second.size() == ConvertedSaplingPaymentAddressSize) {
462         // Bech32 decoding
463         data.reserve((bech.second.size() * 5) / 8);
464         if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
465             CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
466             libzcash::SaplingPaymentAddress ret;
467             ss >> ret;
468             return ret;
469         }
470     }
471     return libzcash::InvalidEncoding();
472 }
473
474 bool IsValidPaymentAddressString(const std::string& str, uint32_t consensusBranchId) {
475     return IsValidPaymentAddress(DecodePaymentAddress(str), consensusBranchId);
476 }
477
478 std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
479 {
480     return boost::apply_visitor(ViewingKeyEncoder(Params()), vk);
481 }
482
483 libzcash::ViewingKey DecodeViewingKey(const std::string& str)
484 {
485     std::vector<unsigned char> data;
486     if (DecodeBase58Check(str, data)) {
487         const std::vector<unsigned char>& vk_prefix = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY);
488         if ((data.size() == libzcash::SerializedSproutViewingKeySize + vk_prefix.size()) &&
489             std::equal(vk_prefix.begin(), vk_prefix.end(), data.begin())) {
490             CSerializeData serialized(data.begin() + vk_prefix.size(), data.end());
491             CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
492             libzcash::SproutViewingKey ret;
493             ss >> ret;
494             memory_cleanse(serialized.data(), serialized.size());
495             memory_cleanse(data.data(), data.size());
496             return ret;
497         }
498     }
499     data.clear();
500     auto bech = bech32::Decode(str);
501     if(bech.first == Params().Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY) &&
502        bech.second.size() == ConvertedSaplingIncomingViewingKeySize) {
503         // Bech32 decoding
504         data.reserve((bech.second.size() * 5) / 8);
505         if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
506             CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
507             libzcash::SaplingIncomingViewingKey ret;
508             ss >> ret;
509             memory_cleanse(data.data(), data.size());
510             return ret;
511         }
512     }
513     return libzcash::InvalidEncoding();
514 }
515
516 std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
517 {
518     return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey);
519 }
520
521 libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
522 {
523     std::vector<unsigned char> data;
524     if (DecodeBase58Check(str, data)) {
525         const std::vector<unsigned char>& zkey_prefix = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY);
526         if ((data.size() == libzcash::SerializedSproutSpendingKeySize + zkey_prefix.size()) &&
527             std::equal(zkey_prefix.begin(), zkey_prefix.end(), data.begin())) {
528             CSerializeData serialized(data.begin() + zkey_prefix.size(), data.end());
529             CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
530             libzcash::SproutSpendingKey ret;
531             ss >> ret;
532             memory_cleanse(serialized.data(), serialized.size());
533             memory_cleanse(data.data(), data.size());
534             return ret;
535         }
536     }
537     data.clear();
538     auto bech = bech32::Decode(str);
539     if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) &&
540         bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) {
541         // Bech32 decoding
542         data.reserve((bech.second.size() * 5) / 8);
543         if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
544             CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
545             libzcash::SaplingExtendedSpendingKey ret;
546             ss >> ret;
547             memory_cleanse(data.data(), data.size());
548             return ret;
549         }
550     }
551     memory_cleanse(data.data(), data.size());
552     return libzcash::InvalidEncoding();
553 }
554
555 CProofRoot::CProofRoot(const UniValue &uni) :
556     version(VERSION_CURRENT),
557     type(TYPE_PBAAS),
558     rootHeight(0)
559 {
560     version = (uint32_t)uni_get_int(find_value(uni, "version"));
561     type = (uint32_t)uni_get_int(find_value(uni, "type"));
562     systemID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "systemid"))));
563     rootHeight = (uint32_t)uni_get_int(find_value(uni, "height"));
564     stateRoot = uint256S(uni_get_str(find_value(uni, "stateroot")));
565     blockHash = uint256S(uni_get_str(find_value(uni, "blockhash")));
566     compactPower = uint256S(uni_get_str(find_value(uni, "power")));
567 }
568
569 UniValue CProofRoot::ToUniValue() const
570 {
571     UniValue obj(UniValue::VOBJ);
572     obj.push_back(Pair("version", (int64_t)version));
573     obj.push_back(Pair("type", (int64_t)type));
574     obj.push_back(Pair("systemid", EncodeDestination(CIdentityID(systemID))));
575     obj.push_back(Pair("height", (int64_t)rootHeight));
576     obj.push_back(Pair("stateroot", stateRoot.GetHex()));
577     obj.push_back(Pair("blockhash", blockHash.GetHex()));
578     obj.push_back(Pair("power", compactPower.GetHex()));
579     return obj;
580 }
581
582 CTokenOutput::CTokenOutput(const UniValue &obj)
583 {
584     nVersion = (uint32_t)uni_get_int(find_value(obj, "version"), VERSION_CURRENT);
585     UniValue values = find_value(obj, "currencyvalues");
586     if (values.isObject())
587     {
588         reserveValues = CCurrencyValueMap(values);
589     }
590 }
591
592 CReserveTransfer::CReserveTransfer(const UniValue &uni) : CTokenOutput(uni), nFees(0)
593 {
594     flags = uni_get_int64(find_value(uni, "flags"), 0);
595     feeCurrencyID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "feecurrencyid"))));
596     nFees = AmountFromValueNoErr(find_value(uni, "fees"));
597
598     if (IsReserveToReserve())
599     {
600         secondReserveID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "destinationcurrencyid"))));
601         destCurrencyID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "via"))));
602     }
603     else
604     {
605         destCurrencyID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "destinationcurrencyid"))));
606     }
607     if (IsCrossSystem())
608     {
609         destSystemID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "exportto"))));
610     }
611     destination = CTransferDestination(find_value(uni, "destination"));
612 }
613
614 CPrincipal::CPrincipal(const UniValue &uni)
615 {
616     nVersion = uni_get_int(find_value(uni, "version"), VERSION_PBAAS);
617     flags = uni_get_int(find_value(uni, "flags"));
618     UniValue primaryAddressesUni = find_value(uni, "primaryaddresses");
619     if (primaryAddressesUni.isArray())
620     {
621         for (int i = 0; i < primaryAddressesUni.size(); i++)
622         {
623             try
624             {
625                 CTxDestination dest = DecodeDestination(uni_get_str(primaryAddressesUni[i]));
626                 if (dest.which() == COptCCParams::ADDRTYPE_PK || dest.which() == COptCCParams::ADDRTYPE_PKH)
627                 {
628                     primaryAddresses.push_back(dest);
629                 }
630             }
631             catch (const std::exception &e)
632             {
633                 LogPrintf("%s: bad address %s\n", __func__, primaryAddressesUni[i].write().c_str());
634                 nVersion = VERSION_INVALID;
635             }
636         }
637     }
638
639     minSigs = uni_get_int(find_value(uni, "minimumsignatures"));
640 }
641
642 CIdentity::CIdentity(const UniValue &uni) : CPrincipal(uni)
643 {
644     UniValue parentUni = find_value(uni, "parent");
645     parent = uint160(GetDestinationID(DecodeDestination(uni_get_str(parentUni))));
646     name = CleanName(uni_get_str(find_value(uni, "name")), parent);
647
648     if (parent.IsNull())
649     {
650         // if either:
651         // 1. we have an explicitly null parent or
652         // 2. with one name and a null parent, we have the verus chain ID, assume we have a null parent
653         // otherwise, default our current chain as the parent of a null-parented ID
654         parent = (!parentUni.isNull() || GetID() == VERUS_CHAINID) ? uint160() : ASSETCHAINS_CHAINID;
655     }
656
657     if (nVersion >= VERSION_PBAAS)
658     {
659         systemID = uint160(GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "systemid")))));
660         if (systemID.IsNull())
661         {
662             systemID = parent.IsNull() ? GetID() : parent;
663         }
664     }
665
666     UniValue hashesUni = find_value(uni, "contentmap");
667     if (hashesUni.isObject())
668     {
669         std::vector<std::string> keys = hashesUni.getKeys();
670         std::vector<UniValue> values = hashesUni.getValues();
671         for (int i = 0; i < keys.size(); i++)
672         {
673             try
674             {
675                 std::vector<unsigned char> vch(ParseHex(keys[i]));
676                 uint160 key;
677                 if (vch.size() == 20 && !((key = uint160(vch)).IsNull() || i >= values.size()))
678                 {
679                     contentMap[key] = uint256S(uni_get_str(values[i]));
680                 }
681                 else
682                 {
683                     nVersion = VERSION_INVALID;
684                 }
685             }
686             catch (const std::exception &e)
687             {
688                 nVersion = VERSION_INVALID;
689             }
690             if (nVersion == VERSION_INVALID)
691             {
692                 LogPrintf("%s: contentmap entry is not valid keys: %s, values: %s\n", __func__, keys[i].c_str(), values[i].write().c_str());
693                 break;
694             }
695         }
696     }
697     std::string revocationStr = uni_get_str(find_value(uni, "revocationauthority"));
698     std::string recoveryStr = uni_get_str(find_value(uni, "recoveryauthority"));
699
700     revocationAuthority = revocationStr == "" ? GetID() : uint160(GetDestinationID(DecodeDestination(revocationStr)));
701     recoveryAuthority = recoveryStr == "" ? GetID() : uint160(GetDestinationID(DecodeDestination(recoveryStr)));
702     libzcash::PaymentAddress pa = DecodePaymentAddress(uni_get_str(find_value(uni, "privateaddress")));
703
704     unlockAfter = uni_get_int(find_value(uni, "timelock"));
705
706     if (revocationAuthority.IsNull() || recoveryAuthority.IsNull())
707     {
708         LogPrintf("%s: invalid address\n", __func__);
709         nVersion = VERSION_INVALID;
710     }
711     else if (boost::get<libzcash::SaplingPaymentAddress>(&pa) != nullptr)
712     {
713         privateAddresses.push_back(*boost::get<libzcash::SaplingPaymentAddress>(&pa));
714     }
715 }
716
717 CTransferDestination::CTransferDestination(const UniValue &obj) : fees(0)
718 {
719     type = uni_get_int(find_value(obj, "type"));
720
721     switch (TypeNoFlags())
722     {
723         case CTransferDestination::DEST_PKH:
724         case CTransferDestination::DEST_SH:
725         case CTransferDestination::DEST_ID:
726         case CTransferDestination::DEST_QUANTUM:
727         {
728             CTxDestination checkDest = DecodeDestination(uni_get_str(find_value(obj, "address")));
729             if (checkDest.which() != COptCCParams::ADDRTYPE_INVALID)
730             {
731                 destination = GetDestinationBytes(checkDest);
732             }
733             else
734             {
735                 type = DEST_INVALID;
736             }
737             break;
738         }
739
740         case CTransferDestination::DEST_PK:
741         {
742             std::string pkStr = uni_get_str(find_value(obj, "address"));
743             destination = ParseHex(pkStr);
744             break;
745         }
746
747         case CTransferDestination::DEST_ETH:
748         {
749             uint160 ethDestID = DecodeEthDestination(uni_get_str(find_value(obj, "address")));
750             destination = std::vector<unsigned char>(ethDestID.begin(), ethDestID.end());
751             break;
752         }
753
754         case CTransferDestination::DEST_FULLID:
755         {
756             CIdentity destID = CIdentity(find_value(obj, "identity"));
757             if (destID.IsValid())
758             {
759                 destination = ::AsVector(destID);
760             }
761             else
762             {
763                 type = DEST_INVALID;
764             }
765             break;
766         }
767
768         case CTransferDestination::DEST_REGISTERCURRENCY:
769         {
770             CCurrencyRegistrationDestination curRegistration({CIdentity(find_value(obj, "identity")), CCurrencyDefinition(find_value(obj, "currency"))});
771             if (curRegistration.IsValid())
772             {
773                 destination = ::AsVector(curRegistration);
774             }
775             else
776             {
777                 type = DEST_INVALID;
778             }
779             break;
780         }
781
782         case CTransferDestination::DEST_RAW:
783         {
784             std::string rawStr = uni_get_str(find_value(obj, "address"));
785             destination = ParseHex(rawStr);
786             break;
787         }
788
789         case CTransferDestination::DEST_NESTEDTRANSFER:
790         {
791             CReserveTransfer nestedTransfer = CReserveTransfer(find_value(obj, "nestedtransfer"));
792             destination = ::AsVector(nestedTransfer);
793             break;
794         }
795     }
796     if (type & FLAG_DEST_GATEWAY)
797     {
798         gatewayID = DecodeEthDestination(uni_get_str(find_value(obj, "gateway")));
799         fees = uni_get_int64(find_value(obj, "fees"));
800     }
801 }
802
803 uint160 CCrossChainRPCData::GetConditionID(const uint160 &cid, uint32_t condition)
804 {
805     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
806     hw << condition;
807     hw << cid;
808     uint256 chainHash = hw.GetHash();
809     return Hash160(chainHash.begin(), chainHash.end());
810 }
811
812 uint160 CCrossChainRPCData::GetConditionID(const uint160 &cid, const uint160 &condition)
813 {
814     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
815     hw << condition;
816     hw << cid;
817     uint256 chainHash = hw.GetHash();
818     return Hash160(chainHash.begin(), chainHash.end());
819 }
820
821 uint160 CCrossChainRPCData::GetConditionID(const uint160 &cid, const uint160 &condition, const uint256 &txid, int32_t voutNum)
822 {
823     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
824     hw << condition;
825     hw << cid;
826     hw << txid;
827     hw << voutNum;
828     uint256 chainHash = hw.GetHash();
829     return Hash160(chainHash.begin(), chainHash.end());
830 }
831
832 uint160 CCrossChainRPCData::GetConditionID(std::string name, uint32_t condition)
833 {
834     uint160 parent;
835     uint160 cid = CIdentity::GetID(name, parent);
836
837     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
838     hw << condition;
839     hw << cid;
840     uint256 chainHash = hw.GetHash();
841     return Hash160(chainHash.begin(), chainHash.end());
842 }
843
844 UniValue CNotaryEvidence::ToUniValue() const
845 {
846     UniValue retObj(UniValue::VOBJ);
847     retObj.push_back(Pair("version", version));
848     retObj.push_back(Pair("type", type));
849     retObj.push_back(Pair("systemid", EncodeDestination(CIdentityID(systemID))));
850     retObj.push_back(Pair("output", output.ToUniValue()));
851     retObj.push_back(Pair("confirmed", confirmed));
852     UniValue sigObj(UniValue::VOBJ);
853     for (auto &oneSig : signatures)
854     {
855         sigObj.push_back(Pair(EncodeDestination(CIdentityID(oneSig.first)), oneSig.second.ToUniValue()));
856     }
857     retObj.push_back(Pair("signatures", sigObj));
858     UniValue evidenceProofs(UniValue::VARR);
859     for (auto &oneProof : evidence)
860     {
861         evidenceProofs.push_back(oneProof.ToUniValue());
862     }
863     retObj.push_back(Pair("evidence", evidenceProofs));
864     return retObj;
865 }
866
867 // this will add the current Verus chain name to subnames if it is not present
868 // on both id and chain names
869 std::vector<std::string> ParseSubNames(const std::string &Name, std::string &ChainOut, bool displayfilter, bool addVerus)
870 {
871     return CVDXF::ParseSubNames(Name, ChainOut, displayfilter, addVerus);
872 }
873
874 // takes a multipart name, either complete or partially processed with a Parent hash,
875 // hash its parent names into a parent ID and return the parent hash and cleaned, single name
876 std::string CleanName(const std::string &Name, uint160 &Parent, bool displayfilter, bool addVerus)
877 {
878     std::string chainName;
879     std::vector<std::string> subNames = ParseSubNames(Name, chainName, displayfilter, addVerus);
880
881     if (!subNames.size())
882     {
883         return "";
884     }
885
886     if (!Parent.IsNull() &&
887         boost::to_lower_copy(subNames.back()) == boost::to_lower_copy(VERUS_CHAINNAME))
888     {
889         subNames.pop_back();
890     }
891
892     for (int i = subNames.size() - 1; i > 0; i--)
893     {
894         std::string parentNameStr = boost::algorithm::to_lower_copy(subNames[i]);
895         const char *parentName = parentNameStr.c_str();
896         uint256 idHash;
897
898         if (Parent.IsNull())
899         {
900             idHash = Hash(parentName, parentName + parentNameStr.size());
901         }
902         else
903         {
904             idHash = Hash(parentName, parentName + strlen(parentName));
905             idHash = Hash(Parent.begin(), Parent.end(), idHash.begin(), idHash.end());
906         }
907         Parent = Hash160(idHash.begin(), idHash.end());
908         //printf("uint160 for parent %s: %s\n", parentName, Parent.GetHex().c_str());
909     }
910     return subNames[0];
911 }
912
913 CNameReservation::CNameReservation(const CTransaction &tx, int *pOutNum)
914 {
915     for (int i = 0; i < tx.vout.size(); i++)
916     {
917         COptCCParams p;
918         if (IsPayToCryptoCondition(tx.vout[i].scriptPubKey, p))
919         {
920             if (p.evalCode == EVAL_IDENTITY_RESERVATION)
921             {
922                 FromVector(p.vData[0], *this);
923                 return;
924             }
925         }
926     }
927 }
928
929 CIdentity::CIdentity(const CScript &scriptPubKey)
930 {
931     COptCCParams p;
932     if (IsPayToCryptoCondition(scriptPubKey, p) && p.IsValid() && p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size())
933     {
934         *this = CIdentity(p.vData[0]);
935     }
936 }
937
938 CIdentityID CIdentity::GetID(const std::string &Name, uint160 &parent)
939 {
940     std::string cleanName = CleanName(Name, parent);
941
942     std::string subName = boost::algorithm::to_lower_copy(cleanName);
943     const char *idName = subName.c_str();
944     //printf("hashing: %s, %s\n", idName, parent.GetHex().c_str());
945
946     uint256 idHash;
947     if (parent.IsNull())
948     {
949         idHash = Hash(idName, idName + strlen(idName));
950     }
951     else
952     {
953         idHash = Hash(idName, idName + strlen(idName));
954         idHash = Hash(parent.begin(), parent.end(), idHash.begin(), idHash.end());
955     }
956     return Hash160(idHash.begin(), idHash.end());
957 }
958
959 CIdentityID CIdentity::GetID(const std::string &Name) const
960 {
961     uint160 parent;
962     std::string cleanName = CleanName(Name, parent);
963
964     std::string subName = boost::algorithm::to_lower_copy(cleanName);
965     const char *idName = subName.c_str();
966     //printf("hashing: %s, %s\n", idName, parent.GetHex().c_str());
967
968     uint256 idHash;
969     if (parent.IsNull())
970     {
971         idHash = Hash(idName, idName + strlen(idName));
972     }
973     else
974     {
975         idHash = Hash(idName, idName + strlen(idName));
976         idHash = Hash(parent.begin(), parent.end(), idHash.begin(), idHash.end());
977
978     }
979     return Hash160(idHash.begin(), idHash.end());
980 }
981
982 CIdentityID CIdentity::GetID() const
983 {
984     uint160 Parent = parent;
985     return GetID(name, Parent);
986 }
987
988 uint160 CCrossChainRPCData::GetID(std::string name)
989 {
990     uint160 parent;
991     //printf("uint160 for name %s: %s\n", name.c_str(), CIdentity::GetID(name, parent).GetHex().c_str());
992     return CIdentity::GetID(name, parent);
993 }
994
995 CScript CIdentity::TransparentOutput() const
996 {
997     CConditionObj<CIdentity> ccObj = CConditionObj<CIdentity>(0, std::vector<CTxDestination>({CTxDestination(CIdentityID(GetID()))}), 1);
998     return MakeMofNCCScript(ccObj);
999 }
1000
1001 CScript CIdentity::TransparentOutput(const CIdentityID &destinationID)
1002 {
1003     CConditionObj<CIdentity> ccObj = CConditionObj<CIdentity>(0, std::vector<CTxDestination>({destinationID}), 1);
1004     return MakeMofNCCScript(ccObj);
1005 }
1006
1007 CScript CIdentity::IdentityUpdateOutputScript(uint32_t height) const
1008 {
1009     CScript ret;
1010
1011     if (!IsValid())
1012     {
1013         return ret;
1014     }
1015
1016     std::vector<CTxDestination> dests1({CTxDestination(CIdentityID(GetID()))});
1017     CConditionObj<CIdentity> primary(EVAL_IDENTITY_PRIMARY, dests1, 1, this);
1018
1019     // when PBaaS activates, we no longer need redundant entries, so reduce the size a bit
1020     if (CConstVerusSolutionVector::GetVersionByHeight(height) >= CActivationHeight::ACTIVATE_PBAAS)
1021     {
1022         if (IsRevoked())
1023         {
1024             std::vector<CTxDestination> dests3({CTxDestination(CIdentityID(recoveryAuthority))});
1025             CConditionObj<CIdentity> recovery(EVAL_IDENTITY_RECOVER, dests3, 1);
1026             ret = MakeMofNCCScript(1, primary, recovery);
1027         }
1028         else
1029         {
1030             std::vector<CTxDestination> dests2({CTxDestination(CIdentityID(revocationAuthority))});
1031             CConditionObj<CIdentity> revocation(EVAL_IDENTITY_REVOKE, dests2, 1);
1032             ret = MakeMofNCCScript(1, primary, revocation);
1033         }
1034     }
1035     else
1036     {
1037         std::vector<CTxDestination> dests2({CTxDestination(CIdentityID(revocationAuthority))});
1038         CConditionObj<CIdentity> revocation(EVAL_IDENTITY_REVOKE, dests2, 1);
1039         std::vector<CTxDestination> dests3({CTxDestination(CIdentityID(recoveryAuthority))});
1040         CConditionObj<CIdentity> recovery(EVAL_IDENTITY_RECOVER, dests3, 1);
1041         ret = MakeMofNCCScript(1, primary, revocation, recovery);
1042     }
1043
1044     return ret;
1045 }
1046
This page took 0.092037 seconds and 4 git commands to generate.