Raven Core  3.0.0
P2P Digital Currency
assets.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2019 The Raven Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 //#include <amount.h>
6 //#include <base58.h>
7 #include "assets/assets.h"
8 #include "assets/assetdb.h"
9 #include <map>
10 #include "tinyformat.h"
11 //#include <rpc/server.h>
12 //#include <script/standard.h>
13 //#include <utilstrencodings.h>
14 
15 #include "amount.h"
16 #include "base58.h"
17 #include "chain.h"
18 #include "consensus/validation.h"
19 #include "core_io.h"
20 #include "httpserver.h"
21 #include "validation.h"
22 #include "net.h"
23 #include "policy/feerate.h"
24 #include "policy/fees.h"
25 #include "policy/policy.h"
26 #include "policy/rbf.h"
27 #include "rpc/mining.h"
28 #include "rpc/safemode.h"
29 #include "rpc/server.h"
30 #include "script/sign.h"
31 #include "timedata.h"
32 #include "util.h"
33 #include "utilmoneystr.h"
34 #include "wallet/coincontrol.h"
35 #include "wallet/feebumper.h"
36 #include "wallet/wallet.h"
37 #include "wallet/walletdb.h"
38 
39 void CheckIPFSTxidMessage(const std::string &message, int64_t expireTime)
40 {
41  size_t msglen = message.length();
42  if (msglen == 46 || msglen == 64) {
43  if (msglen == 64 && !AreMessagingDeployed()) {
44  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Invalid txid hash, only ipfs hashes available until RIP5 is activated"));
45  }
46  } else {
47  if (msglen)
48  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Invalid IPFS hash (must be 46 characters), Txid hashes (must be 64 characters)"));
49  }
50 
51  bool fNotIPFS = false;
52  if (message.substr(0, 2) != "Qm") {
53  fNotIPFS = true;
54  if (!AreMessagingDeployed())
55  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Invalid ipfs hash. Please use a valid ipfs hash. They usually start with Qm"));
56  }
57 
58  if (fNotIPFS && !IsHex(message))
59  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Invalid IPFS/Txid hash"));
60 
61  if (expireTime < 0)
62  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Expire time must be a positive number"));
63 }
64 
65 void CheckRestrictedAssetTransferInputs(const CWalletTx& transaction, const std::string& asset_name) {
66  // Do a validity check before commiting the transaction
67  if (IsAssetNameAnRestricted(asset_name)) {
68  if (pcoinsTip && passets) {
69  for (auto input : transaction.tx->vin) {
70  const COutPoint &prevout = input.prevout;
71  const Coin &coin = pcoinsTip->AccessCoin(prevout);
72 
73  if (coin.IsAsset()) {
74  CAssetOutputEntry data;
75  if (!GetAssetData(coin.out.scriptPubKey, data))
76  throw JSONRPCError(RPC_DATABASE_ERROR, std::string(
77  _("Unable to get coin to verify restricted asset transfer from address")));
78 
79 
82  true)) {
83  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string(
84  _("Restricted asset transfer from address that has been frozen")));
85  }
86  }
87  }
88  }
89  }
90  }
91 }
92 
94 {
95  return AreAssetsDeployed() ? "" : "\nTHIS COMMAND IS NOT YET ACTIVE!\nhttps://github.com/RavenProject/rips/blob/master/rip-0002.mediawiki\n";
96 }
97 
99 {
100  return AreRestrictedAssetsDeployed() ? "" : "\nTHIS COMMAND IS NOT YET ACTIVE! Restricted assets must be active\n\n";
101 }
102 
103 std::string AssetTypeToString(AssetType& assetType)
104 {
105  switch (assetType)
106  {
107  case AssetType::ROOT: return "ROOT";
108  case AssetType::SUB: return "SUB";
109  case AssetType::UNIQUE: return "UNIQUE";
110  case AssetType::OWNER: return "OWNER";
111  case AssetType::MSGCHANNEL: return "MSGCHANNEL";
112  case AssetType::VOTE: return "VOTE";
113  case AssetType::REISSUE: return "REISSUE";
114  case AssetType::QUALIFIER: return "QUALIFIER";
115  case AssetType::SUB_QUALIFIER: return "SUB_QUALIFIER";
116  case AssetType::RESTRICTED: return "RESTRICTED";
117  case AssetType::INVALID: return "INVALID";
118  default: return "UNKNOWN";
119  }
120 }
121 
122 UniValue UnitValueFromAmount(const CAmount& amount, const std::string asset_name)
123 {
124 
125  auto currentActiveAssetCache = GetCurrentAssetCache();
126  if (!currentActiveAssetCache)
127  throw JSONRPCError(RPC_INTERNAL_ERROR, "Asset cache isn't available.");
128 
129  uint8_t units = OWNER_UNITS;
130  if (!IsAssetNameAnOwner(asset_name)) {
131  CNewAsset assetData;
132  if (!currentActiveAssetCache->GetAssetMetaDataIfExists(asset_name, assetData))
133  units = MAX_UNIT;
134  //throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't load asset from cache: " + asset_name);
135  else
136  units = assetData.units;
137  }
138 
139  return ValueFromAmount(amount, units);
140 }
141 
142 UniValue UpdateAddressTag(const JSONRPCRequest &request, const int8_t &flag)
143 {
144  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
145  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
146  return NullUniValue;
147  }
148 
149  ObserveSafeMode();
150  LOCK2(cs_main, pwallet->cs_wallet);
151 
152  EnsureWalletIsUnlocked(pwallet);
153 
154  // Check asset name and infer assetType
155  std::string tag_name = request.params[0].get_str();
156 
157  AssetType assetType;
158  std::string assetError = "";
159  if (!IsAssetNameValid(tag_name, assetType, assetError)) {
160  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + tag_name + std::string("\nError: ") + assetError);
161  }
162 
163  if (assetType != AssetType::QUALIFIER && assetType != AssetType::SUB_QUALIFIER) {
164  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unsupported asset type: ") + AssetTypeToString(assetType));
165  }
166 
167  std::string address = request.params[1].get_str();
168  CTxDestination destination = DecodeDestination(address);
169  if (!IsValidDestination(destination)) {
170  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + address);
171  }
172 
173  // Get the optional change address
174  std::string change_address = "";
175  if (request.params.size() > 2) {
176  change_address = request.params[2].get_str();
177  CTxDestination change_dest = DecodeDestination(change_address);
178  if (!IsValidDestination(change_dest)) {
179  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven change address: ") + change_address);
180  }
181  }
182 
183  CReserveKey reservekey(pwallet);
184  CWalletTx transaction;
185  CAmount nRequiredFee;
186  CCoinControl ctrl;
187 
188  ctrl.destChange = DecodeDestination(change_address);
189 
190  // If the optional change address wasn't given create a new change address for this wallet
191  if (change_address == "") {
192  CKeyID keyID;
193  std::string strFailReason;
194  if (!pwallet->CreateNewChangeAddress(reservekey, keyID, strFailReason))
195  throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
196 
197  change_address = EncodeDestination(keyID);
198  }
199 
200  std::pair<int, std::string> error;
201  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
202 
203  // Always transfer 1 of the qualifier tokens to the change address
204  vTransfers.emplace_back(std::make_pair(CAssetTransfer(tag_name, 1 * COIN), change_address));
205 
206  // Add the asset data with the flag to remove or add the tag 1 = Add, 0 = Remove
207  std::vector< std::pair<CNullAssetTxData, std::string> > vecAssetData;
208  vecAssetData.push_back(std::make_pair(CNullAssetTxData(tag_name, flag), address));
209 
210  // Create the Transaction
211  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee, &vecAssetData))
212  throw JSONRPCError(error.first, error.second);
213 
214  // Send the Transaction to the network
215  std::string txid;
216  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
217  throw JSONRPCError(error.first, error.second);
218 
219  // Display the transaction id
220  UniValue result(UniValue::VARR);
221  result.push_back(txid);
222  return result;
223 }
224 
225 UniValue UpdateAddressRestriction(const JSONRPCRequest &request, const int8_t &flag)
226 {
227  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
228  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
229  return NullUniValue;
230  }
231 
232  ObserveSafeMode();
233  LOCK2(cs_main, pwallet->cs_wallet);
234 
235  EnsureWalletIsUnlocked(pwallet);
236 
237  // Check asset name and infer assetType
238  std::string restricted_name = request.params[0].get_str();
239 
240  AssetType assetType;
241  std::string assetError = "";
242  if (!IsAssetNameValid(restricted_name, assetType, assetError)) {
243  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + restricted_name + std::string("\nError: ") + assetError);
244  }
245 
246  if (assetType != AssetType::RESTRICTED) {
247  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unsupported asset type: ") + AssetTypeToString(assetType));
248  }
249 
250  std::string address = request.params[1].get_str();
251  CTxDestination destination = DecodeDestination(address);
252  if (!IsValidDestination(destination)) {
253  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + address);
254  }
255 
256  // Get the optional change address
257  std::string change_address = "";
258  if (request.params.size() > 2) {
259  change_address = request.params[2].get_str();
260  CTxDestination change_dest = DecodeDestination(change_address);
261  if (!IsValidDestination(change_dest)) {
262  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven change address: ") + change_address);
263  }
264  }
265 
266  CReserveKey reservekey(pwallet);
267  CWalletTx transaction;
268  CAmount nRequiredFee;
269  CCoinControl ctrl;
270 
271  // If the optional change address wasn't given create a new change address for this wallet
272  if (change_address == "") {
273  CKeyID keyID;
274  std::string strFailReason;
275  if (!pwallet->CreateNewChangeAddress(reservekey, keyID, strFailReason))
276  throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
277 
278  change_address = EncodeDestination(keyID);
279  }
280 
281  std::pair<int, std::string> error;
282  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
283 
284  // Always transfer 1 of the restricted tokens to the change address
285  // Use the ROOT owner token to make this change occur. if $TOKEN -> Use TOKEN!
286  vTransfers.emplace_back(std::make_pair(CAssetTransfer(restricted_name.substr(1, restricted_name.size()) + OWNER_TAG, 1 * COIN), change_address));
287 
288  // Add the asset data with the flag to remove or add the tag 1 = Freeze, 0 = Unfreeze
289  std::vector< std::pair<CNullAssetTxData, std::string> > vecAssetData;
290  vecAssetData.push_back(std::make_pair(CNullAssetTxData(restricted_name.substr(0, restricted_name.size()), flag), address));
291 
292  // Create the Transaction
293  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee, &vecAssetData))
294  throw JSONRPCError(error.first, error.second);
295 
296  // Send the Transaction to the network
297  std::string txid;
298  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
299  throw JSONRPCError(error.first, error.second);
300 
301  // Display the transaction id
302  UniValue result(UniValue::VARR);
303  result.push_back(txid);
304  return result;
305 }
306 
307 UniValue UpdateGlobalRestrictedAsset(const JSONRPCRequest &request, const int8_t &flag)
308 {
309  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
310  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
311  return NullUniValue;
312  }
313 
314  ObserveSafeMode();
315  LOCK2(cs_main, pwallet->cs_wallet);
316 
317  EnsureWalletIsUnlocked(pwallet);
318 
319  // Check asset name and infer assetType
320  std::string restricted_name = request.params[0].get_str();
321 
322  AssetType assetType;
323  std::string assetError = "";
324  if (!IsAssetNameValid(restricted_name, assetType, assetError)) {
325  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + restricted_name + std::string("\nError: ") + assetError);
326  }
327 
328  if (assetType != AssetType::RESTRICTED) {
329  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unsupported asset type: ") + AssetTypeToString(assetType));
330  }
331 
332  // Get the optional change address
333  std::string change_address = "";
334  if (request.params.size() > 1) {
335  change_address = request.params[1].get_str();
336  CTxDestination change_dest = DecodeDestination(change_address);
337  if (!IsValidDestination(change_dest)) {
338  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven change address: ") + change_address);
339  }
340  }
341 
342  CReserveKey reservekey(pwallet);
343  CWalletTx transaction;
344  CAmount nRequiredFee;
345  CCoinControl ctrl;
346 
347  // If the optional change address wasn't given create a new change address for this wallet
348  if (change_address == "") {
349  CKeyID keyID;
350  std::string strFailReason;
351  if (!pwallet->CreateNewChangeAddress(reservekey, keyID, strFailReason))
352  throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
353 
354  change_address = EncodeDestination(keyID);
355  }
356 
357  std::pair<int, std::string> error;
358  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
359 
360  // Always transfer 1 of the restricted tokens to the change address
361  // Use the ROOT owner token to make this change occur. if $TOKEN -> Use TOKEN!
362  vTransfers.emplace_back(std::make_pair(CAssetTransfer(restricted_name.substr(1, restricted_name.size()) + OWNER_TAG, 1 * COIN), change_address));
363 
364  // Add the global asset data, 1 = Freeze all transfers, 0 = Allow transfers
365  std::vector<CNullAssetTxData> vecGlobalAssetData;
366  vecGlobalAssetData.push_back(CNullAssetTxData(restricted_name.substr(0, restricted_name.size()), flag));
367 
368  // Create the Transaction
369  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee, nullptr, &vecGlobalAssetData))
370  throw JSONRPCError(error.first, error.second);
371 
372  // Send the Transaction to the network
373  std::string txid;
374  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
375  throw JSONRPCError(error.first, error.second);
376 
377  // Display the transaction id
378  UniValue result(UniValue::VARR);
379  result.push_back(txid);
380  return result;
381 }
382 
384 {
385  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 1 || request.params.size() > 8)
386  throw std::runtime_error(
387  "issue \"asset_name\" qty \"( to_address )\" \"( change_address )\" ( units ) ( reissuable ) ( has_ipfs ) \"( ipfs_hash )\"\n"
389  "\nIssue an asset, subasset or unique asset.\n"
390  "Asset name must not conflict with any existing asset.\n"
391  "Unit as the number of decimals precision for the asset (0 for whole units (\"1\"), 8 for max precision (\"1.00000000\")\n"
392  "Reissuable is true/false for whether additional units can be issued by the original issuer.\n"
393  "If issuing a unique asset these values are required (and will be defaulted to): qty=1, units=0, reissuable=false.\n"
394 
395  "\nArguments:\n"
396  "1. \"asset_name\" (string, required) a unique name\n"
397  "2. \"qty\" (numeric, optional, default=1) the number of units to be issued\n"
398  "3. \"to_address\" (string), optional, default=\"\"), address asset will be sent to, if it is empty, address will be generated for you\n"
399  "4. \"change_address\" (string), optional, default=\"\"), address the the rvn change will be sent to, if it is empty, change address will be generated for you\n"
400  "5. \"units\" (integer, optional, default=0, min=0, max=8), the number of decimals precision for the asset (0 for whole units (\"1\"), 8 for max precision (\"1.00000000\")\n"
401  "6. \"reissuable\" (boolean, optional, default=true (false for unique assets)), whether future reissuance is allowed\n"
402  "7. \"has_ipfs\" (boolean, optional, default=false), whether ifps hash is going to be added to the asset\n"
403  "8. \"ipfs_hash\" (string, optional but required if has_ipfs = 1), an ipfs hash or a txid hash once RIP5 is activated\n"
404 
405  "\nResult:\n"
406  "\"txid\" (string) The transaction id\n"
407 
408  "\nExamples:\n"
409  + HelpExampleCli("issue", "\"ASSET_NAME\" 1000")
410  + HelpExampleCli("issue", "\"ASSET_NAME\" 1000 \"myaddress\"")
411  + HelpExampleCli("issue", "\"ASSET_NAME\" 1000 \"myaddress\" \"changeaddress\" 4")
412  + HelpExampleCli("issue", "\"ASSET_NAME\" 1000 \"myaddress\" \"changeaddress\" 2 true")
413  + HelpExampleCli("issue", "\"ASSET_NAME\" 1000 \"myaddress\" \"changeaddress\" 8 false true QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E")
414  + HelpExampleCli("issue", "\"ASSET_NAME/SUB_ASSET\" 1000 \"myaddress\" \"changeaddress\" 2 true")
415  + HelpExampleCli("issue", "\"ASSET_NAME#uniquetag\"")
416  );
417 
418  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
419  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
420  return NullUniValue;
421  }
422 
423  ObserveSafeMode();
424  LOCK2(cs_main, pwallet->cs_wallet);
425 
426  EnsureWalletIsUnlocked(pwallet);
427 
428  // Check asset name and infer assetType
429  std::string assetName = request.params[0].get_str();
430  AssetType assetType;
431  std::string assetError = "";
432  if (!IsAssetNameValid(assetName, assetType, assetError)) {
433  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + assetName + std::string("\nError: ") + assetError);
434  }
435 
436  // Push the user to use the issue restrictd rpc call if they are trying to issue a restricted asset
437  if (assetType == AssetType::RESTRICTED) {
438  throw (JSONRPCError(RPC_INVALID_PARAMETER, std::string("Use the rpc call issuerestricted to issue a restricted asset")));
439  }
440 
441  // Check for unsupported asset types
442  if (assetType == AssetType::VOTE || assetType == AssetType::REISSUE || assetType == AssetType::OWNER || assetType == AssetType::INVALID) {
443  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unsupported asset type: ") + AssetTypeToString(assetType));
444  }
445 
446  CAmount nAmount = COIN;
447  if (request.params.size() > 1)
448  nAmount = AmountFromValue(request.params[1]);
449 
450  std::string address = "";
451  if (request.params.size() > 2)
452  address = request.params[2].get_str();
453 
454  if (!address.empty()) {
455  CTxDestination destination = DecodeDestination(address);
456  if (!IsValidDestination(destination)) {
457  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + address);
458  }
459  } else {
460  // Create a new address
461  std::string strAccount;
462 
463  if (!pwallet->IsLocked()) {
464  pwallet->TopUpKeyPool();
465  }
466 
467  // Generate a new key that is added to wallet
468  CPubKey newKey;
469  if (!pwallet->GetKeyFromPool(newKey)) {
470  throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
471  }
472  CKeyID keyID = newKey.GetID();
473 
474  pwallet->SetAddressBook(keyID, strAccount, "receive");
475 
476  address = EncodeDestination(keyID);
477  }
478 
479  std::string change_address = "";
480  if (request.params.size() > 3) {
481  change_address = request.params[3].get_str();
482  if (!change_address.empty()) {
483  CTxDestination destination = DecodeDestination(change_address);
484  if (!IsValidDestination(destination)) {
486  std::string("Invalid Change Address: Invalid Raven address: ") + change_address);
487  }
488  }
489  }
490 
491  int units = 0;
492  if (request.params.size() > 4)
493  units = request.params[4].get_int();
494 
495  bool reissuable = assetType != AssetType::UNIQUE && assetType != AssetType::MSGCHANNEL && assetType != AssetType::QUALIFIER && assetType != AssetType::SUB_QUALIFIER;
496  if (request.params.size() > 5)
497  reissuable = request.params[5].get_bool();
498 
499  bool has_ipfs = false;
500  if (request.params.size() > 6)
501  has_ipfs = request.params[6].get_bool();
502 
503  // Check the ipfs
504  std::string ipfs_hash = "";
505  bool fMessageCheck = false;
506  if (request.params.size() > 7 && has_ipfs) {
507  fMessageCheck = true;
508  ipfs_hash = request.params[7].get_str();
509  }
510 
511  // Reissues don't have an expire time
512  int64_t expireTime = 0;
513 
514  // Check the message data
515  if (fMessageCheck)
516  CheckIPFSTxidMessage(ipfs_hash, expireTime);
517 
518  // check for required unique asset params
519  if ((assetType == AssetType::UNIQUE || assetType == AssetType::MSGCHANNEL) && (nAmount != COIN || units != 0 || reissuable)) {
520  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameters for issuing a unique asset."));
521  }
522 
523  // check for required unique asset params
524  if ((assetType == AssetType::QUALIFIER || assetType == AssetType::SUB_QUALIFIER) && (nAmount < QUALIFIER_ASSET_MIN_AMOUNT || nAmount > QUALIFIER_ASSET_MAX_AMOUNT || units != 0 || reissuable)) {
525  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameters for issuing a qualifier asset."));
526  }
527 
528  CNewAsset asset(assetName, nAmount, units, reissuable ? 1 : 0, has_ipfs ? 1 : 0, DecodeAssetData(ipfs_hash));
529 
530  CReserveKey reservekey(pwallet);
531  CWalletTx transaction;
532  CAmount nRequiredFee;
533  std::pair<int, std::string> error;
534 
535  CCoinControl crtl;
536  crtl.destChange = DecodeDestination(change_address);
537 
538  // Create the Transaction
539  if (!CreateAssetTransaction(pwallet, crtl, asset, address, error, transaction, reservekey, nRequiredFee))
540  throw JSONRPCError(error.first, error.second);
541 
542  // Send the Transaction to the network
543  std::string txid;
544  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
545  throw JSONRPCError(error.first, error.second);
546 
547  UniValue result(UniValue::VARR);
548  result.push_back(txid);
549  return result;
550 }
551 
553 {
554  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 2 || request.params.size() > 5)
555  throw std::runtime_error(
556  "issueunique \"root_name\" [asset_tags] ( [ipfs_hashes] ) \"( to_address )\" \"( change_address )\"\n"
558  "\nIssue unique asset(s).\n"
559  "root_name must be an asset you own.\n"
560  "An asset will be created for each element of asset_tags.\n"
561  "If provided ipfs_hashes must be the same length as asset_tags.\n"
562  "Five (5) RVN will be burned for each asset created.\n"
563 
564  "\nArguments:\n"
565  "1. \"root_name\" (string, required) name of the asset the unique asset(s) are being issued under\n"
566  "2. \"asset_tags\" (array, required) the unique tag for each asset which is to be issued\n"
567  "3. \"ipfs_hashes\" (array, optional) ipfs hashes or txid hashes corresponding to each supplied tag (should be same size as \"asset_tags\")\n"
568  "4. \"to_address\" (string, optional, default=\"\"), address assets will be sent to, if it is empty, address will be generated for you\n"
569  "5. \"change_address\" (string, optional, default=\"\"), address the the rvn change will be sent to, if it is empty, change address will be generated for you\n"
570 
571  "\nResult:\n"
572  "\"txid\" (string) The transaction id\n"
573 
574  "\nExamples:\n"
575  + HelpExampleCli("issueunique", "\"MY_ASSET\" \'[\"primo\",\"secundo\"]\'")
576  + HelpExampleCli("issueunique", "\"MY_ASSET\" \'[\"primo\",\"secundo\"]\' \'[\"first_hash\",\"second_hash\"]\'")
577  );
578 
579  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
580  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
581  return NullUniValue;
582  }
583 
584  ObserveSafeMode();
585  LOCK2(cs_main, pwallet->cs_wallet);
586 
587  EnsureWalletIsUnlocked(pwallet);
588 
589 
590  const std::string rootName = request.params[0].get_str();
591  AssetType assetType;
592  std::string assetError = "";
593  if (!IsAssetNameValid(rootName, assetType, assetError)) {
594  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + rootName + std::string("\nError: ") + assetError);
595  }
596  if (assetType != AssetType::ROOT && assetType != AssetType::SUB) {
597  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Root asset must be a regular top-level or sub-asset."));
598  }
599 
600  const UniValue& assetTags = request.params[1];
601  if (!assetTags.isArray() || assetTags.size() < 1) {
602  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Asset tags must be a non-empty array."));
603  }
604 
605  const UniValue& ipfsHashes = request.params[2];
606  if (!ipfsHashes.isNull()) {
607  if (!ipfsHashes.isArray() || ipfsHashes.size() != assetTags.size()) {
608  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("If provided, IPFS hashes must be an array of the same size as the asset tags array."));
609  }
610  }
611 
612  std::string address = "";
613  if (request.params.size() > 3)
614  address = request.params[3].get_str();
615 
616  if (!address.empty()) {
617  CTxDestination destination = DecodeDestination(address);
618  if (!IsValidDestination(destination)) {
619  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + address);
620  }
621  } else {
622  // Create a new address
623  std::string strAccount;
624 
625  if (!pwallet->IsLocked()) {
626  pwallet->TopUpKeyPool();
627  }
628 
629  // Generate a new key that is added to wallet
630  CPubKey newKey;
631  if (!pwallet->GetKeyFromPool(newKey)) {
632  throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
633  }
634  CKeyID keyID = newKey.GetID();
635 
636  pwallet->SetAddressBook(keyID, strAccount, "receive");
637 
638  address = EncodeDestination(keyID);
639  }
640 
641  std::string changeAddress = "";
642  if (request.params.size() > 4)
643  changeAddress = request.params[4].get_str();
644  if (!changeAddress.empty()) {
645  CTxDestination destination = DecodeDestination(changeAddress);
646  if (!IsValidDestination(destination)) {
648  std::string("Invalid Change Address: Invalid Raven address: ") + changeAddress);
649  }
650  }
651 
652  std::vector<CNewAsset> assets;
653  for (int i = 0; i < (int)assetTags.size(); i++) {
654  std::string tag = assetTags[i].get_str();
655 
656  if (!IsUniqueTagValid(tag)) {
657  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unique asset tag is invalid: " + tag));
658  }
659 
660  std::string assetName = GetUniqueAssetName(rootName, tag);
661  CNewAsset asset;
662 
663  if (ipfsHashes.isNull())
664  {
666  }
667  else
668  {
670  DecodeAssetData(ipfsHashes[i].get_str()));
671  }
672 
673  assets.push_back(asset);
674  }
675 
676  CReserveKey reservekey(pwallet);
677  CWalletTx transaction;
678  CAmount nRequiredFee;
679  std::pair<int, std::string> error;
680 
681  CCoinControl crtl;
682 
683  crtl.destChange = DecodeDestination(changeAddress);
684 
685  // Create the Transaction
686  if (!CreateAssetTransaction(pwallet, crtl, assets, address, error, transaction, reservekey, nRequiredFee))
687  throw JSONRPCError(error.first, error.second);
688 
689  // Send the Transaction to the network
690  std::string txid;
691  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
692  throw JSONRPCError(error.first, error.second);
693 
694  UniValue result(UniValue::VARR);
695  result.push_back(txid);
696  return result;
697 }
698 
700 {
701  if (!fAssetIndex) {
702  return "_This rpc call is not functional unless -assetindex is enabled. To enable, please run the wallet with -assetindex, this will require a reindex to occur";
703  }
704 
705  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 1)
706  throw std::runtime_error(
707  "listassetbalancesbyaddress \"address\" (onlytotal) (count) (start)\n"
709  "\nReturns a list of all asset balances for an address.\n"
710 
711  "\nArguments:\n"
712  "1. \"address\" (string, required) a raven address\n"
713  "2. \"onlytotal\" (boolean, optional, default=false) when false result is just a list of assets balances -- when true the result is just a single number representing the number of assets\n"
714  "3. \"count\" (integer, optional, default=50000, MAX=50000) truncates results to include only the first _count_ assets found\n"
715  "4. \"start\" (integer, optional, default=0) results skip over the first _start_ assets found (if negative it skips back from the end)\n"
716 
717  "\nResult:\n"
718  "{\n"
719  " (asset_name) : (quantity),\n"
720  " ...\n"
721  "}\n"
722 
723 
724  "\nExamples:\n"
725  + HelpExampleCli("listassetbalancesbyaddress", "\"myaddress\" false 2 0")
726  + HelpExampleCli("listassetbalancesbyaddress", "\"myaddress\" true")
727  + HelpExampleCli("listassetbalancesbyaddress", "\"myaddress\"")
728  );
729 
730  ObserveSafeMode();
731 
732  std::string address = request.params[0].get_str();
733  CTxDestination destination = DecodeDestination(address);
734  if (!IsValidDestination(destination)) {
735  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + address);
736  }
737 
738  bool fOnlyTotal = false;
739  if (request.params.size() > 1)
740  fOnlyTotal = request.params[1].get_bool();
741 
742  size_t count = INT_MAX;
743  if (request.params.size() > 2) {
744  if (request.params[2].get_int() < 1)
745  throw JSONRPCError(RPC_INVALID_PARAMETER, "count must be greater than 1.");
746  count = request.params[2].get_int();
747  }
748 
749  long start = 0;
750  if (request.params.size() > 3) {
751  start = request.params[3].get_int();
752  }
753 
754  if (!passetsdb)
755  throw JSONRPCError(RPC_INTERNAL_ERROR, "asset db unavailable.");
756 
757  LOCK(cs_main);
758  std::vector<std::pair<std::string, CAmount> > vecAssetAmounts;
759  int nTotalEntries = 0;
760  if (!passetsdb->AddressDir(vecAssetAmounts, nTotalEntries, fOnlyTotal, address, count, start))
761  throw JSONRPCError(RPC_INTERNAL_ERROR, "couldn't retrieve address asset directory.");
762 
763  // If only the number of addresses is wanted return it
764  if (fOnlyTotal) {
765  return nTotalEntries;
766  }
767 
768  UniValue result(UniValue::VOBJ);
769  for (auto& pair : vecAssetAmounts) {
770  result.push_back(Pair(pair.first, UnitValueFromAmount(pair.second, pair.first)));
771  }
772 
773  return result;
774 }
775 
777 {
778  if (request.fHelp || !AreAssetsDeployed() || request.params.size() != 1)
779  throw std::runtime_error(
780  "getassetdata \"asset_name\"\n"
782  "\nReturns assets metadata if that asset exists\n"
783 
784  "\nArguments:\n"
785  "1. \"asset_name\" (string, required) the name of the asset\n"
786 
787  "\nResult:\n"
788  "{\n"
789  " name: (string),\n"
790  " amount: (number),\n"
791  " units: (number),\n"
792  " reissuable: (number),\n"
793  " has_ipfs: (number),\n"
794  " ipfs_hash: (hash), (only if has_ipfs = 1 and that data is a ipfs hash)\n"
795  " txid_hash: (hash), (only if has_ipfs = 1 and that data is a txid hash)\n"
796  " verifier_string: (string)\n"
797  "}\n"
798 
799  "\nExamples:\n"
800  + HelpExampleCli("getassetdata", "\"ASSET_NAME\"")
801  + HelpExampleRpc("getassetdata", "\"ASSET_NAME\"")
802  );
803 
804 
805  std::string asset_name = request.params[0].get_str();
806 
807  LOCK(cs_main);
808  UniValue result (UniValue::VOBJ);
809 
810  auto currentActiveAssetCache = GetCurrentAssetCache();
811  if (currentActiveAssetCache) {
812  CNewAsset asset;
813  if (!currentActiveAssetCache->GetAssetMetaDataIfExists(asset_name, asset))
814  return NullUniValue;
815 
816  result.push_back(Pair("name", asset.strName));
817  result.push_back(Pair("amount", UnitValueFromAmount(asset.nAmount, asset.strName)));
818  result.push_back(Pair("units", asset.units));
819  result.push_back(Pair("reissuable", asset.nReissuable));
820  result.push_back(Pair("has_ipfs", asset.nHasIPFS));
821 
822  if (asset.nHasIPFS) {
823  if (asset.strIPFSHash.size() == 32) {
824  result.push_back(Pair("txid", EncodeAssetData(asset.strIPFSHash)));
825  } else {
826  result.push_back(Pair("ipfs_hash", EncodeAssetData(asset.strIPFSHash)));
827  }
828  }
829 
831  if (currentActiveAssetCache->GetAssetVerifierStringIfExists(asset.strName, verifier)) {
832  result.push_back(Pair("verifier_string", verifier.verifier_string));
833  }
834 
835  return result;
836  }
837 
838  return NullUniValue;
839 }
840 
841 template <class Iter, class Incr>
842 void safe_advance(Iter& curr, const Iter& end, Incr n)
843 {
844  size_t remaining(std::distance(curr, end));
845  if (remaining < n)
846  {
847  n = remaining;
848  }
849  std::advance(curr, n);
850 };
851 
853 {
854  if (request.fHelp || !AreAssetsDeployed() || request.params.size() > 5)
855  throw std::runtime_error(
856  "listmyassets \"( asset )\" ( verbose ) ( count ) ( start ) (confs) \n"
858  "\nReturns a list of all asset that are owned by this wallet\n"
859 
860  "\nArguments:\n"
861  "1. \"asset\" (string, optional, default=\"*\") filters results -- must be an asset name or a partial asset name followed by '*' ('*' matches all trailing characters)\n"
862  "2. \"verbose\" (boolean, optional, default=false) when false results only contain balances -- when true results include outpoints\n"
863  "3. \"count\" (integer, optional, default=ALL) truncates results to include only the first _count_ assets found\n"
864  "4. \"start\" (integer, optional, default=0) results skip over the first _start_ assets found (if negative it skips back from the end)\n"
865  "5. \"confs\" (integet, optional, default=0) results are skipped if they don't have this number of confirmations\n"
866 
867  "\nResult (verbose=false):\n"
868  "{\n"
869  " (asset_name): balance,\n"
870  " ...\n"
871  "}\n"
872 
873  "\nResult (verbose=true):\n"
874  "{\n"
875  " (asset_name):\n"
876  " {\n"
877  " \"balance\": balance,\n"
878  " \"outpoints\":\n"
879  " [\n"
880  " {\n"
881  " \"txid\": txid,\n"
882  " \"vout\": vout,\n"
883  " \"amount\": amount\n"
884  " }\n"
885  " {...}, {...}\n"
886  " ]\n"
887  " }\n"
888  "}\n"
889  "{...}, {...}\n"
890 
891  "\nExamples:\n"
892  + HelpExampleRpc("listmyassets", "")
893  + HelpExampleCli("listmyassets", "ASSET")
894  + HelpExampleCli("listmyassets", "\"ASSET*\" true 10 20")
895  + HelpExampleCli("listmyassets", "\"ASSET*\" true 10 20 1")
896  );
897 
898  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
899  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
900  return NullUniValue;
901  }
902 
903  ObserveSafeMode();
904  LOCK2(cs_main, pwallet->cs_wallet);
905 
906  std::string filter = "*";
907  if (request.params.size() > 0)
908  filter = request.params[0].get_str();
909 
910  if (filter == "")
911  filter = "*";
912 
913  bool verbose = false;
914  if (request.params.size() > 1)
915  verbose = request.params[1].get_bool();
916 
917  size_t count = INT_MAX;
918  if (request.params.size() > 2) {
919  if (request.params[2].get_int() < 1)
920  throw JSONRPCError(RPC_INVALID_PARAMETER, "count must be greater than 1.");
921  count = request.params[2].get_int();
922  }
923 
924  long start = 0;
925  if (request.params.size() > 3) {
926  start = request.params[3].get_int();
927  }
928 
929  int confs = 0;
930  if (request.params.size() > 4) {
931  confs = request.params[4].get_int();
932  }
933 
934  // retrieve balances
935  std::map<std::string, CAmount> balances;
936  std::map<std::string, std::vector<COutput> > outputs;
937  if (filter == "*") {
938  if (!GetAllMyAssetBalances(outputs, balances, confs))
939  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset balances. For all assets");
940  }
941  else if (filter.back() == '*') {
942  std::vector<std::string> assetNames;
943  filter.pop_back();
944  if (!GetAllMyAssetBalances(outputs, balances, confs, filter))
945  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset balances. For all assets");
946  }
947  else {
948  if (!IsAssetNameValid(filter))
949  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid asset name.");
950  if (!GetAllMyAssetBalances(outputs, balances, confs, filter))
951  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset balances. For all assets");
952  }
953 
954  // pagination setup
955  auto bal = balances.begin();
956  if (start >= 0)
957  safe_advance(bal, balances.end(), (size_t)start);
958  else
959  safe_advance(bal, balances.end(), balances.size() + start);
960  auto end = bal;
961  safe_advance(end, balances.end(), count);
962 
963  // generate output
964  UniValue result(UniValue::VOBJ);
965  if (verbose) {
966  for (; bal != end && bal != balances.end(); bal++) {
967  UniValue asset(UniValue::VOBJ);
968  asset.push_back(Pair("balance", UnitValueFromAmount(bal->second, bal->first)));
969 
970  UniValue outpoints(UniValue::VARR);
971  for (auto const& out : outputs.at(bal->first)) {
972  UniValue tempOut(UniValue::VOBJ);
973  tempOut.push_back(Pair("txid", out.tx->GetHash().GetHex()));
974  tempOut.push_back(Pair("vout", (int)out.i));
975 
976  //
977  // get amount for this outpoint
978  CAmount txAmount = 0;
979  auto it = pwallet->mapWallet.find(out.tx->GetHash());
980  if (it == pwallet->mapWallet.end()) {
981  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
982  }
983  const CWalletTx* wtx = out.tx;
984  CTxOut txOut = wtx->tx->vout[out.i];
985  std::string strAddress;
986  if (CheckIssueDataTx(txOut)) {
987  CNewAsset asset;
988  if (!AssetFromScript(txOut.scriptPubKey, asset, strAddress))
989  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset from script.");
990  txAmount = asset.nAmount;
991  }
992  else if (CheckReissueDataTx(txOut)) {
993  CReissueAsset asset;
994  if (!ReissueAssetFromScript(txOut.scriptPubKey, asset, strAddress))
995  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset from script.");
996  txAmount = asset.nAmount;
997  }
998  else if (CheckTransferOwnerTx(txOut)) {
999  CAssetTransfer asset;
1000  if (!TransferAssetFromScript(txOut.scriptPubKey, asset, strAddress))
1001  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset from script.");
1002  txAmount = asset.nAmount;
1003  }
1004  else if (CheckOwnerDataTx(txOut)) {
1005  std::string assetName;
1006  if (!OwnerAssetFromScript(txOut.scriptPubKey, assetName, strAddress))
1007  throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't get asset from script.");
1008  txAmount = OWNER_ASSET_AMOUNT;
1009  }
1010  tempOut.push_back(Pair("amount", UnitValueFromAmount(txAmount, bal->first)));
1011  //
1012  //
1013 
1014  outpoints.push_back(tempOut);
1015  }
1016  asset.push_back(Pair("outpoints", outpoints));
1017  result.push_back(Pair(bal->first, asset));
1018  }
1019  }
1020  else {
1021  for (; bal != end && bal != balances.end(); bal++) {
1022  result.push_back(Pair(bal->first, UnitValueFromAmount(bal->second, bal->first)));
1023  }
1024  }
1025  return result;
1026 }
1027 
1029 {
1030  if (!fAssetIndex) {
1031  return "_This rpc call is not functional unless -assetindex is enabled. To enable, please run the wallet with -assetindex, this will require a reindex to occur";
1032  }
1033 
1034  if (request.fHelp || !AreAssetsDeployed() || request.params.size() > 4 || request.params.size() < 1)
1035  throw std::runtime_error(
1036  "listaddressesbyasset \"asset_name\" (onlytotal) (count) (start)\n"
1038  "\nReturns a list of all address that own the given asset (with balances)"
1039  "\nOr returns the total size of how many address own the given asset"
1040 
1041  "\nArguments:\n"
1042  "1. \"asset_name\" (string, required) name of asset\n"
1043  "2. \"onlytotal\" (boolean, optional, default=false) when false result is just a list of addresses with balances -- when true the result is just a single number representing the number of addresses\n"
1044  "3. \"count\" (integer, optional, default=50000, MAX=50000) truncates results to include only the first _count_ assets found\n"
1045  "4. \"start\" (integer, optional, default=0) results skip over the first _start_ assets found (if negative it skips back from the end)\n"
1046 
1047  "\nResult:\n"
1048  "[ "
1049  " (address): balance,\n"
1050  " ...\n"
1051  "]\n"
1052 
1053  "\nExamples:\n"
1054  + HelpExampleCli("listaddressesbyasset", "\"ASSET_NAME\" false 2 0")
1055  + HelpExampleCli("listaddressesbyasset", "\"ASSET_NAME\" true")
1056  + HelpExampleCli("listaddressesbyasset", "\"ASSET_NAME\"")
1057  );
1058 
1059  LOCK(cs_main);
1060 
1061  std::string asset_name = request.params[0].get_str();
1062  bool fOnlyTotal = false;
1063  if (request.params.size() > 1)
1064  fOnlyTotal = request.params[1].get_bool();
1065 
1066  size_t count = INT_MAX;
1067  if (request.params.size() > 2) {
1068  if (request.params[2].get_int() < 1)
1069  throw JSONRPCError(RPC_INVALID_PARAMETER, "count must be greater than 1.");
1070  count = request.params[2].get_int();
1071  }
1072 
1073  long start = 0;
1074  if (request.params.size() > 3) {
1075  start = request.params[3].get_int();
1076  }
1077 
1078  if (!IsAssetNameValid(asset_name))
1079  return "_Not a valid asset name";
1080 
1081  LOCK(cs_main);
1082  std::vector<std::pair<std::string, CAmount> > vecAddressAmounts;
1083  int nTotalEntries = 0;
1084  if (!passetsdb->AssetAddressDir(vecAddressAmounts, nTotalEntries, fOnlyTotal, asset_name, count, start))
1085  throw JSONRPCError(RPC_INTERNAL_ERROR, "couldn't retrieve address asset directory.");
1086 
1087  // If only the number of addresses is wanted return it
1088  if (fOnlyTotal) {
1089  return nTotalEntries;
1090  }
1091 
1092  UniValue result(UniValue::VOBJ);
1093  for (auto& pair : vecAddressAmounts) {
1094  result.push_back(Pair(pair.first, UnitValueFromAmount(pair.second, asset_name)));
1095  }
1096 
1097 
1098  return result;
1099 }
1100 
1102 {
1103  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 3 || request.params.size() > 6)
1104  throw std::runtime_error(
1105  "transfer \"asset_name\" qty \"to_address\" \"message\" expire_time \"change_address\"\n"
1107  "\nTransfers a quantity of an owned asset to a given address"
1108 
1109  "\nArguments:\n"
1110  "1. \"asset_name\" (string, required) name of asset\n"
1111  "2. \"qty\" (numeric, required) number of assets you want to send to the address\n"
1112  "3. \"to_address\" (string, required) address to send the asset to\n"
1113  "4. \"message\" (string, optional) Once RIP5 is voted in ipfs hash or txid hash to send along with the transfer\n"
1114  "5. \"expire_time\" (numeric, optional) UTC timestamp of when the message expires\n"
1115  "6. \"change_address\" (string, optional, default = \"\") the transaction change will be sent to this address\n"
1116 
1117  "\nResult:\n"
1118  "txid"
1119  "[ \n"
1120  "txid\n"
1121  "]\n"
1122 
1123  "\nExamples:\n"
1124  + HelpExampleCli("transfer", "\"ASSET_NAME\" 20 \"address\" \"\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\" 15863654")
1125  + HelpExampleCli("transfer", "\"ASSET_NAME\" 20 \"address\" \"\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\" 15863654")
1126  );
1127 
1128  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1129  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1130  return NullUniValue;
1131  }
1132 
1133  ObserveSafeMode();
1134  LOCK2(cs_main, pwallet->cs_wallet);
1135 
1136  EnsureWalletIsUnlocked(pwallet);
1137 
1138  std::string asset_name = request.params[0].get_str();
1139 
1140  if (IsAssetNameAQualifier(asset_name))
1141  throw JSONRPCError(RPC_INVALID_PARAMETER, "Please use the rpc call transferqualifierasset to send qualifier assets from this wallet.");
1142 
1143  CAmount nAmount = AmountFromValue(request.params[1]);
1144 
1145  std::string to_address = request.params[2].get_str();
1146  CTxDestination to_dest = DecodeDestination(to_address);
1147  if (!IsValidDestination(to_dest)) {
1148  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + to_address);
1149  }
1150 
1151  bool fMessageCheck = false;
1152  std::string message = "";
1153  if (request.params.size() > 3) {
1154  message = request.params[3].get_str();
1155  if (!message.empty())
1156  fMessageCheck = true;
1157  }
1158 
1159  int64_t expireTime = 0;
1160  if (!message.empty()) {
1161  if (request.params.size() > 4) {
1162  expireTime = request.params[4].get_int64();
1163  }
1164  }
1165 
1166  if (!message.empty() || expireTime > 0) {
1167  if (!AreMessagingDeployed()) {
1168  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Unable to send messages until Messaging RIP5 is enabled"));
1169  }
1170  }
1171 
1172  if (fMessageCheck)
1173  CheckIPFSTxidMessage(message, expireTime);
1174 
1175  std::string change_address = "";
1176  if(request.params.size() > 5) {
1177  change_address = request.params[5].get_str();
1178 
1179  if (!change_address.empty()) {
1180  CTxDestination change_dest = DecodeDestination(change_address);
1181  if (!IsValidDestination(change_dest)) {
1182  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + change_address);
1183  }
1184  }
1185  }
1186 
1187  std::pair<int, std::string> error;
1188  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
1189 
1190  CAssetTransfer transfer(asset_name, nAmount, DecodeAssetData(message), expireTime);
1191 
1192  vTransfers.emplace_back(std::make_pair(transfer, to_address));
1193  CReserveKey reservekey(pwallet);
1194  CWalletTx transaction;
1195  CAmount nRequiredFee;
1196 
1197  CCoinControl ctrl;
1198  ctrl.destChange = DecodeDestination(change_address);
1199 
1200  // Create the Transaction
1201  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee))
1202  throw JSONRPCError(error.first, error.second);
1203 
1204  // Do a validity check before commiting the transaction
1205  CheckRestrictedAssetTransferInputs(transaction, asset_name);
1206 
1207  // Send the Transaction to the network
1208  std::string txid;
1209  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
1210  throw JSONRPCError(error.first, error.second);
1211 
1212  // Display the transaction id
1213  UniValue result(UniValue::VARR);
1214  result.push_back(txid);
1215  return result;
1216 }
1217 
1219 {
1220  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 4 || request.params.size() > 6)
1221  throw std::runtime_error(
1222  "transferfromaddresses \"asset_name\" [\"from_addresses\"] qty \"to_address\" \"message\" expire_time\n"
1224  "\nTransfer a quantity of an owned asset in specific address(es) to a given address"
1225 
1226  "\nArguments:\n"
1227  "1. \"asset_name\" (string, required) name of asset\n"
1228  "2. \"from_addresses\" (array, required) list of from addresses to send from\n"
1229  "3. \"qty\" (numeric, required) number of assets you want to send to the address\n"
1230  "4. \"to_address\" (string, required) address to send the asset to\n"
1231  "5. \"message\" (string, optional) Once RIP5 is voted in ipfs hash or txid hash to send along with the transfer\n"
1232  "6. \"expire_time\" (numeric, optional) UTC timestamp of when the message expires\n"
1233 
1234  "\nResult:\n"
1235  "txid"
1236  "[ \n"
1237  "txid\n"
1238  "]\n"
1239 
1240  "\nExamples:\n"
1241  + HelpExampleCli("transferfromaddresses", "\"ASSET_NAME\" \'[\"fromaddress1\", \"fromaddress2\"]\' 20 \"to_address\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\" 154652365")
1242  + HelpExampleRpc("transferfromaddresses", "\"ASSET_NAME\" \'[\"fromaddress1\", \"fromaddress2\"]\' 20 \"to_address\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\" 154652365")
1243  );
1244 
1245  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1246  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1247  return NullUniValue;
1248  }
1249 
1250  ObserveSafeMode();
1251  LOCK2(cs_main, pwallet->cs_wallet);
1252 
1253  EnsureWalletIsUnlocked(pwallet);
1254 
1255  std::string asset_name = request.params[0].get_str();
1256 
1257  const UniValue& from_addresses = request.params[1];
1258 
1259  if (!from_addresses.isArray() || from_addresses.size() < 1) {
1260  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("From addresses must be a non-empty array."));
1261  }
1262 
1263  std::set<std::string> setFromDestinations;
1264 
1265  // Add the given array of addresses into the set of destinations
1266  for (int i = 0; i < (int) from_addresses.size(); i++) {
1267  std::string address = from_addresses[i].get_str();
1268  CTxDestination dest = DecodeDestination(address);
1269  if (!IsValidDestination(dest))
1270  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("From addresses must be valid addresses. Invalid address: ") + address);
1271 
1272  setFromDestinations.insert(address);
1273  }
1274 
1275  CAmount nAmount = AmountFromValue(request.params[2]);
1276 
1277  std::string address = request.params[3].get_str();
1278 
1279  bool fMessageCheck = false;
1280  std::string message = "";
1281  if (request.params.size() > 4) {
1282  fMessageCheck = true;
1283  message = request.params[4].get_str();
1284  }
1285 
1286  int64_t expireTime = 0;
1287  if (!message.empty()) {
1288  if (request.params.size() > 5) {
1289  expireTime = request.params[5].get_int64();
1290  }
1291  }
1292 
1293  if (fMessageCheck)
1294  CheckIPFSTxidMessage(message, expireTime);
1295 
1296  std::pair<int, std::string> error;
1297  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
1298 
1299  vTransfers.emplace_back(std::make_pair(CAssetTransfer(asset_name, nAmount, DecodeAssetData(message), expireTime), address));
1300  CReserveKey reservekey(pwallet);
1301  CWalletTx transaction;
1302  CAmount nRequiredFee;
1303 
1304  CCoinControl ctrl;
1305  std::map<std::string, std::vector<COutput> > mapAssetCoins;
1306  pwallet->AvailableAssets(mapAssetCoins);
1307 
1308  if (!mapAssetCoins.count(asset_name)) {
1309  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Wallet doesn't own the asset_name: " + asset_name));
1310  }
1311 
1312  // Add all the asset outpoints that match the set of given from addresses
1313  for (const auto& out : mapAssetCoins.at(asset_name)) {
1314  // Get the address that the coin resides in, because to send a valid message. You need to send it to the same address that it currently resides in.
1315  CTxDestination dest;
1316  ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, dest);
1317 
1318  if (setFromDestinations.count(EncodeDestination(dest)))
1319  ctrl.SelectAsset(COutPoint(out.tx->GetHash(), out.i));
1320  }
1321 
1322  std::vector<COutPoint> outs;
1323  ctrl.ListSelectedAssets(outs);
1324  if (!outs.size()) {
1325  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("No asset outpoints are selected from the given addresses, failed to create the transaction"));
1326  }
1327 
1328  // Create the Transaction
1329  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee))
1330  throw JSONRPCError(error.first, error.second);
1331 
1332  // Do a validity check before commiting the transaction
1333  CheckRestrictedAssetTransferInputs(transaction, asset_name);
1334 
1335  // Send the Transaction to the network
1336  std::string txid;
1337  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
1338  throw JSONRPCError(error.first, error.second);
1339 
1340  // Display the transaction id
1341  UniValue result(UniValue::VARR);
1342  result.push_back(txid);
1343  return result;
1344 }
1345 
1347 {
1348  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 4 || request.params.size() > 6)
1349  throw std::runtime_error(
1350  "transferfromaddress \"asset_name\" \"from_address\" qty \"to_address\" \"message\" expire_time\n"
1352  "\nTransfer a quantity of an owned asset in a specific address to a given address"
1353 
1354  "\nArguments:\n"
1355  "1. \"asset_name\" (string, required) name of asset\n"
1356  "2. \"from_address\" (string, required) address that the asset will be transferred from\n"
1357  "3. \"qty\" (numeric, required) number of assets you want to send to the address\n"
1358  "4. \"to_address\" (string, required) address to send the asset to\n"
1359  "5. \"message\" (string, optional) Once RIP5 is voted in ipfs hash or txid hash to send along with the transfer\n"
1360  "6. \"expire_time\" (numeric, optional) UTC timestamp of when the message expires\n"
1361 
1362  "\nResult:\n"
1363  "txid"
1364  "[ \n"
1365  "txid\n"
1366  "]\n"
1367 
1368  "\nExamples:\n"
1369  + HelpExampleCli("transferfromaddress", "\"ASSET_NAME\" \"fromaddress\" 20 \"address\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\", 156545652")
1370  + HelpExampleRpc("transferfromaddress", "\"ASSET_NAME\" \"fromaddress\" 20 \"address\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\", 156545652")
1371  );
1372 
1373  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1374  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1375  return NullUniValue;
1376  }
1377 
1378  ObserveSafeMode();
1379  LOCK2(cs_main, pwallet->cs_wallet);
1380 
1381  EnsureWalletIsUnlocked(pwallet);
1382 
1383  std::string asset_name = request.params[0].get_str();
1384 
1385  std::string from_address = request.params[1].get_str();
1386 
1387  // Check to make sure the given from address is valid
1388  CTxDestination dest = DecodeDestination(from_address);
1389  if (!IsValidDestination(dest))
1390  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("From address must be valid addresses. Invalid address: ") + from_address);
1391 
1392  CAmount nAmount = AmountFromValue(request.params[2]);
1393 
1394  std::string address = request.params[3].get_str();
1395 
1396 
1397  bool fMessageCheck = false;
1398  std::string message = "";
1399  if (request.params.size() > 4) {
1400  fMessageCheck = true;
1401  message = request.params[4].get_str();
1402  }
1403 
1404  int64_t expireTime = 0;
1405  if (!message.empty()) {
1406  if (request.params.size() > 5) {
1407  expireTime = request.params[5].get_int64();
1408  }
1409  }
1410 
1411  if (fMessageCheck)
1412  CheckIPFSTxidMessage(message, expireTime);
1413 
1414  std::pair<int, std::string> error;
1415  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
1416 
1417  vTransfers.emplace_back(std::make_pair(CAssetTransfer(asset_name, nAmount, DecodeAssetData(message), expireTime), address));
1418  CReserveKey reservekey(pwallet);
1419  CWalletTx transaction;
1420  CAmount nRequiredFee;
1421 
1422  CCoinControl ctrl;
1423  std::map<std::string, std::vector<COutput> > mapAssetCoins;
1424  pwallet->AvailableAssets(mapAssetCoins);
1425 
1426  if (!mapAssetCoins.count(asset_name)) {
1427  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Wallet doesn't own the asset_name: " + asset_name));
1428  }
1429 
1430  // Add all the asset outpoints that match the given from addresses
1431  for (const auto& out : mapAssetCoins.at(asset_name)) {
1432  // Get the address that the coin resides in, because to send a valid message. You need to send it to the same address that it currently resides in.
1433  CTxDestination dest;
1434  ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, dest);
1435 
1436  if (from_address == EncodeDestination(dest))
1437  ctrl.SelectAsset(COutPoint(out.tx->GetHash(), out.i));
1438  }
1439 
1440  std::vector<COutPoint> outs;
1441  ctrl.ListSelectedAssets(outs);
1442  if (!outs.size()) {
1443  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("No asset outpoints are selected from the given address, failed to create the transaction"));
1444  }
1445 
1446  // Create the Transaction
1447  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee))
1448  throw JSONRPCError(error.first, error.second);
1449 
1450  // Do a validity check before commiting the transaction
1451  CheckRestrictedAssetTransferInputs(transaction, asset_name);
1452 
1453  // Send the Transaction to the network
1454  std::string txid;
1455  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
1456  throw JSONRPCError(error.first, error.second);
1457 
1458  // Display the transaction id
1459  UniValue result(UniValue::VARR);
1460  result.push_back(txid);
1461  return result;
1462 }
1463 
1464 
1466 {
1467  if (request.fHelp || !AreAssetsDeployed() || request.params.size() > 7 || request.params.size() < 3)
1468  throw std::runtime_error(
1469  "reissue \"asset_name\" qty \"to_address\" \"change_address\" ( reissuable ) ( new_unit) \"( new_ipfs )\" \n"
1471  "\nReissues a quantity of an asset to an owned address if you own the Owner Token"
1472  "\nCan change the reissuable flag during reissuance"
1473  "\nCan change the ipfs hash during reissuance"
1474 
1475  "\nArguments:\n"
1476  "1. \"asset_name\" (string, required) name of asset that is being reissued\n"
1477  "2. \"qty\" (numeric, required) number of assets to reissue\n"
1478  "3. \"to_address\" (string, required) address to send the asset to\n"
1479  "4. \"change_address\" (string, optional) address that the change of the transaction will be sent to\n"
1480  "5. \"reissuable\" (boolean, optional, default=true), whether future reissuance is allowed\n"
1481  "6. \"new_unit\" (numeric, optional, default=-1), the new units that will be associated with the asset\n"
1482  "6. \"new_ifps\" (string, optional, default=\"\"), whether to update the current ipfshash or txid once RIP5 is active\n"
1483 
1484  "\nResult:\n"
1485  "\"txid\" (string) The transaction id\n"
1486 
1487  "\nExamples:\n"
1488  + HelpExampleCli("reissue", "\"ASSET_NAME\" 20 \"address\"")
1489  + HelpExampleRpc("reissue", "\"ASSET_NAME\" 20 \"address\" \"change_address\" \"true\" 8 \"Qmd286K6pohQcTKYqnS1YhWrCiS4gz7Xi34sdwMe9USZ7u\"")
1490  );
1491 
1492  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1493  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1494  return NullUniValue;
1495  }
1496 
1497  ObserveSafeMode();
1498  LOCK2(cs_main, pwallet->cs_wallet);
1499 
1500  // To send a transaction the wallet must be unlocked
1501  EnsureWalletIsUnlocked(pwallet);
1502 
1503  // Get that paramaters
1504  std::string asset_name = request.params[0].get_str();
1505  CAmount nAmount = AmountFromValue(request.params[1]);
1506  std::string address = request.params[2].get_str();
1507 
1508  std::string changeAddress = "";
1509  if (request.params.size() > 3)
1510  changeAddress = request.params[3].get_str();
1511 
1512  bool reissuable = true;
1513  if (request.params.size() > 4) {
1514  reissuable = request.params[4].get_bool();
1515  }
1516 
1517  int newUnits = -1;
1518  if (request.params.size() > 5) {
1519  newUnits = request.params[5].get_int();
1520  }
1521 
1522  std::string newipfs = "";
1523  bool fMessageCheck = false;
1524 
1525  if (request.params.size() > 6) {
1526  fMessageCheck = true;
1527  newipfs = request.params[6].get_str();
1528  }
1529 
1530  // Reissues don't have an expire time
1531  int64_t expireTime = 0;
1532 
1533  // Check the message data
1534  if (fMessageCheck)
1535  CheckIPFSTxidMessage(newipfs, expireTime);
1536 
1537  CReissueAsset reissueAsset(asset_name, nAmount, newUnits, reissuable, DecodeAssetData(newipfs));
1538 
1539  std::pair<int, std::string> error;
1540  CReserveKey reservekey(pwallet);
1541  CWalletTx transaction;
1542  CAmount nRequiredFee;
1543 
1544  CCoinControl crtl;
1545  crtl.destChange = DecodeDestination(changeAddress);
1546 
1547  // Create the Transaction
1548  if (!CreateReissueAssetTransaction(pwallet, crtl, reissueAsset, address, error, transaction, reservekey, nRequiredFee))
1549  throw JSONRPCError(error.first, error.second);
1550 
1551  std::string strError = "";
1552  if (!ContextualCheckReissueAsset(passets, reissueAsset, strError, *transaction.tx.get()))
1553  throw JSONRPCError(RPC_INVALID_REQUEST, strError);
1554 
1555  // Send the Transaction to the network
1556  std::string txid;
1557  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
1558  throw JSONRPCError(error.first, error.second);
1559 
1560  UniValue result(UniValue::VARR);
1561  result.push_back(txid);
1562  return result;
1563 }
1564 
1566 {
1567  if (request.fHelp || !AreAssetsDeployed() || request.params.size() > 4)
1568  throw std::runtime_error(
1569  "listassets \"( asset )\" ( verbose ) ( count ) ( start )\n"
1571  "\nReturns a list of all assets\n"
1572  "\nThis could be a slow/expensive operation as it reads from the database\n"
1573 
1574  "\nArguments:\n"
1575  "1. \"asset\" (string, optional, default=\"*\") filters results -- must be an asset name or a partial asset name followed by '*' ('*' matches all trailing characters)\n"
1576  "2. \"verbose\" (boolean, optional, default=false) when false result is just a list of asset names -- when true results are asset name mapped to metadata\n"
1577  "3. \"count\" (integer, optional, default=ALL) truncates results to include only the first _count_ assets found\n"
1578  "4. \"start\" (integer, optional, default=0) results skip over the first _start_ assets found (if negative it skips back from the end)\n"
1579 
1580  "\nResult (verbose=false):\n"
1581  "[\n"
1582  " asset_name,\n"
1583  " ...\n"
1584  "]\n"
1585 
1586  "\nResult (verbose=true):\n"
1587  "{\n"
1588  " (asset_name):\n"
1589  " {\n"
1590  " amount: (number),\n"
1591  " units: (number),\n"
1592  " reissuable: (number),\n"
1593  " has_ipfs: (number),\n"
1594  " ipfs_hash: (hash) (only if has_ipfs = 1 and data is a ipfs hash)\n"
1595  " ipfs_hash: (hash) (only if has_ipfs = 1 and data is a txid hash)\n"
1596  " },\n"
1597  " {...}, {...}\n"
1598  "}\n"
1599 
1600  "\nExamples:\n"
1601  + HelpExampleRpc("listassets", "")
1602  + HelpExampleCli("listassets", "ASSET")
1603  + HelpExampleCli("listassets", "\"ASSET*\" true 10 20")
1604  );
1605 
1606  ObserveSafeMode();
1607 
1608  if (!passetsdb)
1609  throw JSONRPCError(RPC_INTERNAL_ERROR, "asset db unavailable.");
1610 
1611  std::string filter = "*";
1612  if (request.params.size() > 0)
1613  filter = request.params[0].get_str();
1614 
1615  if (filter == "")
1616  filter = "*";
1617 
1618  bool verbose = false;
1619  if (request.params.size() > 1)
1620  verbose = request.params[1].get_bool();
1621 
1622  size_t count = INT_MAX;
1623  if (request.params.size() > 2) {
1624  if (request.params[2].get_int() < 1)
1625  throw JSONRPCError(RPC_INVALID_PARAMETER, "count must be greater than 1.");
1626  count = request.params[2].get_int();
1627  }
1628 
1629  long start = 0;
1630  if (request.params.size() > 3) {
1631  start = request.params[3].get_int();
1632  }
1633 
1634  std::vector<CDatabasedAssetData> assets;
1635  if (!passetsdb->AssetDir(assets, filter, count, start))
1636  throw JSONRPCError(RPC_INTERNAL_ERROR, "couldn't retrieve asset directory.");
1637 
1638  UniValue result;
1639  result = verbose ? UniValue(UniValue::VOBJ) : UniValue(UniValue::VARR);
1640 
1641  for (auto data : assets) {
1642  CNewAsset asset = data.asset;
1643  if (verbose) {
1644  UniValue detail(UniValue::VOBJ);
1645  detail.push_back(Pair("name", asset.strName));
1646  detail.push_back(Pair("amount", UnitValueFromAmount(asset.nAmount, asset.strName)));
1647  detail.push_back(Pair("units", asset.units));
1648  detail.push_back(Pair("reissuable", asset.nReissuable));
1649  detail.push_back(Pair("has_ipfs", asset.nHasIPFS));
1650  detail.push_back(Pair("block_height", data.nHeight));
1651  detail.push_back(Pair("blockhash", data.blockHash.GetHex()));
1652  if (asset.nHasIPFS) {
1653  if (asset.strIPFSHash.size() == 32) {
1654  detail.push_back(Pair("txid_hash", EncodeAssetData(asset.strIPFSHash)));
1655  } else {
1656  detail.push_back(Pair("ipfs_hash", EncodeAssetData(asset.strIPFSHash)));
1657  }
1658  }
1659  result.push_back(Pair(asset.strName, detail));
1660  } else {
1661  result.push_back(asset.strName);
1662  }
1663  }
1664 
1665  return result;
1666 }
1667 
1669 {
1670  if (request.fHelp || !AreAssetsDeployed() || request.params.size())
1671  throw std::runtime_error(
1672  "getcacheinfo \n"
1674 
1675  "\nResult:\n"
1676  "[\n"
1677  " uxto cache size:\n"
1678  " asset total (exclude dirty):\n"
1679  " asset address map:\n"
1680  " asset address balance:\n"
1681  " my unspent asset:\n"
1682  " reissue data:\n"
1683  " asset metadata map:\n"
1684  " asset metadata list (est):\n"
1685  " dirty cache (est):\n"
1686 
1687 
1688  "]\n"
1689 
1690  "\nExamples:\n"
1691  + HelpExampleRpc("getcacheinfo", "")
1692  + HelpExampleCli("getcacheinfo", "")
1693  );
1694 
1695  auto currentActiveAssetCache = GetCurrentAssetCache();
1696  if (!currentActiveAssetCache)
1697  throw JSONRPCError(RPC_VERIFY_ERROR, "asset cache is null");
1698 
1699  if (!pcoinsTip)
1700  throw JSONRPCError(RPC_VERIFY_ERROR, "coins tip cache is null");
1701 
1702  if (!passetsCache)
1703  throw JSONRPCError(RPC_VERIFY_ERROR, "asset metadata cache is nul");
1704 
1705  UniValue result(UniValue::VARR);
1706 
1707  UniValue info(UniValue::VOBJ);
1708  info.push_back(Pair("uxto cache size", (int)pcoinsTip->DynamicMemoryUsage()));
1709  info.push_back(Pair("asset total (exclude dirty)", (int)currentActiveAssetCache->DynamicMemoryUsage()));
1710 
1711  UniValue descendants(UniValue::VOBJ);
1712 
1713  descendants.push_back(Pair("asset address balance", (int)memusage::DynamicUsage(currentActiveAssetCache->mapAssetsAddressAmount)));
1714  descendants.push_back(Pair("reissue data", (int)memusage::DynamicUsage(currentActiveAssetCache->mapReissuedAssetData)));
1715 
1716  info.push_back(Pair("reissue tracking (memory only)", (int)memusage::DynamicUsage(mapReissuedAssets) + (int)memusage::DynamicUsage(mapReissuedTx)));
1717  info.push_back(Pair("asset data", descendants));
1718  info.push_back(Pair("asset metadata map", (int)memusage::DynamicUsage(passetsCache->GetItemsMap())));
1719  info.push_back(Pair("asset metadata list (est)", (int)passetsCache->GetItemsList().size() * (32 + 80))); // Max 32 bytes for asset name, 80 bytes max for asset data
1720  info.push_back(Pair("dirty cache (est)", (int)currentActiveAssetCache->GetCacheSize()));
1721  info.push_back(Pair("dirty cache V2 (est)", (int)currentActiveAssetCache->GetCacheSizeV2()));
1722 
1723  result.push_back(info);
1724  return result;
1725 }
1726 
1728 {
1729  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 2 || request.params.size() > 3)
1730  throw std::runtime_error(
1731  "addtagtoaddress tag_name to_address (change_address)\n"
1733  "\nAssign a tag to a address\n"
1734 
1735  "\nArguments:\n"
1736  "1. \"tag_name\" (string, required) the name of the tag you are assigning to the address\n"
1737  "2. \"to_address\" (string, required) the address that will be assigned the tag\n"
1738  "3. \"change_address\" (string, optional) The change address for the qualifier token to be sent to\n"
1739 
1740  "\nResult:\n"
1741  "\"txid\" (string) The transaction id\n"
1742 
1743  "\nExamples:\n"
1744  + HelpExampleCli("addtagtoaddress", "\"#TAG\" \"to_address\"")
1745  + HelpExampleRpc("addtagtoaddress", "\"#TAG\" \"to_address\"")
1746  + HelpExampleCli("addtagtoaddress", "\"#TAG\" \"to_address\" \"change_address\"")
1747  + HelpExampleRpc("addtagtoaddress", "\"#TAG\" \"to_address\" \"change_address\"")
1748  );
1749 
1750  // 1 - on
1751  return UpdateAddressTag(request, 1);
1752 }
1753 
1755 {
1756  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 2 || request.params.size() > 3)
1757  throw std::runtime_error(
1758  "removetagfromaddress tag_name to_address (change_address)\n"
1760  "\nRemove a tag from a address\n"
1761 
1762  "\nArguments:\n"
1763  "1. \"tag_name\" (string, required) the name of the tag you are removing from the address\n"
1764  "2. \"to_address\" (string, required) the address that the tag will be removed from\n"
1765  "3. \"change_address\" (string, optional) The change address for the qualifier token to be sent to\n"
1766 
1767  "\nResult:\n"
1768  "\"txid\" (string) The transaction id\n"
1769 
1770  "\nExamples:\n"
1771  + HelpExampleCli("removetagfromaddress", "\"#TAG\" \"to_address\"")
1772  + HelpExampleRpc("removetagfromaddress", "\"#TAG\" \"to_address\"")
1773  + HelpExampleCli("removetagfromaddress", "\"#TAG\" \"to_address\" \"change_address\"")
1774  + HelpExampleRpc("removetagfromaddress", "\"#TAG\" \"to_address\" \"change_address\"")
1775  );
1776 
1777  // 0 = off
1778  return UpdateAddressTag(request, 0);
1779 }
1780 
1782 {
1783  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 2 || request.params.size() > 3)
1784  throw std::runtime_error(
1785  "freezeaddress asset_name address (change_address)\n"
1787  "\nFreeze an address from transferring a restricted asset\n"
1788 
1789  "\nArguments:\n"
1790  "1. \"asset_name\" (string, required) the name of the restricted asset you want to freeze\n"
1791  "2. \"address\" (string, required) the address that will be frozen\n"
1792  "3. \"change_address\" (string, optional) The change address for the owner token of the restricted asset\n"
1793 
1794  "\nResult:\n"
1795  "\"txid\" (string) The transaction id\n"
1796 
1797  "\nExamples:\n"
1798  + HelpExampleCli("freezeaddress", "\"$RESTRICTED_ASSET\" \"address\"")
1799  + HelpExampleRpc("freezeaddress", "\"$RESTRICTED_ASSET\" \"address\"")
1800  + HelpExampleCli("freezeaddress", "\"$RESTRICTED_ASSET\" \"address\" \"change_address\"")
1801  + HelpExampleRpc("freezeaddress", "\"$RESTRICTED_ASSET\" \"address\" \"change_address\"")
1802  );
1803 
1804  // 1 = Freeze
1805  return UpdateAddressRestriction(request, 1);
1806 }
1807 
1809 {
1810  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 2 || request.params.size() > 3)
1811  throw std::runtime_error(
1812  "unfreezeaddress asset_name address (change_address)\n"
1814  "\nUnfreeze an address from transferring a restricted asset\n"
1815 
1816  "\nArguments:\n"
1817  "1. \"asset_name\" (string, required) the name of the restricted asset you want to unfreeze\n"
1818  "2. \"address\" (string, required) the address that will be unfrozen\n"
1819  "3. \"change_address\" (string, optional) The change address for the owner token of the restricted asset\n"
1820 
1821  "\nResult:\n"
1822  "\"txid\" (string) The transaction id\n"
1823 
1824  "\nExamples:\n"
1825  + HelpExampleCli("unfreezeaddress", "\"$RESTRICTED_ASSET\" \"address\"")
1826  + HelpExampleRpc("unfreezeaddress", "\"$RESTRICTED_ASSET\" \"address\"")
1827  + HelpExampleCli("unfreezeaddress", "\"$RESTRICTED_ASSET\" \"address\" \"change_address\"")
1828  + HelpExampleRpc("unfreezeaddress", "\"$RESTRICTED_ASSET\" \"address\" \"change_address\"")
1829  );
1830 
1831  // 0 = Unfreeze
1832  return UpdateAddressRestriction(request, 0);
1833 }
1834 
1836 {
1837  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 1 || request.params.size() > 2)
1838  throw std::runtime_error(
1839  "freezerestrictedasset asset_name (change_address)\n"
1841  "\nFreeze all trading for a specific restricted asset\n"
1842 
1843  "\nArguments:\n"
1844  "1. \"asset_name\" (string, required) the name of the restricted asset you want to unfreeze\n"
1845  "2. \"change_address\" (string, optional) The change address for the owner token of the restricted asset\n"
1846 
1847  "\nResult:\n"
1848  "\"txid\" (string) The transaction id\n"
1849 
1850  "\nExamples:\n"
1851  + HelpExampleCli("freezerestrictedasset", "\"$RESTRICTED_ASSET\"")
1852  + HelpExampleRpc("freezerestrictedasset", "\"$RESTRICTED_ASSET\"")
1853  + HelpExampleCli("freezerestrictedasset", "\"$RESTRICTED_ASSET\" \"change_address\"")
1854  + HelpExampleRpc("freezerestrictedasset", "\"$RESTRICTED_ASSET\" \"change_address\"")
1855  );
1856 
1857  // 1 = Freeze all trading
1858  return UpdateGlobalRestrictedAsset(request, 1);
1859 }
1860 
1862 {
1863  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 1 || request.params.size() > 2)
1864  throw std::runtime_error(
1865  "unfreezerestrictedasset asset_name (change_address)\n"
1867  "\nUnfreeze all trading for a specific restricted asset\n"
1868 
1869  "\nArguments:\n"
1870  "1. \"asset_name\" (string, required) the name of the restricted asset you want to unfreeze\n"
1871  "2. \"change_address\" (string, optional) The change address for the owner token of the restricted asset\n"
1872 
1873  "\nResult:\n"
1874  "\"txid\" (string) The transaction id\n"
1875 
1876  "\nExamples:\n"
1877  + HelpExampleCli("unfreezerestrictedasset", "\"$RESTRICTED_ASSET\"")
1878  + HelpExampleRpc("unfreezerestrictedasset", "\"$RESTRICTED_ASSET\"")
1879  + HelpExampleCli("unfreezerestrictedasset", "\"$RESTRICTED_ASSET\" \"change_address\"")
1880  + HelpExampleRpc("unfreezerestrictedasset", "\"$RESTRICTED_ASSET\" \"change_address\"")
1881  );
1882 
1883  // 0 = Unfreeze all trading
1884  return UpdateGlobalRestrictedAsset(request, 0);
1885 }
1886 
1888 {
1889  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() !=1)
1890  throw std::runtime_error(
1891  "listtagsforaddress address\n"
1893  "\nList all tags assigned to an address\n"
1894 
1895  "\nArguments:\n"
1896  "1. \"address\" (string, required) the address to list tags for\n"
1897 
1898  "\nResult:\n"
1899  "["
1900  "\"tag_name\", (string) The tag name\n"
1901  "...,\n"
1902  "]\n"
1903 
1904  "\nExamples:\n"
1905  + HelpExampleCli("listtagsforaddress", "\"address\"")
1906  + HelpExampleRpc("listtagsforaddress", "\"address\"")
1907  );
1908 
1909  if (!prestricteddb)
1910  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
1911 
1912  std::string address = request.params[0].get_str();
1913 
1914  // Check to make sure the given from address is valid
1915  CTxDestination dest = DecodeDestination(address);
1916  if (!IsValidDestination(dest))
1917  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Not valid RVN address: ") + address);
1918 
1919  std::vector<std::string> qualifiers;
1920 
1921  // This function forces a FlushStateToDisk so that a database scan and occur
1922  if (!prestricteddb->GetAddressQualifiers(address, qualifiers)) {
1923  throw JSONRPCError(RPC_DATABASE_ERROR, "Failed to search the database");
1924  }
1925 
1926  UniValue ret(UniValue::VARR);
1927  for (auto item : qualifiers) {
1928  ret.push_back(item);
1929  }
1930 
1931  return ret;
1932 }
1933 
1935 {
1936  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() !=1)
1937  throw std::runtime_error(
1938  "listaddressesfortag tag_name\n"
1940  "\nList all addresses that have been assigned a given tag\n"
1941 
1942  "\nArguments:\n"
1943  "1. \"tag_name\" (string, required) the tag asset name to search for\n"
1944 
1945  "\nResult:\n"
1946  "["
1947  "\"address\", (string) The address\n"
1948  "...,\n"
1949  "]\n"
1950 
1951  "\nExamples:\n"
1952  + HelpExampleCli("listaddressesfortag", "\"#TAG\"")
1953  + HelpExampleRpc("listaddressesfortag", "\"#TAG\"")
1954  );
1955 
1956  if (!prestricteddb)
1957  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
1958 
1959  std::string qualifier_name = request.params[0].get_str();
1960 
1961  if (!IsAssetNameAQualifier(qualifier_name))
1962  throw JSONRPCError(RPC_INVALID_PARAMETER, "You must use qualifier asset names only, qualifier assets start with '#'");
1963 
1964 
1965  std::vector<std::string> addresses;
1966 
1967  // This function forces a FlushStateToDisk so that a database scan and occur
1968  if (!prestricteddb->GetQualifierAddresses(qualifier_name, addresses)) {
1969  throw JSONRPCError(RPC_DATABASE_ERROR, "Failed to search the database");
1970  }
1971 
1972  UniValue ret(UniValue::VARR);
1973  for (auto item : addresses) {
1974  ret.push_back(item);
1975  }
1976 
1977  return ret;
1978 }
1979 
1981 {
1982  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() !=1)
1983  throw std::runtime_error(
1984  "listaddressrestrictions address\n"
1986  "\nList all assets that have frozen this address\n"
1987 
1988  "\nArguments:\n"
1989  "1. \"address\" (string), required) the address to list restrictions for\n"
1990 
1991  "\nResult:\n"
1992  "["
1993  "\"asset_name\", (string) The restriction name\n"
1994  "...,\n"
1995  "]\n"
1996 
1997  "\nExamples:\n"
1998  + HelpExampleCli("listaddressrestrictions", "\"address\"")
1999  + HelpExampleRpc("listaddressrestrictions", "\"address\"")
2000  );
2001 
2002  if (!prestricteddb)
2003  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
2004 
2005  std::string address = request.params[0].get_str();
2006 
2007  // Check to make sure the given from address is valid
2008  CTxDestination dest = DecodeDestination(address);
2009  if (!IsValidDestination(dest))
2010  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Not valid RVN address: ") + address);
2011 
2012  std::vector<std::string> restrictions;
2013 
2014  if (!prestricteddb->GetAddressRestrictions(address, restrictions)) {
2015  throw JSONRPCError(RPC_DATABASE_ERROR, "Failed to search the database");
2016  }
2017 
2018  UniValue ret(UniValue::VARR);
2019  for (auto item : restrictions) {
2020  ret.push_back(item);
2021  }
2022 
2023  return ret;
2024 }
2025 
2027 {
2028  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() != 0)
2029  throw std::runtime_error(
2030  "listglobalrestrictions\n"
2032  "\nList all global restricted assets\n"
2033 
2034 
2035  "\nResult:\n"
2036  "["
2037  "\"asset_name\", (string) The asset name\n"
2038  "...,\n"
2039  "]\n"
2040 
2041  "\nExamples:\n"
2042  + HelpExampleCli("listglobalrestrictions", "")
2043  + HelpExampleRpc("listglobalrestrictions", "")
2044  );
2045 
2046  if (!prestricteddb)
2047  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
2048 
2049  std::vector<std::string> restrictions;
2050 
2051  if (!prestricteddb->GetGlobalRestrictions(restrictions)) {
2052  throw JSONRPCError(RPC_DATABASE_ERROR, "Failed to search the database");
2053  }
2054 
2055  UniValue ret(UniValue::VARR);
2056  for (auto item : restrictions) {
2057  ret.push_back(item);
2058  }
2059 
2060  return ret;
2061 }
2062 
2064 {
2065  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() != 1)
2066  throw std::runtime_error(
2067  "getverifierstring restricted_name\n"
2069  "\nRetrieve the verifier string that belongs to the given restricted asset\n"
2070 
2071  "\nArguments:\n"
2072  "1. \"restricted_name\" (string, required) the asset_name\n"
2073 
2074  "\nResult:\n"
2075  "\"verifier_string\", (string) The verifier for the asset\n"
2076 
2077  "\nExamples:\n"
2078  + HelpExampleCli("getverifierstring", "\"restricted_name\"")
2079  + HelpExampleRpc("getverifierstring", "\"restricted_name\"")
2080  );
2081 
2082  if (!prestricteddb)
2083  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
2084 
2085  if (!passets) {
2086  throw JSONRPCError(RPC_DATABASE_ERROR, "Assets cache not available");
2087  }
2088 
2089  std::string asset_name = request.params[0].get_str();
2090 
2091  CNullAssetTxVerifierString verifier;
2092  if (!passets->GetAssetVerifierStringIfExists(asset_name, verifier))
2093  throw JSONRPCError(RPC_INVALID_PARAMETER, _("Verifier not found for asset: ") + asset_name);
2094 
2095  return verifier.verifier_string;
2096 }
2097 
2099 {
2100  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() != 2)
2101  throw std::runtime_error(
2102  "checkaddresstag address tag_name\n"
2104  "\nChecks to see if an address has the given tag\n"
2105 
2106  "\nArguments:\n"
2107  "1. \"address\" (string, required) the RVN address to search\n"
2108  "1. \"tag_name\" (string, required) the tag to search\n"
2109 
2110  "\nResult:\n"
2111  "\"true/false\", (boolean) If the address has the tag\n"
2112 
2113  "\nExamples:\n"
2114  + HelpExampleCli("checkaddresstag", "\"address\" \"tag_name\"")
2115  + HelpExampleRpc("checkaddresstag", "\"address\" \"tag_name\"")
2116  );
2117 
2118  if (!prestricteddb)
2119  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
2120 
2121  if (!passetsQualifierCache)
2122  throw JSONRPCError(RPC_DATABASE_ERROR, "Qualifier cache not available");
2123 
2124  if (!passets)
2125  throw JSONRPCError(RPC_DATABASE_ERROR, "Asset cache not available");
2126 
2127 
2128  std::string address = request.params[0].get_str();
2129  std::string qualifier_name = request.params[1].get_str();
2130 
2131  // Check to make sure the given from address is valid
2132  CTxDestination dest = DecodeDestination(address);
2133  if (!IsValidDestination(dest))
2134  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Not valid RVN address: ") + address);
2135 
2136  return passets->CheckForAddressQualifier(qualifier_name, address);
2137 }
2138 
2140 {
2141  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() != 2)
2142  throw std::runtime_error(
2143  "checkaddressrestriction address restricted_name\n"
2145  "\nChecks to see if an address has been frozen by the given restricted asset\n"
2146 
2147  "\nArguments:\n"
2148  "1. \"address\" (string, required) the RVN address to search\n"
2149  "1. \"restricted_name\" (string, required) the restricted asset to search\n"
2150 
2151  "\nResult:\n"
2152  "\"true/false\", (boolean) If the address is frozen\n"
2153 
2154  "\nExamples:\n"
2155  + HelpExampleCli("checkaddressrestriction", "\"address\" \"restricted_name\"")
2156  + HelpExampleRpc("checkaddressrestriction", "\"address\" \"restricted_name\"")
2157  );
2158 
2159  if (!prestricteddb)
2160  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
2161 
2163  throw JSONRPCError(RPC_DATABASE_ERROR, "Restriction cache not available");
2164 
2165  if (!passets)
2166  throw JSONRPCError(RPC_DATABASE_ERROR, "Asset cache not available");
2167 
2168  std::string address = request.params[0].get_str();
2169  std::string restricted_name = request.params[1].get_str();
2170 
2171  // Check to make sure the given from address is valid
2172  CTxDestination dest = DecodeDestination(address);
2173  if (!IsValidDestination(dest))
2174  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Not valid RVN address: ") + address);
2175 
2176  return passets->CheckForAddressRestriction(restricted_name, address);
2177 }
2178 
2180 {
2181  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() != 1)
2182  throw std::runtime_error(
2183  "checkglobalrestriction restricted_name\n"
2185  "\nChecks to see if a restricted asset is globally frozen\n"
2186 
2187  "\nArguments:\n"
2188  "1. \"restricted_name\" (string, required) the restricted asset to search\n"
2189 
2190  "\nResult:\n"
2191  "\"true/false\", (boolean) If the restricted asset is frozen globally\n"
2192 
2193  "\nExamples:\n"
2194  + HelpExampleCli("checkglobalrestriction", "\"restricted_name\"")
2195  + HelpExampleRpc("checkglobalrestriction", "\"restricted_name\"")
2196  );
2197 
2198  if (!prestricteddb)
2199  throw JSONRPCError(RPC_DATABASE_ERROR, "Restricted asset database not available");
2200 
2202  throw JSONRPCError(RPC_DATABASE_ERROR, "Restriction cache not available");
2203 
2204  if (!passets)
2205  throw JSONRPCError(RPC_DATABASE_ERROR, "Asset cache not available");
2206 
2207  std::string restricted_name = request.params[0].get_str();
2208 
2209  return passets->CheckForGlobalRestriction(restricted_name, true);
2210 }
2211 
2213 {
2214  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 4 || request.params.size() > 9)
2215  throw std::runtime_error(
2216  "issuerestrictedasset \"asset_name\" qty \"verifier\" \"to_address\" \"( change_address )\" (units) ( reissuable ) ( has_ipfs ) \"( ipfs_hash )\"\n"
2218  "\nIssue a restricted asset.\n"
2219  "Restricted asset names must not conflict with any existing restricted asset.\n"
2220  "Restricted assets have units set to 0.\n"
2221  "Reissuable is true/false for whether additional assets can be created and if the verifier string can be changed\n"
2222 
2223  "\nArguments:\n"
2224  "1. \"asset_name\" (string, required) a unique name, starts with '$'\n"
2225  "2. \"qty\" (numeric, required) the number of assets to be issued\n"
2226  "3. \"verifier\" (string, required) the KYC string that is evaluated when restricted asset transfers are made\n"
2227  "4. \"to_address\" (string, required), address asset will be sent to, this address must obey the verifier rules\n"
2228  "5. \"change_address\" (string, optional, default=\"\"), address the the rvn change will be sent to, if it is empty, change address will be generated for you\n"
2229  "6. \"units\" (integer, optional, default=0, min=0, max=8), the number of decimals precision for the asset (0 for whole units (\"1\"), 8 for max precision (\"1.00000000\")\n"
2230  "7. \"reissuable\" (boolean, optional, default=true (false for unique assets)), whether future reissuance is allowed\n"
2231  "8. \"has_ipfs\" (boolean, optional, default=false), whether ifps hash is going to be added to the asset\n"
2232  "9. \"ipfs_hash\" (string, optional but required if has_ipfs = 1), an ipfs hash or a txid hash once RIP5 is activated\n"
2233 
2234  "\nResult:\n"
2235  "\"txid\" (string) The transaction id\n"
2236 
2237  "\nExamples:\n"
2238  + HelpExampleCli("issuerestrictedasset", "\"$ASSET_NAME\" 1000 \"#KYC & !#AML\" \"myaddress\"")
2239  + HelpExampleCli("issuerestrictedasset", "\"$ASSET_NAME\" 1000 \"#KYC & !#AML\" \"myaddress\"")
2240  + HelpExampleCli("issuerestrictedasset", "\"$ASSET_NAME\" 1000 \"#KYC & !#AML\" \"myaddress\" \"changeaddress\" 5")
2241  + HelpExampleCli("issuerestrictedasset", "\"$ASSET_NAME\" 1000 \"#KYC & !#AML\" \"myaddress\" \"changeaddress\" 8 true")
2242  + HelpExampleCli("issuerestrictedasset", "\"$ASSET_NAME\" 1000 \"#KYC & !#AML\" \"myaddress\" \"changeaddress\" 0 false true QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E")
2243  );
2244 
2245  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2246  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2247  return NullUniValue;
2248  }
2249 
2250  ObserveSafeMode();
2251  LOCK2(cs_main, pwallet->cs_wallet);
2252 
2253  EnsureWalletIsUnlocked(pwallet);
2254 
2255  // Check asset name and infer assetType
2256  std::string assetName = request.params[0].get_str();
2257  AssetType assetType;
2258  std::string assetError = "";
2259  if (!IsAssetNameValid(assetName, assetType, assetError)) {
2260  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + assetName + std::string("\nError: ") + assetError);
2261  }
2262 
2263  // Check for unsupported asset types, only restricted assets are allowed for this rpc call
2264  if (assetType != AssetType::RESTRICTED) {
2265  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unsupported asset type: ") + AssetTypeToString(assetType));
2266  }
2267 
2268  // Get the remaining three required parameters
2269  CAmount nAmount = AmountFromValue(request.params[1]);
2270  std::string verifier_string = request.params[2].get_str();
2271  std::string to_address = request.params[3].get_str();
2272 
2273  // Validate the address
2274  CTxDestination destination = DecodeDestination(to_address);
2275  if (!IsValidDestination(destination)) {
2276  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + to_address);
2277  }
2278 
2279  // Validate the verifier string with the given to_address
2280  std::string strError = "";
2281  if (!ContextualCheckVerifierString(passets, verifier_string, to_address, strError, true))
2282  throw JSONRPCError(RPC_INVALID_PARAMETER, strError);
2283 
2284  // Get the change address if one was given
2285  std::string change_address = "";
2286  if (request.params.size() > 4)
2287  change_address = request.params[4].get_str();
2288  if (!change_address.empty()) {
2289  CTxDestination destination = DecodeDestination(change_address);
2290  if (!IsValidDestination(destination)) {
2292  std::string("Invalid Change Address: Invalid Raven address: ") + change_address);
2293  }
2294  }
2295 
2296  int units = MIN_UNIT;
2297  if (request.params.size() > 5)
2298  units = request.params[5].get_int();
2299 
2300  if (units < MIN_UNIT || units > MAX_UNIT)
2301  throw JSONRPCError(RPC_INVALID_PARAMETER, "Units must be between 0 and 8");
2302 
2303  // Restristed assets are reissuable by default
2304  bool reissuable = true;
2305  if (request.params.size() > 6)
2306  reissuable = request.params[6].get_bool();
2307 
2308  bool has_ipfs = false;
2309  if (request.params.size() > 7)
2310  has_ipfs = request.params[7].get_bool();
2311 
2312  // Check the ipfs
2313  std::string ipfs_hash = "";
2314  bool fMessageCheck = false;
2315  if (request.params.size() > 8 && has_ipfs) {
2316  fMessageCheck = true;
2317  ipfs_hash = request.params[8].get_str();
2318  }
2319 
2320  // issues don't have an expire time
2321  int64_t expireTime = 0;
2322 
2323  // Check the message data
2324  if (fMessageCheck)
2325  CheckIPFSTxidMessage(ipfs_hash, expireTime);
2326 
2327  CNewAsset asset(assetName, nAmount, units, reissuable ? 1 : 0, has_ipfs ? 1 : 0, DecodeAssetData(ipfs_hash));
2328 
2329  CReserveKey reservekey(pwallet);
2330  CWalletTx transaction;
2331  CAmount nRequiredFee;
2332  std::pair<int, std::string> error;
2333 
2334  CCoinControl crtl;
2335  crtl.destChange = DecodeDestination(change_address);
2336 
2337  std::string verifierStripped = GetStrippedVerifierString(verifier_string);
2338 
2339  // Create the Transaction
2340  if (!CreateAssetTransaction(pwallet, crtl, asset, to_address, error, transaction, reservekey, nRequiredFee, &verifierStripped))
2341  throw JSONRPCError(error.first, error.second);
2342 
2343  // Send the Transaction to the network
2344  std::string txid;
2345  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
2346  throw JSONRPCError(error.first, error.second);
2347 
2348  UniValue result(UniValue::VARR);
2349  result.push_back(txid);
2350  return result;
2351 }
2352 
2354 {
2355  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() < 3 || request.params.size() > 9)
2356  throw std::runtime_error(
2357  "reissuerestrictedasset \"asset_name\" qty to_address ( change_verifier ) ( \"new_verifier\" ) \"( to_address )\" \"( change_address )\" ( new_unit ) ( reissuable ) \"( ipfs_hash )\"\n"
2359  "\nReissue a already created restricted\n"
2360  "Reissuable is true/false for whether additional asset quantity can be created, an changing the verifier string\n"
2361 
2362  "\nArguments:\n"
2363  "1. \"asset_name\" (string, required) a unique name, starts with '$'\n"
2364  "2. \"qty\" (numeric, required) the number of assets to be issued\n"
2365  "3. \"to_address\" (string, required) address asset will be sent to, this address must have the verifier string requirements\n"
2366  "4. \"change_verifier\" (boolean, optional, default=false) If the verifier string will get changed\n"
2367  "5. \"verifier\" (string, optional, default=\"\") the KYC string that is evaluated when restricted asset transfers are made\n"
2368  "6. \"change_address\" (string, optional, default=\"\"), address the the rvn change will be sent to, if it is empty, change address will be generated for you\n"
2369  "7. \"new_unit\" (numeric, optional, default=-1), the new units that will be associated with the asset\n"
2370  "8. \"reissuable\" (boolean, optional, default=true (false for unique assets)), whether future reissuance is allowed\n"
2371  "9. \"ipfs_hash\" (string, optional but required if has_ipfs = 1), an ipfs hash or a txid hash once RIP5 is activated\n"
2372 
2373  "\nResult:\n"
2374  "\"txid\" (string) The transaction id\n"
2375 
2376  "\nExamples:\n"
2377  + HelpExampleCli("reissuerestrictedasset", "\"$ASSET_NAME\" 1000 \"myaddress\" true \"KYC && !AML\"")
2378  + HelpExampleCli("reissuerestrictedasset", "\"$ASSET_NAME\" 1000 \"myaddress\" true \"KYC && !AML\" ")
2379  + HelpExampleCli("reissuerestrictedasset", "\"$ASSET_NAME\" 1000 \"myaddress\" true \"KYC && !AML\" \"changeaddress\"")
2380  + HelpExampleCli("reissuerestrictedasset", "\"$ASSET_NAME\" 1000 \"myaddress\" true \"KYC && !AML\" \"changeaddress\" true")
2381  + HelpExampleCli("reissuerestrictedasset", "\"$ASSET_NAME\" 1000 \"myaddress\" false \"\" \"changeaddress\" -1 false true QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E")
2382  );
2383 
2384  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2385  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2386  return NullUniValue;
2387  }
2388 
2389  ObserveSafeMode();
2390  LOCK2(cs_main, pwallet->cs_wallet);
2391 
2392  EnsureWalletIsUnlocked(pwallet);
2393 
2394  // Check asset name and infer assetType
2395  std::string assetName = request.params[0].get_str();
2396  AssetType assetType;
2397  std::string assetError = "";
2398  if (!IsAssetNameValid(assetName, assetType, assetError)) {
2399  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid asset name: ") + assetName + std::string("\nError: ") + assetError);
2400  }
2401 
2402  // Check for unsupported asset types, only restricted assets are allowed for this rpc call
2403  if (assetType != AssetType::RESTRICTED) {
2404  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Unsupported asset type: ") + AssetTypeToString(assetType));
2405  }
2406 
2407  CAmount nAmount = AmountFromValue(request.params[1]);
2408  std::string to_address = request.params[2].get_str();
2409 
2410  CTxDestination to_dest = DecodeDestination(to_address);
2411  if (!IsValidDestination(to_dest)) {
2412  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + to_address);
2413  }
2414 
2415  bool fChangeVerifier = false;
2416  if (request.params.size() > 3)
2417  fChangeVerifier = request.params[3].get_bool();
2418 
2419  std::string verifier_string = "";
2420  if (request.params.size() > 4)
2421  verifier_string = request.params[4].get_str();
2422 
2423  std::string change_address = "";
2424  if (request.params.size() > 5) {
2425  change_address = request.params[5].get_str();
2426  CTxDestination change_dest = DecodeDestination(change_address);
2427  if (!IsValidDestination(change_dest)) {
2429  std::string("Invalid Change Address: Invalid Raven address: ") + change_address);
2430  }
2431  }
2432 
2433  int newUnits = -1;
2434  if (request.params.size() > 6)
2435  newUnits = request.params[6].get_int();
2436 
2437  if (newUnits < -1 || newUnits > MAX_UNIT)
2438  throw JSONRPCError(RPC_INVALID_PARAMETER, "Units must be between -1 and 8, -1 means don't change the current units");
2439 
2440  bool reissuable = true;
2441  if (request.params.size() > 7)
2442  reissuable = request.params[7].get_bool();
2443 
2444  std::string new_ipfs_data = "";
2445  bool fMessageCheck = false;
2446 
2447  if (request.params.size() > 8) {
2448  fMessageCheck = true;
2449  new_ipfs_data = request.params[8].get_str();
2450  }
2451 
2452  // Reissues don't have an expire time
2453  int64_t expireTime = 0;
2454 
2455  // Check the message data
2456  if (fMessageCheck)
2457  CheckIPFSTxidMessage(new_ipfs_data, expireTime);
2458 
2459  CReissueAsset reissueAsset(assetName, nAmount, newUnits, reissuable ? 1 : 0, DecodeAssetData(new_ipfs_data));
2460 
2461  CReserveKey reservekey(pwallet);
2462  CWalletTx transaction;
2463  CAmount nRequiredFee;
2464  std::pair<int, std::string> error;
2465 
2466  CCoinControl crtl;
2467  crtl.destChange = DecodeDestination(change_address);
2468 
2469  std::string verifierStripped = GetStrippedVerifierString(verifier_string);
2470 
2471  // Create the Transaction
2472  if (!CreateReissueAssetTransaction(pwallet, crtl, reissueAsset, to_address, error, transaction, reservekey, nRequiredFee, fChangeVerifier ? &verifierStripped : nullptr))
2473  throw JSONRPCError(error.first, error.second);
2474 
2475  std::string strError = "";
2476  if (!ContextualCheckReissueAsset(passets, reissueAsset, strError, *transaction.tx.get()))
2477  throw JSONRPCError(RPC_INVALID_REQUEST, strError);
2478 
2479  // Send the Transaction to the network
2480  std::string txid;
2481  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
2482  throw JSONRPCError(error.first, error.second);
2483 
2484  UniValue result(UniValue::VARR);
2485  result.push_back(txid);
2486  return result;
2487 }
2488 
2490 {
2491  if (request.fHelp || !AreAssetsDeployed() || request.params.size() < 3 || request.params.size() > 6)
2492  throw std::runtime_error(
2493  "transferqualifier \"qualifier_name\" qty \"to_address\" (\"change_address\") (\"message\") (expire_time) \n"
2495  "\nTransfer a qualifier asset owned by this wallet to the given address"
2496 
2497  "\nArguments:\n"
2498  "1. \"qualifier_name\" (string, required) name of qualifier asset\n"
2499  "2. \"qty\" (numeric, required) number of assets you want to send to the address\n"
2500  "3. \"to_address\" (string, required) address to send the asset to\n"
2501  "4. \"change_address\" (string, optional, default = \"\") the transaction change will be sent to this address\n"
2502  "5. \"message\" (string, optional) Once RIP5 is voted in ipfs hash or txid hash to send along with the transfer\n"
2503  "6. \"expire_time\" (numeric, optional) UTC timestamp of when the message expires\n"
2504 
2505  "\nResult:\n"
2506  "txid"
2507  "[ \n"
2508  "txid\n"
2509  "]\n"
2510 
2511  "\nExamples:\n"
2512  + HelpExampleCli("transferqualifier", "\"#QUALIFIER\" 20 \"to_address\" \"\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\" 15863654")
2513  + HelpExampleCli("transferqualifier", "\"#QUALIFIER\" 20 \"to_address\" \"change_address\" \"QmTqu3Lk3gmTsQVtjU7rYYM37EAW4xNmbuEAp2Mjr4AV7E\" 15863654")
2514  );
2515 
2516  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2517  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2518  return NullUniValue;
2519  }
2520 
2521  ObserveSafeMode();
2522  LOCK2(cs_main, pwallet->cs_wallet);
2523 
2524  EnsureWalletIsUnlocked(pwallet);
2525 
2526  std::string asset_name = request.params[0].get_str();
2527 
2528  if (!IsAssetNameAQualifier(asset_name))
2529  throw JSONRPCError(RPC_INVALID_PARAMETER, "Only use this rpc call to send Qualifier assets. Qualifier assets start with the character '#'");
2530 
2531  CAmount nAmount = AmountFromValue(request.params[1]);
2532 
2533  std::string to_address = request.params[2].get_str();
2534  CTxDestination to_dest = DecodeDestination(to_address);
2535  if (!IsValidDestination(to_dest)) {
2536  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + to_address);
2537  }
2538 
2539  std::string change_address = "";
2540  if(request.params.size() > 3) {
2541  change_address = request.params[3].get_str();
2542 
2543  CTxDestination change_dest = DecodeDestination(change_address);
2544  if (!IsValidDestination(change_dest)) {
2545  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Raven address: ") + change_address);
2546  }
2547  }
2548 
2549  if (request.params.size() > 4) {
2550  if (!AreMessagingDeployed()) {
2551  throw JSONRPCError(RPC_INVALID_PARAMS, std::string("Unable to send messages until Messaging RIP5 is enabled"));
2552  }
2553  }
2554 
2555  bool fMessageCheck = false;
2556  std::string message = "";
2557  if (request.params.size() > 4) {
2558  fMessageCheck = true;
2559  message = request.params[4].get_str();
2560  }
2561 
2562  int64_t expireTime = 0;
2563  if (!message.empty()) {
2564  if (request.params.size() > 5) {
2565  expireTime = request.params[5].get_int64();
2566  }
2567  }
2568 
2569  if (fMessageCheck)
2570  CheckIPFSTxidMessage(message, expireTime);
2571 
2572  std::pair<int, std::string> error;
2573  std::vector< std::pair<CAssetTransfer, std::string> >vTransfers;
2574 
2575  CAssetTransfer transfer(asset_name, nAmount, DecodeAssetData(message), expireTime);
2576 
2577  vTransfers.emplace_back(std::make_pair(transfer, to_address));
2578  CReserveKey reservekey(pwallet);
2579  CWalletTx transaction;
2580  CAmount nRequiredFee;
2581 
2582  CCoinControl ctrl;
2583  ctrl.destChange = DecodeDestination(change_address);
2584 
2585  // Create the Transaction
2586  if (!CreateTransferAssetTransaction(pwallet, ctrl, vTransfers, "", error, transaction, reservekey, nRequiredFee))
2587  throw JSONRPCError(error.first, error.second);
2588 
2589  // Send the Transaction to the network
2590  std::string txid;
2591  if (!SendAssetTransaction(pwallet, transaction, reservekey, error, txid))
2592  throw JSONRPCError(error.first, error.second);
2593 
2594  // Display the transaction id
2595  UniValue result(UniValue::VARR);
2596  result.push_back(txid);
2597  return result;
2598 }
2599 
2601 {
2602  if (request.fHelp || !AreRestrictedAssetsDeployed() || request.params.size() != 1)
2603  throw std::runtime_error(
2604  "isvalidverifierstring verifier_string\n"
2606  "\nChecks to see if the given verifier string is valid\n"
2607 
2608  "\nArguments:\n"
2609  "1. \"verifier_string\" (string, required) the verifier string to check\n"
2610 
2611  "\nResult:\n"
2612  "\"xxxxxxx\", (string) If the verifier string is valid, and the reason\n"
2613 
2614  "\nExamples:\n"
2615  + HelpExampleCli("isvalidverifierstring", "\"verifier_string\"")
2616  + HelpExampleRpc("isvalidverifierstring", "\"verifier_string\"")
2617  );
2618 
2619  ObserveSafeMode();
2620  LOCK(cs_main);
2621 
2622  if (!passets)
2623  throw JSONRPCError(RPC_DATABASE_ERROR, "Asset cache not available");
2624 
2625  std::string verifier_string = request.params[0].get_str();
2626 
2627  std::string strError;
2628  if (!ContextualCheckVerifierString(passets, verifier_string, "", strError, true)) {
2629  throw JSONRPCError(RPC_INVALID_PARAMETER, strError);
2630  }
2631 
2632  return _("Valid Verifier");
2633 }
2634 
2635 
2636 
2637 static const CRPCCommand commands[] =
2638 { // category name actor (function) argNames
2639  // ----------- ------------------------ ----------------------- ----------
2640  { "assets", "issue", &issue, {"asset_name","qty","to_address","change_address","units","reissuable","has_ipfs","ipfs_hash"} },
2641  { "assets", "issueunique", &issueunique, {"root_name", "asset_tags", "ipfs_hashes", "to_address", "change_address"}},
2642  { "assets", "listassetbalancesbyaddress", &listassetbalancesbyaddress, {"address", "onlytotal", "count", "start"} },
2643  { "assets", "getassetdata", &getassetdata, {"asset_name"}},
2644  { "assets", "listmyassets", &listmyassets, {"asset", "verbose", "count", "start", "confs"}},
2645  { "assets", "listaddressesbyasset", &listaddressesbyasset, {"asset_name", "onlytotal", "count", "start"}},
2646  { "assets", "transferfromaddress", &transferfromaddress, {"asset_name", "from_address" "qty", "to_address", "message", "expire_time"}},
2647  { "assets", "transferfromaddresses", &transferfromaddresses, {"asset_name", "from_addresses" "qty", "to_address", "message", "expire_time"}},
2648  { "assets", "transfer", &transfer, {"asset_name", "qty", "to_address", "message", "expire_time", "change_address"}},
2649  { "assets", "reissue", &reissue, {"asset_name", "qty", "to_address", "change_address", "reissuable", "new_unit", "new_ipfs"}},
2650  { "assets", "listassets", &listassets, {"asset", "verbose", "count", "start"}},
2651  { "assets", "getcacheinfo", &getcacheinfo, {}},
2652 
2653  { "restricted assets", "transferqualifier", &transferqualifier, {"qualifier_name", "qty", "to_address", "change_address", "message", "expire_time"}},
2654  { "restricted assets", "issuerestrictedasset", &issuerestrictedasset, {"asset_name","qty","verifier","to_address","change_address","units","reissuable","has_ipfs","ipfs_hash"} },
2655  { "restricted assets", "reissuerestrictedasset", &reissuerestrictedasset, {"asset_name", "qty", "change_verifier", "new_verifier", "to_address", "change_address", "new_unit", "reissuable", "ipfs_hash"}},
2656  { "restricted assets", "addtagtoaddress", &addtagtoaddress, {"tag_name", "to_address", "change_address"}},
2657  { "restricted assets", "removetagfromaddress", &removetagfromaddress, {"tag_name", "to_address", "change_address"}},
2658  { "restricted assets", "freezeaddress", &freezeaddress, {"asset_name", "address", "change_address"}},
2659  { "restricted assets", "unfreezeaddress", &unfreezeaddress, {"asset_name", "address", "change_address"}},
2660  { "restricted assets", "freezerestrictedasset", &freezerestrictedasset, {"asset_name", "change_address"}},
2661  { "restricted assets", "unfreezerestrictedasset", &unfreezerestrictedasset, {"asset_name", "change_address"}},
2662  { "restricted assets", "listaddressesfortag", &listaddressesfortag, {"tag_name"}},
2663  { "restricted assets", "listtagsforaddress", &listtagsforaddress, {"address"}},
2664  { "restricted assets", "listaddressrestrictions", &listaddressrestrictions, {"address"}},
2665  { "restricted assets", "listglobalrestrictions", &listglobalrestrictions, {}},
2666  { "restricted assets", "getverifierstring", &getverifierstring, {"restricted_name"}},
2667  { "restricted assets", "checkaddresstag", &checkaddresstag, {"address", "tag_name"}},
2668  { "restricted assets", "checkaddressrestriction", &checkaddressrestriction, {"address", "restricted_name"}},
2669  { "restricted assets", "checkglobalrestriction", &checkglobalrestriction, {"restricted_name"}},
2670  { "restricted assets", "isvalidverifierstring", &isvalidverifierstring, {"verifier_string"}}
2671 
2672 };
2673 
2675 {
2676  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
2677  t.appendCommand(commands[vcidx].name, &commands[vcidx]);
2678 }
#define OWNER_ASSET_AMOUNT
Definition: assets.h:35
#define UNIQUE_ASSET_AMOUNT
Definition: assets.h:36
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:89
bool CheckIssueDataTx(const CTxOut &txOut)
issue asset scripts to make sure script meets the standards
Definition: assets.cpp:3068
bool CreateAssetTransaction(CWallet *pwallet, CCoinControl &coinControl, const CNewAsset &asset, const std::string &address, std::pair< int, std::string > &error, CWalletTx &wtxNew, CReserveKey &reservekey, CAmount &nFeeRequired, std::string *verifier_string)
Creates new asset issuance transaction.
Definition: assets.cpp:3745
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:210
#define UNIQUE_ASSET_UNITS
Definition: assets.h:37
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:81
Raven RPC command dispatcher.
Definition: server.h:143
int8_t units
Definition: assettypes.h:102
CScript scriptPubKey
Definition: transaction.h:141
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or a pruned one if not found.
Definition: coins.cpp:390
bool get_bool() const
UniValue listassetbalancesbyaddress(const JSONRPCRequest &request)
Definition: assets.cpp:699
bool ContextualCheckReissueAsset(CAssetsCache *assetCache, const CReissueAsset &reissue_asset, std::string &strError, const CTransaction &tx)
Definition: assets.cpp:5273
void CheckIPFSTxidMessage(const std::string &message, int64_t expireTime)
Definition: assets.cpp:39
A UTXO entry.
Definition: coins.h:32
CLRUCache< std::string, int8_t > * passetsQualifierCache
Global variable that points to the asset address qualifier LRU Cache (protected by cs_main) ...
Definition: validation.cpp:236
bool CheckOwnerDataTx(const CTxOut &txOut)
Definition: assets.cpp:3085
bool CheckForGlobalRestriction(const std::string &restricted_name, bool fSkipTempCache=false)
Return true if the restricted asset is globally freezing trading.
Definition: assets.cpp:4651
CCriticalSection cs_wallet
Definition: wallet.h:751
bool CreateTransferAssetTransaction(CWallet *pwallet, const CCoinControl &coinControl, const std::vector< std::pair< CAssetTransfer, std::string > >vTransfers, const std::string &changeAddress, std::pair< int, std::string > &error, CWalletTx &wtxNew, CReserveKey &reservekey, CAmount &nFeeRequired, std::vector< std::pair< CNullAssetTxData, std::string > > *nullAssetTxData, std::vector< CNullAssetTxData > *nullGlobalRestrictionData)
Create a transfer asset transaction.
Definition: assets.cpp:4094
UniValue getcacheinfo(const JSONRPCRequest &request)
Definition: assets.cpp:1668
CRestrictedDB * prestricteddb
Global variable that points to the active restricted asset database (protected by cs_main) ...
Definition: validation.cpp:239
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
Definition: rpcwallet.cpp:63
bool AssetFromScript(const CScript &scriptPubKey, CNewAsset &assetNew, std::string &strAddress)
Definition: assets.cpp:664
bool TransferAssetFromScript(const CScript &scriptPubKey, CAssetTransfer &assetTransfer, std::string &strAddress)
Get specific asset type metadata from the given scripts.
Definition: assets.cpp:638
UniValue removetagfromaddress(const JSONRPCRequest &request)
Definition: assets.cpp:1754
CCriticalSection cs_main
Global state.
Definition: validation.cpp:72
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
Definition: coins.cpp:46
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:402
CTxOut out
unspent transaction output
Definition: coins.h:36
CTxDestination DecodeDestination(const std::string &str)
Definition: base58.cpp:333
bool GetAddressQualifiers(std::string &address, std::vector< std::string > &qualifiers)
UniValue listmyassets(const JSONRPCRequest &request)
Definition: assets.cpp:852
UniValue issue(const JSONRPCRequest &request)
Definition: assets.cpp:383
const std::string & get_str() const
std::string strName
Definition: assettypes.h:100
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: server.cpp:527
int64_t get_int64() const
UniValue unfreezerestrictedasset(const JSONRPCRequest &request)
Definition: assets.cpp:1861
UniValue ValueFromAmount(const CAmount &amount, const int8_t units)
Definition: core_write.cpp:38
CAssetsDB * passetsdb
RVN START.
Definition: validation.cpp:226
bool ReissueAssetFromScript(const CScript &scriptPubKey, CReissueAsset &reissue, std::string &strAddress)
Definition: assets.cpp:789
UniValue UpdateAddressTag(const JSONRPCRequest &request, const int8_t &flag)
Definition: assets.cpp:142
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:299
UniValue listglobalrestrictions(const JSONRPCRequest &request)
Definition: assets.cpp:2026
std::string strIPFSHash
Definition: assettypes.h:105
bool fAssetIndex
Definition: validation.cpp:84
UniValue UpdateGlobalRestrictedAsset(const JSONRPCRequest &request, const int8_t &flag)
Definition: assets.cpp:307
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:143
Coin Control Features.
Definition: coincontrol.h:17
#define QUALIFIER_ASSET_MAX_AMOUNT
Definition: assets.h:44
#define OWNER_UNITS
Definition: assets.h:34
Invalid, missing or duplicate parameter.
Definition: protocol.h:54
int8_t nReissuable
Definition: assettypes.h:103
UniValue isvalidverifierstring(const JSONRPCRequest &request)
Definition: assets.cpp:2600
CLRUCache< std::string, int8_t > * passetsRestrictionCache
Global variable that points to the asset address restriction LRU Cache (protected by cs_main) ...
Definition: validation.cpp:237
RVN START.
Definition: wallet.h:191
bool GetAssetData(const CScript &script, CAssetOutputEntry &data)
Definition: assets.cpp:3440
UniValue listaddressesfortag(const JSONRPCRequest &request)
Definition: assets.cpp:1934
int64_t CAmount
Amount in corbies (Can be negative)
Definition: amount.h:13
bool CheckTransferOwnerTx(const CTxOut &txOut)
Definition: assets.cpp:3093
General error during transaction or block submission.
Definition: protocol.h:57
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:3832
bool AreMessagingDeployed()
#define MAX_UNIT
Definition: assettypes.h:16
CCoinsViewCache * pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: validation.cpp:223
#define LOCK2(cs1, cs2)
Definition: sync.h:177
std::string name
Definition: server.h:135
bool IsAssetNameValid(const std::string &name, AssetType &assetType, std::string &error)
Definition: assets.cpp:207
#define UNIQUE_ASSETS_REISSUABLE
Definition: assets.h:38
void safe_advance(Iter &curr, const Iter &end, Incr n)
Definition: assets.cpp:842
UniValue transferfromaddresses(const JSONRPCRequest &request)
Definition: assets.cpp:1218
int8_t nHasIPFS
Definition: assettypes.h:104
std::string DecodeAssetData(std::string encoded)
Decode and Encode IPFS hashes, or OIP hashes.
Definition: assets.cpp:3699
UniValue issueunique(const JSONRPCRequest &request)
Definition: assets.cpp:552
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
bool AssetDir(std::vector< CDatabasedAssetData > &assets, const std::string filter, const size_t count, const long start)
Definition: assetdb.cpp:176
UniValue UnitValueFromAmount(const CAmount &amount, const std::string asset_name)
Definition: assets.cpp:122
bool AreAssetsDeployed()
RVN START.
UniValue transfer(const JSONRPCRequest &request)
Definition: assets.cpp:1101
CTransactionRef tx
Definition: wallet.h:211
UniValue params
Definition: server.h:45
CAssetsCache * GetCurrentAssetCache()
#define LOCK(cs)
Definition: sync.h:176
#define OWNER_TAG
Definition: assets.h:32
bool IsLocked() const
Definition: crypter.h:148
UniValue checkglobalrestriction(const JSONRPCRequest &request)
Definition: assets.cpp:2179
std::string assetName
Definition: wallet.h:194
CTxDestination destChange
Definition: coincontrol.h:20
std::map< std::string, uint256 > mapReissuedAssets
Definition: assets.cpp:41
An encapsulated public key.
Definition: pubkey.h:40
#define MIN_UNIT
Definition: assettypes.h:17
bool IsHex(const std::string &str)
void RegisterAssetRPCCommands(CRPCTable &t)
Register asset RPC commands.
Definition: assets.cpp:2674
bool CreateNewChangeAddress(CReserveKey &reservekey, CKeyID &keyID, std::string &strFailReason)
RVN START.
Definition: wallet.cpp:2756
UniValue getassetdata(const JSONRPCRequest &request)
Definition: assets.cpp:776
bool OwnerAssetFromScript(const CScript &scriptPubKey, std::string &assetName, std::string &strAddress)
Definition: assets.cpp:764
An output of a transaction.
Definition: transaction.h:137
int get_int() const
Invalid address or key.
Definition: protocol.h:52
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: server.cpp:522
CAmount AmountFromValue(const UniValue &value)
Definition: server.cpp:113
UniValue listaddressesbyasset(const JSONRPCRequest &request)
Definition: assets.cpp:1028
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
CLRUCache< std::string, int8_t > * passetsGlobalRestrictionCache
Global variable that points to the global asset restriction LRU Cache (protected by cs_main) ...
Definition: validation.cpp:238
bool SendAssetTransaction(CWallet *pwallet, CWalletTx &transaction, CReserveKey &reserveKey, std::pair< int, std::string > &error, std::string &txid)
Send any type of asset transaction to the network.
Definition: assets.cpp:4243
UniValue issuerestrictedasset(const JSONRPCRequest &request)
Definition: assets.cpp:2212
UniValue getverifierstring(const JSONRPCRequest &request)
Definition: assets.cpp:2063
bool isNull() const
Definition: univalue.h:79
UniValue reissuerestrictedasset(const JSONRPCRequest &request)
Definition: assets.cpp:2353
std::string GetUniqueAssetName(const std::string &parent, const std::string &tag)
Build a unique asset buy giving the root name, and the tag name (ROOT, TAG) => ROOT::TAG.
Definition: assets.cpp:399
std::string AssetActivationWarning()
Definition: assets.cpp:93
std::string GetStrippedVerifierString(const std::string &verifier)
Definition: assets.cpp:4728
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:285
bool GetQualifierAddresses(std::string &qualifier, std::vector< std::string > &addresses)
UniValue listassets(const JSONRPCRequest &request)
Definition: assets.cpp:1565
bool AreRestrictedAssetsDeployed()
AssetType
Definition: assettypes.h:21
Database error.
Definition: protocol.h:55
CAmount nAmount
Definition: assettypes.h:240
bool fHelp
Definition: server.h:46
void ListSelectedAssets(std::vector< COutPoint > &vOutpoints) const
Definition: coincontrol.h:118
void AvailableAssets(std::map< std::string, std::vector< COutput > > &mapAssetCoins, bool fOnlySafe=true, const CCoinControl *coinControl=nullptr, const CAmount &nMinimumAmount=1, const CAmount &nMaximumAmount=MAX_MONEY, const CAmount &nMinimumSumAmount=MAX_MONEY, const uint64_t &nMaximumCount=0, const int &nMinDepth=0, const int &nMaxDepth=9999999) const
Helper function that calls AvailableCoinsAll, used for transfering assets.
Definition: wallet.cpp:2165
CAssetsCache * passets
Global variable that point to the active assets (protected by cs_main)
Definition: validation.cpp:227
UniValue freezerestrictedasset(const JSONRPCRequest &request)
Definition: assets.cpp:1835
CAmount nAmount
Definition: assettypes.h:101
UniValue transferqualifier(const JSONRPCRequest &request)
Definition: assets.cpp:2489
#define ARRAYLEN(array)
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:326
void CheckRestrictedAssetTransferInputs(const CWalletTx &transaction, const std::string &asset_name)
Definition: assets.cpp:65
A key allocated from the key pool.
Definition: wallet.h:1193
UniValue listaddressrestrictions(const JSONRPCRequest &request)
Definition: assets.cpp:1980
UniValue UpdateAddressRestriction(const JSONRPCRequest &request, const int8_t &flag)
Definition: assets.cpp:225
bool CreateReissueAssetTransaction(CWallet *pwallet, CCoinControl &coinControl, const CReissueAsset &reissueAsset, const std::string &address, std::pair< int, std::string > &error, CWalletTx &wtxNew, CReserveKey &reservekey, CAmount &nFeeRequired, std::string *verifier_string)
Create a reissue asset transaction.
Definition: assets.cpp:3917
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:3940
bool GetAllMyAssetBalances(std::map< std::string, std::vector< COutput > > &outputs, std::map< std::string, CAmount > &amounts, const int confirmations, const std::string &prefix)
sets balances with the total quantity of each owned asset
Definition: assets.cpp:3673
UniValue checkaddressrestriction(const JSONRPCRequest &request)
Definition: assets.cpp:2139
bool GetGlobalRestrictions(std::vector< std::string > &restrictions)
std::map< uint256, std::string > mapReissuedTx
Definition: assets.cpp:40
bool CheckForAddressQualifier(const std::string &qualifier_name, const std::string &address, bool fSkipTempCache=false)
Return true if the address has the given qualifier assigned to it.
Definition: assets.cpp:4514
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:30
bool ContextualCheckVerifierString(CAssetsCache *cache, const std::string &verifier, const std::string &check_address, std::string &strError, bool fWithTags)
Definition: assets.cpp:4979
bool GetAddressRestrictions(std::string &address, std::vector< std::string > &restrictions)
UniValue listtagsforaddress(const JSONRPCRequest &request)
Definition: assets.cpp:1887
bool AddressDir(std::vector< std::pair< std::string, CAmount > > &vecAssetAmount, int &totalEntries, const bool &fGetTotal, const std::string &address, const size_t count, const long start)
Definition: assetdb.cpp:247
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:673
std::string RestrictedActivationWarning()
Definition: assets.cpp:98
bool IsAssetNameAQualifier(const std::string &name)
Check if an asset is a qualifier asset or sub qualifier.
Definition: assets.cpp:306
UniValue freezeaddress(const JSONRPCRequest &request)
Definition: assets.cpp:1781
const UniValue NullUniValue
Definition: univalue.cpp:15
CWallet * GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: rpcwallet.cpp:40
bool error(const char *fmt, const Args &... args)
Definition: util.h:168
UniValue unfreezeaddress(const JSONRPCRequest &request)
Definition: assets.cpp:1808
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:818
void ObserveSafeMode()
Definition: safemode.cpp:7
bool GetKeyFromPool(CPubKey &key, bool internal=false)
Definition: wallet.cpp:4056
Standard JSON-RPC 2.0 errors.
Definition: protocol.h:38
Wallet errors.
Definition: protocol.h:78
UniValue JSONRPCError(int code, const std::string &message)
Definition: protocol.cpp:55
bool GetAssetVerifierStringIfExists(const std::string &name, CNullAssetTxVerifierString &verifier, bool fSkipTempCache=false)
Returns true if the Asset Verifier String was found for an asset_name, if fSkipTempCache is true...
Definition: assets.cpp:4445
size_t size() const
Definition: univalue.h:70
bool CheckForAddressRestriction(const std::string &restricted_name, const std::string &address, bool fSkipTempCache=false)
Return true if the address is marked as frozen.
Definition: assets.cpp:4593
CLRUCache< std::string, CDatabasedAssetData > * passetsCache
Global variable that point to the assets metadata LRU Cache (protected by cs_main) ...
Definition: validation.cpp:228
bool AssetAddressDir(std::vector< std::pair< std::string, CAmount > > &vecAddressAmount, int &totalEntries, const bool &fGetTotal, const std::string &assetName, const size_t count, const long start)
Definition: assetdb.cpp:320
std::string AssetTypeToString(AssetType &assetType)
Definition: assets.cpp:103
bool IsAsset() const
Definition: coins.h:82
CTxDestination destination
Definition: wallet.h:195
UniValue transferfromaddress(const JSONRPCRequest &request)
Definition: assets.cpp:1346
void SelectAsset(const COutPoint &output)
Definition: coincontrol.h:86
std::string EncodeAssetData(std::string decoded)
Definition: assets.cpp:3716
bool IsUniqueTagValid(const std::string &tag)
Check if an unique tagname is valid.
Definition: assets.cpp:126
bool isArray() const
Definition: univalue.h:85
UniValue addtagtoaddress(const JSONRPCRequest &request)
Definition: assets.cpp:1727
CAmount nAmount
Definition: assettypes.h:191
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: util.h:66
bool CheckReissueDataTx(const CTxOut &txOut)
Definition: assets.cpp:3077
UniValue reissue(const JSONRPCRequest &request)
Definition: assets.cpp:1465
bool IsAssetNameAnRestricted(const std::string &name)
Check if an asset is a restricted asset.
Definition: assets.cpp:301
void EnsureWalletIsUnlocked(CWallet *const pwallet)
Definition: rpcwallet.cpp:80
bool IsAssetNameAnOwner(const std::string &name)
Check if an asset is an owner.
Definition: assets.cpp:296
UniValue checkaddresstag(const JSONRPCRequest &request)
Definition: assets.cpp:2098