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 .
10 #include <script/script.h>
11 #include <utilstrencodings.h>
13 #include <boost/variant/apply_visitor.hpp>
14 #include <boost/variant/static_visitor.hpp>
16 #include "pbaas/identity.h"
17 #include "cc/CCinclude.h"
18 #include "boost/algorithm/string.hpp"
24 extern uint160 VERUS_CHAINID;
25 extern std::string VERUS_CHAINNAME;
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"
32 bool VERUS_PRIVATECHANGE;
33 std::string VERUS_DEFAULT_ZADDR;
37 class DestinationEncoder : public boost::static_visitor<std::string>
40 const CChainParams& m_params;
43 DestinationEncoder(const CChainParams& params) : m_params(params) {}
45 std::string operator()(const CKeyID& id) const
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);
52 std::string operator()(const CPubKey& key) const
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);
60 std::string operator()(const CScriptID& id) const
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);
67 std::string operator()(const CIdentityID& id) const
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);
74 std::string operator()(const CIndexID& id) const
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);
81 std::string operator()(const CQuantumID& id) const
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);
88 std::string operator()(const CNoDestination& no) const { return {}; }
91 class DestinationBytes : public boost::static_visitor<std::vector<unsigned char>>
96 std::vector<unsigned char> operator()(const CKeyID& id) const
98 return std::vector<unsigned char>(id.begin(), id.end());
101 std::vector<unsigned char> operator()(const CPubKey& key) const
103 return std::vector<unsigned char>(key.begin(), key.end());
106 std::vector<unsigned char> operator()(const CScriptID& id) const
108 return std::vector<unsigned char>(id.begin(), id.end());
111 std::vector<unsigned char> operator()(const CIdentityID& id) const
113 return std::vector<unsigned char>(id.begin(), id.end());
116 std::vector<unsigned char> operator()(const CIndexID& id) const
118 return std::vector<unsigned char>(id.begin(), id.end());
121 std::vector<unsigned char> operator()(const CQuantumID& id) const
123 return std::vector<unsigned char>(id.begin(), id.end());
126 std::vector<unsigned char> operator()(const CNoDestination& no) const { return {}; }
129 class DestinationID : public boost::static_visitor<uint160>
134 uint160 operator()(const CKeyID& id) const
139 uint160 operator()(const CPubKey& key) const
141 return (uint160)key.GetID();
144 uint160 operator()(const CScriptID& id) const
149 uint160 operator()(const CIdentityID& id) const
154 uint160 operator()(const CIndexID& id) const
159 uint160 operator()(const CQuantumID& id) const
164 uint160 operator()(const CNoDestination& no) const { return CKeyID(); }
167 CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
169 std::vector<unsigned char> data;
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());
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);
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);
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);
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);
205 else if (std::count(str.begin(), str.end(), '@') == 1)
208 std::string cleanName = CleanName(str, parent);
211 return CIdentityID(CIdentity::GetID(cleanName, parent));
215 return CNoDestination();
218 class PaymentAddressEncoder : public boost::static_visitor<std::string>
221 const CChainParams& m_params;
224 PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}
226 std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
228 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
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);
235 std::string operator()(const libzcash::SaplingPaymentAddress& zaddr) const
237 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
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);
248 std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
251 class ViewingKeyEncoder : public boost::static_visitor<std::string>
254 const CChainParams& m_params;
257 ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}
259 std::string operator()(const libzcash::SproutViewingKey& vk) const
261 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
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());
270 std::string operator()(const libzcash::SaplingIncomingViewingKey& vk) const
272 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
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());
283 std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
286 class SpendingKeyEncoder : public boost::static_visitor<std::string>
289 const CChainParams& m_params;
292 SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}
294 std::string operator()(const libzcash::SproutSpendingKey& zkey) const
296 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
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());
305 std::string operator()(const libzcash::SaplingExtendedSpendingKey& zkey) const
307 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
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());
321 std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
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;
333 CKey DecodeSecret(const std::string& str)
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);
345 memory_cleanse(data.data(), data.size());
349 std::string EncodeSecret(const CKey& key)
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()) {
357 std::string ret = EncodeBase58Check(data);
358 memory_cleanse(data.data(), data.size());
362 CExtPubKey DecodeExtPubKey(const std::string& str)
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());
375 std::string EncodeExtPubKey(const CExtPubKey& key)
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);
385 CExtKey DecodeExtKey(const std::string& str)
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());
398 std::string EncodeExtKey(const CExtKey& key)
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());
409 std::string EncodeDestination(const CTxDestination& dest)
411 return boost::apply_visitor(DestinationEncoder(Params()), dest);
414 std::vector<unsigned char> GetDestinationBytes(const CTxDestination& dest)
416 return boost::apply_visitor(DestinationBytes(), dest);
419 uint160 GetDestinationID(const CTxDestination dest)
421 return boost::apply_visitor(DestinationID(), dest);
424 CTxDestination DecodeDestination(const std::string& str)
426 return DecodeDestination(str, Params());
429 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
431 return IsValidDestination(DecodeDestination(str, params));
434 bool IsValidDestinationString(const std::string& str)
436 return IsValidDestinationString(str, Params());
439 std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
441 return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr);
444 libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
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;
459 auto bech = bech32::Decode(str);
460 if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
461 bech.second.size() == ConvertedSaplingPaymentAddressSize) {
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;
471 return libzcash::InvalidEncoding();
474 bool IsValidPaymentAddressString(const std::string& str, uint32_t consensusBranchId) {
475 return IsValidPaymentAddress(DecodePaymentAddress(str), consensusBranchId);
478 std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
480 return boost::apply_visitor(ViewingKeyEncoder(Params()), vk);
483 libzcash::ViewingKey DecodeViewingKey(const std::string& str)
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;
494 memory_cleanse(serialized.data(), serialized.size());
495 memory_cleanse(data.data(), data.size());
500 auto bech = bech32::Decode(str);
501 if(bech.first == Params().Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY) &&
502 bech.second.size() == ConvertedSaplingIncomingViewingKeySize) {
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;
509 memory_cleanse(data.data(), data.size());
513 return libzcash::InvalidEncoding();
516 std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
518 return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey);
521 libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
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;
532 memory_cleanse(serialized.data(), serialized.size());
533 memory_cleanse(data.data(), data.size());
538 auto bech = bech32::Decode(str);
539 if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) &&
540 bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) {
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;
547 memory_cleanse(data.data(), data.size());
551 memory_cleanse(data.data(), data.size());
552 return libzcash::InvalidEncoding();
555 CProofRoot::CProofRoot(const UniValue &uni) :
556 version(VERSION_CURRENT),
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")));
569 UniValue CProofRoot::ToUniValue() const
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()));
582 CTokenOutput::CTokenOutput(const UniValue &obj)
584 nVersion = (uint32_t)uni_get_int(find_value(obj, "version"), VERSION_CURRENT);
585 UniValue values = find_value(obj, "currencyvalues");
586 if (values.isObject())
588 reserveValues = CCurrencyValueMap(values);
592 CReserveTransfer::CReserveTransfer(const UniValue &uni) : CTokenOutput(uni), nFees(0)
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"));
598 if (IsReserveToReserve())
600 secondReserveID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "destinationcurrencyid"))));
601 destCurrencyID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "via"))));
605 destCurrencyID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "destinationcurrencyid"))));
609 destSystemID = GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "exportto"))));
611 destination = CTransferDestination(find_value(uni, "destination"));
614 CPrincipal::CPrincipal(const UniValue &uni)
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())
621 for (int i = 0; i < primaryAddressesUni.size(); i++)
625 CTxDestination dest = DecodeDestination(uni_get_str(primaryAddressesUni[i]));
626 if (dest.which() == COptCCParams::ADDRTYPE_PK || dest.which() == COptCCParams::ADDRTYPE_PKH)
628 primaryAddresses.push_back(dest);
631 catch (const std::exception &e)
633 LogPrintf("%s: bad address %s\n", __func__, primaryAddressesUni[i].write().c_str());
634 nVersion = VERSION_INVALID;
639 minSigs = uni_get_int(find_value(uni, "minimumsignatures"));
642 CIdentity::CIdentity(const UniValue &uni) : CPrincipal(uni)
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);
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;
657 if (nVersion >= VERSION_PBAAS)
659 systemID = uint160(GetDestinationID(DecodeDestination(uni_get_str(find_value(uni, "systemid")))));
660 if (systemID.IsNull())
662 systemID = parent.IsNull() ? GetID() : parent;
666 UniValue hashesUni = find_value(uni, "contentmap");
667 if (hashesUni.isObject())
669 std::vector<std::string> keys = hashesUni.getKeys();
670 std::vector<UniValue> values = hashesUni.getValues();
671 for (int i = 0; i < keys.size(); i++)
675 std::vector<unsigned char> vch(ParseHex(keys[i]));
677 if (vch.size() == 20 && !((key = uint160(vch)).IsNull() || i >= values.size()))
679 contentMap[key] = uint256S(uni_get_str(values[i]));
683 nVersion = VERSION_INVALID;
686 catch (const std::exception &e)
688 nVersion = VERSION_INVALID;
690 if (nVersion == VERSION_INVALID)
692 LogPrintf("%s: contentmap entry is not valid keys: %s, values: %s\n", __func__, keys[i].c_str(), values[i].write().c_str());
697 std::string revocationStr = uni_get_str(find_value(uni, "revocationauthority"));
698 std::string recoveryStr = uni_get_str(find_value(uni, "recoveryauthority"));
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")));
704 unlockAfter = uni_get_int(find_value(uni, "timelock"));
706 if (revocationAuthority.IsNull() || recoveryAuthority.IsNull())
708 LogPrintf("%s: invalid address\n", __func__);
709 nVersion = VERSION_INVALID;
711 else if (boost::get<libzcash::SaplingPaymentAddress>(&pa) != nullptr)
713 privateAddresses.push_back(*boost::get<libzcash::SaplingPaymentAddress>(&pa));
717 CTransferDestination::CTransferDestination(const UniValue &obj) : fees(0)
719 type = uni_get_int(find_value(obj, "type"));
721 switch (TypeNoFlags())
723 case CTransferDestination::DEST_PKH:
724 case CTransferDestination::DEST_SH:
725 case CTransferDestination::DEST_ID:
726 case CTransferDestination::DEST_QUANTUM:
728 CTxDestination checkDest = DecodeDestination(uni_get_str(find_value(obj, "address")));
729 if (checkDest.which() != COptCCParams::ADDRTYPE_INVALID)
731 destination = GetDestinationBytes(checkDest);
740 case CTransferDestination::DEST_PK:
742 std::string pkStr = uni_get_str(find_value(obj, "address"));
743 destination = ParseHex(pkStr);
747 case CTransferDestination::DEST_ETH:
749 uint160 ethDestID = DecodeEthDestination(uni_get_str(find_value(obj, "address")));
750 destination = std::vector<unsigned char>(ethDestID.begin(), ethDestID.end());
754 case CTransferDestination::DEST_FULLID:
756 CIdentity destID = CIdentity(find_value(obj, "identity"));
757 if (destID.IsValid())
759 destination = ::AsVector(destID);
768 case CTransferDestination::DEST_REGISTERCURRENCY:
770 CCurrencyRegistrationDestination curRegistration({CIdentity(find_value(obj, "identity")), CCurrencyDefinition(find_value(obj, "currency"))});
771 if (curRegistration.IsValid())
773 destination = ::AsVector(curRegistration);
782 case CTransferDestination::DEST_RAW:
784 std::string rawStr = uni_get_str(find_value(obj, "address"));
785 destination = ParseHex(rawStr);
789 case CTransferDestination::DEST_NESTEDTRANSFER:
791 CReserveTransfer nestedTransfer = CReserveTransfer(find_value(obj, "nestedtransfer"));
792 destination = ::AsVector(nestedTransfer);
796 if (type & FLAG_DEST_GATEWAY)
798 gatewayID = DecodeEthDestination(uni_get_str(find_value(obj, "gateway")));
799 fees = uni_get_int64(find_value(obj, "fees"));
803 uint160 CCrossChainRPCData::GetConditionID(const uint160 &cid, uint32_t condition)
805 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
808 uint256 chainHash = hw.GetHash();
809 return Hash160(chainHash.begin(), chainHash.end());
812 uint160 CCrossChainRPCData::GetConditionID(const uint160 &cid, const uint160 &condition)
814 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
817 uint256 chainHash = hw.GetHash();
818 return Hash160(chainHash.begin(), chainHash.end());
821 uint160 CCrossChainRPCData::GetConditionID(const uint160 &cid, const uint160 &condition, const uint256 &txid, int32_t voutNum)
823 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
828 uint256 chainHash = hw.GetHash();
829 return Hash160(chainHash.begin(), chainHash.end());
832 uint160 CCrossChainRPCData::GetConditionID(std::string name, uint32_t condition)
835 uint160 cid = CIdentity::GetID(name, parent);
837 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
840 uint256 chainHash = hw.GetHash();
841 return Hash160(chainHash.begin(), chainHash.end());
844 UniValue CNotaryEvidence::ToUniValue() const
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)
855 sigObj.push_back(Pair(EncodeDestination(CIdentityID(oneSig.first)), oneSig.second.ToUniValue()));
857 retObj.push_back(Pair("signatures", sigObj));
858 UniValue evidenceProofs(UniValue::VARR);
859 for (auto &oneProof : evidence)
861 evidenceProofs.push_back(oneProof.ToUniValue());
863 retObj.push_back(Pair("evidence", evidenceProofs));
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)
871 return CVDXF::ParseSubNames(Name, ChainOut, displayfilter, addVerus);
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)
878 std::string chainName;
879 std::vector<std::string> subNames = ParseSubNames(Name, chainName, displayfilter, addVerus);
881 if (!subNames.size())
886 if (!Parent.IsNull() &&
887 boost::to_lower_copy(subNames.back()) == boost::to_lower_copy(VERUS_CHAINNAME))
892 for (int i = subNames.size() - 1; i > 0; i--)
894 std::string parentNameStr = boost::algorithm::to_lower_copy(subNames[i]);
895 const char *parentName = parentNameStr.c_str();
900 idHash = Hash(parentName, parentName + parentNameStr.size());
904 idHash = Hash(parentName, parentName + strlen(parentName));
905 idHash = Hash(Parent.begin(), Parent.end(), idHash.begin(), idHash.end());
907 Parent = Hash160(idHash.begin(), idHash.end());
908 //printf("uint160 for parent %s: %s\n", parentName, Parent.GetHex().c_str());
913 CNameReservation::CNameReservation(const CTransaction &tx, int *pOutNum)
915 for (int i = 0; i < tx.vout.size(); i++)
918 if (IsPayToCryptoCondition(tx.vout[i].scriptPubKey, p))
920 if (p.evalCode == EVAL_IDENTITY_RESERVATION)
922 FromVector(p.vData[0], *this);
929 CIdentity::CIdentity(const CScript &scriptPubKey)
932 if (IsPayToCryptoCondition(scriptPubKey, p) && p.IsValid() && p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size())
934 *this = CIdentity(p.vData[0]);
938 CIdentityID CIdentity::GetID(const std::string &Name, uint160 &parent)
940 std::string cleanName = CleanName(Name, parent);
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());
949 idHash = Hash(idName, idName + strlen(idName));
953 idHash = Hash(idName, idName + strlen(idName));
954 idHash = Hash(parent.begin(), parent.end(), idHash.begin(), idHash.end());
956 return Hash160(idHash.begin(), idHash.end());
959 CIdentityID CIdentity::GetID(const std::string &Name) const
962 std::string cleanName = CleanName(Name, parent);
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());
971 idHash = Hash(idName, idName + strlen(idName));
975 idHash = Hash(idName, idName + strlen(idName));
976 idHash = Hash(parent.begin(), parent.end(), idHash.begin(), idHash.end());
979 return Hash160(idHash.begin(), idHash.end());
982 CIdentityID CIdentity::GetID() const
984 uint160 Parent = parent;
985 return GetID(name, Parent);
988 uint160 CCrossChainRPCData::GetID(std::string name)
991 //printf("uint160 for name %s: %s\n", name.c_str(), CIdentity::GetID(name, parent).GetHex().c_str());
992 return CIdentity::GetID(name, parent);
995 CScript CIdentity::TransparentOutput() const
997 CConditionObj<CIdentity> ccObj = CConditionObj<CIdentity>(0, std::vector<CTxDestination>({CTxDestination(CIdentityID(GetID()))}), 1);
998 return MakeMofNCCScript(ccObj);
1001 CScript CIdentity::TransparentOutput(const CIdentityID &destinationID)
1003 CConditionObj<CIdentity> ccObj = CConditionObj<CIdentity>(0, std::vector<CTxDestination>({destinationID}), 1);
1004 return MakeMofNCCScript(ccObj);
1007 CScript CIdentity::IdentityUpdateOutputScript(uint32_t height) const
1016 std::vector<CTxDestination> dests1({CTxDestination(CIdentityID(GetID()))});
1017 CConditionObj<CIdentity> primary(EVAL_IDENTITY_PRIMARY, dests1, 1, this);
1019 // when PBaaS activates, we no longer need redundant entries, so reduce the size a bit
1020 if (CConstVerusSolutionVector::GetVersionByHeight(height) >= CActivationHeight::ACTIVATE_PBAAS)
1024 std::vector<CTxDestination> dests3({CTxDestination(CIdentityID(recoveryAuthority))});
1025 CConditionObj<CIdentity> recovery(EVAL_IDENTITY_RECOVER, dests3, 1);
1026 ret = MakeMofNCCScript(1, primary, recovery);
1030 std::vector<CTxDestination> dests2({CTxDestination(CIdentityID(revocationAuthority))});
1031 CConditionObj<CIdentity> revocation(EVAL_IDENTITY_REVOKE, dests2, 1);
1032 ret = MakeMofNCCScript(1, primary, revocation);
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);