]> Git Repo - VerusCoin.git/blob - src/key_io.cpp
testnet breaking changes - Implement index address, hardening, makefile fixes
[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 bool VERUS_PRIVATECHANGE;
29 std::string VERUS_DEFAULT_ZADDR;
30
31 namespace
32 {
33 class DestinationEncoder : public boost::static_visitor<std::string>
34 {
35 private:
36     const CChainParams& m_params;
37
38 public:
39     DestinationEncoder(const CChainParams& params) : m_params(params) {}
40
41     std::string operator()(const CKeyID& id) const
42     {
43         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
44         data.insert(data.end(), id.begin(), id.end());
45         return EncodeBase58Check(data);
46     }
47
48     std::string operator()(const CPubKey& key) const
49     {
50         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
51         CKeyID id = key.GetID();
52         data.insert(data.end(), id.begin(), id.end());
53         return EncodeBase58Check(data);
54     }
55
56     std::string operator()(const CScriptID& id) const
57     {
58         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
59         data.insert(data.end(), id.begin(), id.end());
60         return EncodeBase58Check(data);
61     }
62
63     std::string operator()(const CIdentityID& id) const
64     {
65         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::IDENTITY_ADDRESS);
66         data.insert(data.end(), id.begin(), id.end());
67         return EncodeBase58Check(data);
68     }
69
70     std::string operator()(const CIndexID& id) const
71     {
72         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::INDEX_ADDRESS);
73         data.insert(data.end(), id.begin(), id.end());
74         return EncodeBase58Check(data);
75     }
76
77     std::string operator()(const CQuantumID& id) const
78     {
79         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::QUANTUM_ADDRESS);
80         data.insert(data.end(), id.begin(), id.end());
81         return EncodeBase58Check(data);
82     }
83
84     std::string operator()(const CNoDestination& no) const { return {}; }
85 };
86
87 class DestinationBytes : public boost::static_visitor<std::vector<unsigned char>>
88 {
89 public:
90     DestinationBytes() {}
91
92     std::vector<unsigned char> operator()(const CKeyID& id) const
93     {
94         return std::vector<unsigned char>(id.begin(), id.end());
95     }
96
97     std::vector<unsigned char> operator()(const CPubKey& key) const
98     {
99         return std::vector<unsigned char>(key.begin(), key.end());
100     }
101
102     std::vector<unsigned char> operator()(const CScriptID& id) const
103     {
104         return std::vector<unsigned char>(id.begin(), id.end());
105     }
106
107     std::vector<unsigned char> operator()(const CIdentityID& id) const
108     {
109         return std::vector<unsigned char>(id.begin(), id.end());
110     }
111
112     std::vector<unsigned char> operator()(const CIndexID& id) const
113     {
114         return std::vector<unsigned char>(id.begin(), id.end());
115     }
116
117     std::vector<unsigned char> operator()(const CQuantumID& id) const
118     {
119         return std::vector<unsigned char>(id.begin(), id.end());
120     }
121
122     std::vector<unsigned char> operator()(const CNoDestination& no) const { return {}; }
123 };
124
125 class DestinationID : public boost::static_visitor<uint160>
126 {
127 public:
128     DestinationID() {}
129
130     uint160 operator()(const CKeyID& id) const
131     {
132         return (uint160)id;
133     }
134
135     uint160 operator()(const CPubKey& key) const
136     {
137         return (uint160)key.GetID();
138     }
139
140     uint160 operator()(const CScriptID& id) const
141     {
142         return (uint160)id;
143     }
144
145     uint160 operator()(const CIdentityID& id) const
146     {
147         return (uint160)id;
148     }
149
150     uint160 operator()(const CIndexID& id) const
151     {
152         return (uint160)id;
153     }
154
155     uint160 operator()(const CQuantumID& id) const
156     {
157         return (uint160)id;
158     }
159
160     uint160 operator()(const CNoDestination& no) const { return CKeyID(); }
161 };
162
163 CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
164 {
165     std::vector<unsigned char> data;
166     uint160 hash;
167     if (DecodeBase58Check(str, data)) {
168         // base58-encoded Bitcoin addresses.
169         // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
170         const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
171         if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
172             std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
173             return CKeyID(hash);
174         }
175
176         // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
177         const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
178         if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
179             std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
180             return CScriptID(hash);
181         }
182
183         const std::vector<unsigned char>& identity_prefix = params.Base58Prefix(CChainParams::IDENTITY_ADDRESS);
184         if (data.size() == hash.size() + identity_prefix.size() && std::equal(identity_prefix.begin(), identity_prefix.end(), data.begin())) {
185             std::copy(data.begin() + identity_prefix.size(), data.end(), hash.begin());
186             return CIdentityID(hash);
187         }
188
189         const std::vector<unsigned char>& index_prefix = params.Base58Prefix(CChainParams::INDEX_ADDRESS);
190         if (data.size() == hash.size() + index_prefix.size() && std::equal(index_prefix.begin(), index_prefix.end(), data.begin())) {
191             std::copy(data.begin() + index_prefix.size(), data.end(), hash.begin());
192             return CIndexID(hash);
193         }
194
195         const std::vector<unsigned char>& quantum_prefix = params.Base58Prefix(CChainParams::QUANTUM_ADDRESS);
196         if (data.size() == hash.size() + quantum_prefix.size() && std::equal(quantum_prefix.begin(), quantum_prefix.end(), data.begin())) {
197             std::copy(data.begin() + quantum_prefix.size(), data.end(), hash.begin());
198             return CQuantumID(hash);
199         }
200     }
201     else if (std::count(str.begin(), str.end(), '@') == 1)
202     {
203         uint160 parent;
204         return CIdentityID(CIdentity::GetID(str, parent));
205     }
206
207     return CNoDestination();
208 }
209
210 class PaymentAddressEncoder : public boost::static_visitor<std::string>
211 {
212 private:
213     const CChainParams& m_params;
214
215 public:
216     PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}
217
218     std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
219     {
220         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
221         ss << zaddr;
222         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
223         data.insert(data.end(), ss.begin(), ss.end());
224         return EncodeBase58Check(data);
225     }
226
227     std::string operator()(const libzcash::SaplingPaymentAddress& zaddr) const
228     {
229         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
230         ss << zaddr;
231         // ConvertBits requires unsigned char, but CDataStream uses char
232         std::vector<unsigned char> seraddr(ss.begin(), ss.end());
233         std::vector<unsigned char> data;
234         // See calculation comment below
235         data.reserve((seraddr.size() * 8 + 4) / 5);
236         ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, seraddr.begin(), seraddr.end());
237         return bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS), data);
238     }
239
240     std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
241 };
242
243 class ViewingKeyEncoder : public boost::static_visitor<std::string>
244 {
245 private:
246     const CChainParams& m_params;
247
248 public:
249     ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}
250
251     std::string operator()(const libzcash::SproutViewingKey& vk) const
252     {
253         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
254         ss << vk;
255         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY);
256         data.insert(data.end(), ss.begin(), ss.end());
257         std::string ret = EncodeBase58Check(data);
258         memory_cleanse(data.data(), data.size());
259         return ret;
260     }
261
262     std::string operator()(const libzcash::SaplingIncomingViewingKey& vk) const
263     {
264         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
265         ss << vk;
266         std::vector<unsigned char> serkey(ss.begin(), ss.end());
267         std::vector<unsigned char> data;
268         ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
269         std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY), data);
270         memory_cleanse(serkey.data(), serkey.size());
271         memory_cleanse(data.data(), data.size());
272         return ret;
273     }
274
275     std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
276 };
277
278 class SpendingKeyEncoder : public boost::static_visitor<std::string>
279 {
280 private:
281     const CChainParams& m_params;
282
283 public:
284     SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}
285
286     std::string operator()(const libzcash::SproutSpendingKey& zkey) const
287     {
288         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
289         ss << zkey;
290         std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY);
291         data.insert(data.end(), ss.begin(), ss.end());
292         std::string ret = EncodeBase58Check(data);
293         memory_cleanse(data.data(), data.size());
294         return ret;
295     }
296
297     std::string operator()(const libzcash::SaplingExtendedSpendingKey& zkey) const
298     {
299         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
300         ss << zkey;
301         // ConvertBits requires unsigned char, but CDataStream uses char
302         std::vector<unsigned char> serkey(ss.begin(), ss.end());
303         std::vector<unsigned char> data;
304         // See calculation comment below
305         data.reserve((serkey.size() * 8 + 4) / 5);
306         ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
307         std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY), data);
308         memory_cleanse(serkey.data(), serkey.size());
309         memory_cleanse(data.data(), data.size());
310         return ret;
311     }
312
313     std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
314 };
315
316 // Sizes of SaplingPaymentAddress and SaplingSpendingKey after
317 // ConvertBits<8, 5, true>(). The calculations below take the
318 // regular serialized size in bytes, convert to bits, and then
319 // perform ceiling division to get the number of 5-bit clusters.
320 const size_t ConvertedSaplingPaymentAddressSize = ((32 + 11) * 8 + 4) / 5;
321 const size_t ConvertedSaplingExtendedSpendingKeySize = (ZIP32_XSK_SIZE * 8 + 4) / 5;
322 const size_t ConvertedSaplingIncomingViewingKeySize = (32 * 8 + 4) / 5;
323 } // namespace
324
325 CKey DecodeSecret(const std::string& str)
326 {
327     CKey key;
328     std::vector<unsigned char> data;
329     if (DecodeBase58Check(str, data)) {
330         const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
331         if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
332             std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
333             bool compressed = data.size() == 33 + privkey_prefix.size();
334             key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
335         }
336     }
337     memory_cleanse(data.data(), data.size());
338     return key;
339 }
340
341 std::string EncodeSecret(const CKey& key)
342 {
343     assert(key.IsValid());
344     std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
345     data.insert(data.end(), key.begin(), key.end());
346     if (key.IsCompressed()) {
347         data.push_back(1);
348     }
349     std::string ret = EncodeBase58Check(data);
350     memory_cleanse(data.data(), data.size());
351     return ret;
352 }
353
354 CExtPubKey DecodeExtPubKey(const std::string& str)
355 {
356     CExtPubKey key;
357     std::vector<unsigned char> data;
358     if (DecodeBase58Check(str, data)) {
359         const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
360         if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
361             key.Decode(data.data() + prefix.size());
362         }
363     }
364     return key;
365 }
366
367 std::string EncodeExtPubKey(const CExtPubKey& key)
368 {
369     std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
370     size_t size = data.size();
371     data.resize(size + BIP32_EXTKEY_SIZE);
372     key.Encode(data.data() + size);
373     std::string ret = EncodeBase58Check(data);
374     return ret;
375 }
376
377 CExtKey DecodeExtKey(const std::string& str)
378 {
379     CExtKey key;
380     std::vector<unsigned char> data;
381     if (DecodeBase58Check(str, data)) {
382         const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
383         if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
384             key.Decode(data.data() + prefix.size());
385         }
386     }
387     return key;
388 }
389
390 std::string EncodeExtKey(const CExtKey& key)
391 {
392     std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
393     size_t size = data.size();
394     data.resize(size + BIP32_EXTKEY_SIZE);
395     key.Encode(data.data() + size);
396     std::string ret = EncodeBase58Check(data);
397     memory_cleanse(data.data(), data.size());
398     return ret;
399 }
400
401 std::string EncodeDestination(const CTxDestination& dest)
402 {
403     return boost::apply_visitor(DestinationEncoder(Params()), dest);
404 }
405
406 std::vector<unsigned char> GetDestinationBytes(const CTxDestination& dest)
407 {
408     return boost::apply_visitor(DestinationBytes(), dest);
409 }
410
411 uint160 GetDestinationID(const CTxDestination dest)
412 {
413     return boost::apply_visitor(DestinationID(), dest);
414 }
415
416 CTxDestination DecodeDestination(const std::string& str)
417 {
418     return DecodeDestination(str, Params());
419 }
420
421 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
422 {
423     return IsValidDestination(DecodeDestination(str, params));
424 }
425
426 bool IsValidDestinationString(const std::string& str)
427 {
428     return IsValidDestinationString(str, Params());
429 }
430
431 std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
432 {
433     return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr);
434 }
435
436 libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
437 {
438     std::vector<unsigned char> data;
439     if (DecodeBase58Check(str, data)) {
440         const std::vector<unsigned char>& zaddr_prefix = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
441         if ((data.size() == libzcash::SerializedSproutPaymentAddressSize + zaddr_prefix.size()) &&
442             std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) {
443             CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end());
444             CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
445             libzcash::SproutPaymentAddress ret;
446             ss >> ret;
447             return ret;
448         }
449     }
450     data.clear();
451     auto bech = bech32::Decode(str);
452     if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
453         bech.second.size() == ConvertedSaplingPaymentAddressSize) {
454         // Bech32 decoding
455         data.reserve((bech.second.size() * 5) / 8);
456         if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
457             CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
458             libzcash::SaplingPaymentAddress ret;
459             ss >> ret;
460             return ret;
461         }
462     }
463     return libzcash::InvalidEncoding();
464 }
465
466 bool IsValidPaymentAddressString(const std::string& str, uint32_t consensusBranchId) {
467     return IsValidPaymentAddress(DecodePaymentAddress(str), consensusBranchId);
468 }
469
470 std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
471 {
472     return boost::apply_visitor(ViewingKeyEncoder(Params()), vk);
473 }
474
475 libzcash::ViewingKey DecodeViewingKey(const std::string& str)
476 {
477     std::vector<unsigned char> data;
478     if (DecodeBase58Check(str, data)) {
479         const std::vector<unsigned char>& vk_prefix = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY);
480         if ((data.size() == libzcash::SerializedSproutViewingKeySize + vk_prefix.size()) &&
481             std::equal(vk_prefix.begin(), vk_prefix.end(), data.begin())) {
482             CSerializeData serialized(data.begin() + vk_prefix.size(), data.end());
483             CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
484             libzcash::SproutViewingKey ret;
485             ss >> ret;
486             memory_cleanse(serialized.data(), serialized.size());
487             memory_cleanse(data.data(), data.size());
488             return ret;
489         }
490     }
491     data.clear();
492     auto bech = bech32::Decode(str);
493     if(bech.first == Params().Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY) &&
494        bech.second.size() == ConvertedSaplingIncomingViewingKeySize) {
495         // Bech32 decoding
496         data.reserve((bech.second.size() * 5) / 8);
497         if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
498             CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
499             libzcash::SaplingIncomingViewingKey ret;
500             ss >> ret;
501             memory_cleanse(data.data(), data.size());
502             return ret;
503         }
504     }
505     return libzcash::InvalidEncoding();
506 }
507
508 std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
509 {
510     return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey);
511 }
512
513 libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
514 {
515     std::vector<unsigned char> data;
516     if (DecodeBase58Check(str, data)) {
517         const std::vector<unsigned char>& zkey_prefix = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY);
518         if ((data.size() == libzcash::SerializedSproutSpendingKeySize + zkey_prefix.size()) &&
519             std::equal(zkey_prefix.begin(), zkey_prefix.end(), data.begin())) {
520             CSerializeData serialized(data.begin() + zkey_prefix.size(), data.end());
521             CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
522             libzcash::SproutSpendingKey ret;
523             ss >> ret;
524             memory_cleanse(serialized.data(), serialized.size());
525             memory_cleanse(data.data(), data.size());
526             return ret;
527         }
528     }
529     data.clear();
530     auto bech = bech32::Decode(str);
531     if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) &&
532         bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) {
533         // Bech32 decoding
534         data.reserve((bech.second.size() * 5) / 8);
535         if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
536             CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
537             libzcash::SaplingExtendedSpendingKey ret;
538             ss >> ret;
539             memory_cleanse(data.data(), data.size());
540             return ret;
541         }
542     }
543     memory_cleanse(data.data(), data.size());
544     return libzcash::InvalidEncoding();
545 }
546
547 uint160 CCrossChainRPCData::GetConditionID(uint160 cid, int32_t condition)
548 {
549     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
550     hw << condition;
551     hw << cid;
552     uint256 chainHash = hw.GetHash();
553     return Hash160(chainHash.begin(), chainHash.end());
554 }
555
556 uint160 CCrossChainRPCData::GetConditionID(std::string name, int32_t condition)
557 {
558     uint160 parent;
559     uint160 cid = CIdentity::GetID(name, parent);
560
561     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
562     hw << condition;
563     hw << cid;
564     uint256 chainHash = hw.GetHash();
565     return Hash160(chainHash.begin(), chainHash.end());
566 }
567
568 std::string TrimLeading(const std::string &Name, unsigned char ch)
569 {
570     std::string nameCopy = Name;
571     int removeSpaces;
572     for (removeSpaces = 0; removeSpaces < nameCopy.size(); removeSpaces++)
573     {
574         if (nameCopy[removeSpaces] != ch)
575         {
576             break;
577         }
578     }
579     if (removeSpaces)
580     {
581         nameCopy.erase(nameCopy.begin(), nameCopy.begin() + removeSpaces);
582     }
583     return nameCopy;
584 }
585
586 std::string TrimTrailing(const std::string &Name, unsigned char ch)
587 {
588     std::string nameCopy = Name;
589     int removeSpaces;
590     for (removeSpaces = nameCopy.size() - 1; removeSpaces >= 0; removeSpaces--)
591     {
592         if (nameCopy[removeSpaces] != ch)
593         {
594             break;
595         }
596     }
597     nameCopy.resize(nameCopy.size() - ((nameCopy.size() - 1) - removeSpaces));
598     return nameCopy;
599 }
600
601 std::string TrimSpaces(const std::string &Name)
602 {
603     return TrimTrailing(TrimLeading(Name, ' '), ' ');
604 }
605
606 // this will add the current Verus chain name to subnames if it is not present
607 // on both id and chain names
608 std::vector<std::string> ParseSubNames(const std::string &Name, std::string &ChainOut, bool displayfilter, bool addVerus)
609 {
610     std::string nameCopy = Name;
611     std::string invalidChars = "\\/:*?\"<>|";
612     if (displayfilter)
613     {
614         invalidChars += "\n\t\r\b\t\v\f\x1B";
615     }
616     for (int i = 0; i < nameCopy.size(); i++)
617     {
618         if (invalidChars.find(nameCopy[i]) != std::string::npos)
619         {
620             return std::vector<std::string>();
621         }
622     }
623
624     std::vector<std::string> retNames;
625     boost::split(retNames, nameCopy, boost::is_any_of("@"));
626     if (!retNames.size() || retNames.size() > 2)
627     {
628         return std::vector<std::string>();
629     }
630
631     bool explicitChain = false;
632     if (retNames.size() == 2)
633     {
634         ChainOut = retNames[1];
635         explicitChain = true;
636     }    
637
638     nameCopy = retNames[0];
639     boost::split(retNames, nameCopy, boost::is_any_of("."));
640
641     int numRetNames = retNames.size();
642
643     if (addVerus)
644     {
645         if (explicitChain)
646         {
647             std::vector<std::string> chainOutNames;
648             boost::split(chainOutNames, ChainOut, boost::is_any_of("."));
649             if (boost::to_lower_copy(chainOutNames.back()) != boost::to_lower_copy(VERUS_CHAINNAME))
650             {
651                 chainOutNames.push_back(VERUS_CHAINNAME);
652             }
653         }
654         if (boost::to_lower_copy(retNames.back()) != boost::to_lower_copy(VERUS_CHAINNAME))
655         {
656             retNames.push_back(VERUS_CHAINNAME);
657         }
658     }
659
660     for (int i = 0; i < retNames.size(); i++)
661     {
662         if (retNames[i].size() > KOMODO_ASSETCHAIN_MAXLEN - 1)
663         {
664             retNames[i] = std::string(retNames[i], 0, (KOMODO_ASSETCHAIN_MAXLEN - 1));
665         }
666         // spaces are allowed, but no sub-name can have leading or trailing spaces
667         if (!retNames[i].size() || retNames[i] != TrimTrailing(TrimLeading(retNames[i], ' '), ' '))
668         {
669             return std::vector<std::string>();
670         }
671     }
672
673     // if no explicit chain is specified, default to chain of the ID
674     if (!explicitChain && retNames.size())
675     {
676         for (int i = 1; i < retNames.size(); i++)
677         {
678             if (ChainOut.size())
679             {
680                 ChainOut = ChainOut + ".";
681             }
682             ChainOut = ChainOut + retNames[i];
683         }
684     }
685
686     return retNames;
687 }
688
689 // takes a multipart name, either complete or partially processed with a Parent hash,
690 // hash its parent names into a parent ID and return the parent hash and cleaned, single name
691 std::string CleanName(const std::string &Name, uint160 &Parent, bool displayfilter)
692 {
693     std::string chainName;
694     std::vector<std::string> subNames = ParseSubNames(Name, chainName);
695
696     if (!subNames.size())
697     {
698         return "";
699     }
700
701     if (!Parent.IsNull() &&
702         boost::to_lower_copy(subNames.back()) == boost::to_lower_copy(VERUS_CHAINNAME))
703     {
704         subNames.pop_back();
705     }
706
707     for (int i = subNames.size() - 1; i > 0; i--)
708     {
709         std::string parentNameStr = boost::algorithm::to_lower_copy(subNames[i]);
710         const char *parentName = parentNameStr.c_str();
711         uint256 idHash;
712
713         if (Parent.IsNull())
714         {
715             idHash = Hash(parentName, parentName + parentNameStr.size());
716         }
717         else
718         {
719             idHash = Hash(parentName, parentName + strlen(parentName));
720             idHash = Hash(Parent.begin(), Parent.end(), idHash.begin(), idHash.end());
721         }
722         Parent = Hash160(idHash.begin(), idHash.end());
723         //printf("uint160 for parent %s: %s\n", parentName, Parent.GetHex().c_str());
724     }
725     return subNames[0];
726 }
727
728 CNameReservation::CNameReservation(const CTransaction &tx, int *pOutNum)
729 {
730     for (int i = 0; i < tx.vout.size(); i++)
731     {
732         COptCCParams p;
733         if (IsPayToCryptoCondition(tx.vout[i].scriptPubKey, p))
734         {
735             if (p.evalCode == EVAL_IDENTITY_RESERVATION)
736             {
737                 FromVector(p.vData[0], *this);
738                 return;
739             }
740         }
741     }
742 }
743
744 CIdentity::CIdentity(const CScript &scriptPubKey)
745 {
746     COptCCParams p;
747     if (IsPayToCryptoCondition(scriptPubKey, p) && p.IsValid() && p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size())
748     {
749         *this = CIdentity(p.vData[0]);
750     }
751 }
752
753 CIdentityID CIdentity::GetID(const std::string &Name, uint160 &parent)
754 {
755     std::string cleanName = CleanName(Name, parent);
756
757     std::string subName = boost::algorithm::to_lower_copy(cleanName);
758     const char *idName = subName.c_str();
759     //printf("hashing: %s, %s\n", idName, parent.GetHex().c_str());
760
761     uint256 idHash;
762     if (parent.IsNull())
763     {
764         idHash = Hash(idName, idName + strlen(idName));
765     }
766     else
767     {
768         idHash = Hash(idName, idName + strlen(idName));
769         idHash = Hash(parent.begin(), parent.end(), idHash.begin(), idHash.end());
770     }
771     return Hash160(idHash.begin(), idHash.end());
772 }
773
774 CIdentityID CIdentity::GetID(const std::string &Name) const
775 {
776     uint160 parent;
777     std::string cleanName = CleanName(Name, parent);
778
779     std::string subName = boost::algorithm::to_lower_copy(cleanName);
780     const char *idName = subName.c_str();
781     //printf("hashing: %s, %s\n", idName, parent.GetHex().c_str());
782
783     uint256 idHash;
784     if (parent.IsNull())
785     {
786         idHash = Hash(idName, idName + strlen(idName));
787     }
788     else
789     {
790         idHash = Hash(idName, idName + strlen(idName));
791         idHash = Hash(parent.begin(), parent.end(), idHash.begin(), idHash.end());
792
793     }
794     return Hash160(idHash.begin(), idHash.end());
795 }
796
797 CIdentityID CIdentity::GetID() const
798 {
799     uint160 Parent = parent;
800     return GetID(name, Parent);
801 }
802
803 uint160 CCrossChainRPCData::GetID(std::string name)
804 {
805     uint160 parent;
806     //printf("uint160 for name %s: %s\n", name.c_str(), CIdentity::GetID(name, parent).GetHex().c_str());
807     return CIdentity::GetID(name, parent);
808 }
809
810 CScript CIdentity::TransparentOutput() const
811 {
812     CConditionObj<CIdentity> ccObj = CConditionObj<CIdentity>(0, std::vector<CTxDestination>({CTxDestination(CIdentityID(GetID()))}), 1);
813     return MakeMofNCCScript(ccObj);
814 }
815
816 CScript CIdentity::TransparentOutput(const CIdentityID &destinationID)
817 {
818     CConditionObj<CIdentity> ccObj = CConditionObj<CIdentity>(0, std::vector<CTxDestination>({destinationID}), 1);
819     return MakeMofNCCScript(ccObj);
820 }
821
822 CScript CIdentity::IdentityUpdateOutputScript() const
823 {
824     CScript ret;
825
826     if (!IsValid())
827     {
828         return ret;
829     }
830
831     std::vector<CTxDestination> dests1({CTxDestination(CIdentityID(GetID()))});
832     CConditionObj<CIdentity> primary(EVAL_IDENTITY_PRIMARY, dests1, 1, this);
833     std::vector<CTxDestination> dests2({CTxDestination(CIdentityID(revocationAuthority))});
834     CConditionObj<CIdentity> revocation(EVAL_IDENTITY_REVOKE, dests2, 1);
835     std::vector<CTxDestination> dests3({CTxDestination(CIdentityID(recoveryAuthority))});
836     CConditionObj<CIdentity> recovery(EVAL_IDENTITY_RECOVER, dests3, 1);
837
838     ret = MakeMofNCCScript(1, primary, revocation, recovery);
839     return ret;
840 }
841
This page took 0.070431 seconds and 4 git commands to generate.