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