diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 943a168df1..3416bd59d2 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -120,6 +120,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "issueasset", 0, "assetamount" }, { "issueasset", 1, "tokenamount" }, { "issueasset", 2, "blind" }, + { "reissueasset", 1, "assetamount" }, { "setban", 3, "absolute" }, { "setnetworkactive", 0, "state" }, { "getmempoolancestors", 1, "verbose" }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fe9a6ad6f3..c6ca52127b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3803,6 +3803,94 @@ UniValue issueasset(const JSONRPCRequest& request) return ret; } +UniValue reissueasset(const JSONRPCRequest& request) +{ + if (!EnsureWalletIsAvailable(request.fHelp)) + return NullUniValue; + + if (request.fHelp || request.params.size() != 2) + throw runtime_error( + "reissueasset asset assetamount\n" + "\nCreate more of an already issued asset. Must have reissuance token in wallet to do so. Reissuing does not affect your reissuance token balance, only asset.\n" + "\nArguments:\n" + "1. \"asset\" (string, required) The asset you want to re-issue. The corresponding token must be in your wallet.\n" + "2. \"assetamount\" (numeric or string, required) Amount of additional asset to generate.\n" + "\nResult:\n" + "\"txid\" (string) Txid of the issuance transaction\n" + "\nExamples:\n" + + HelpExampleCli("reissueasset", " 0") + + HelpExampleRpc("reissueasset", ", 0") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + std::string assetstr = request.params[0].get_str(); + + CAsset asset = GetAssetFromString(assetstr); + + CAmount nAmount = AmountFromValue(request.params[1]); + if (nAmount <= 0) + throw JSONRPCError(RPC_TYPE_ERROR, "Reissuance must create a non-zero amount."); + + if (!pwalletMain->IsLocked()) + pwalletMain->TopUpKeyPool(); + + // Find the entropy and reissuance token in wallet + std::map > tokenMap = pwalletMain->GetReissuanceTokenTypes(); + CAsset reissuanceToken; + uint256 entropy; + for (const auto& it : tokenMap) { + if (it.second.second == asset) { + reissuanceToken = it.second.first; + entropy = it.first; + } + if (it.second.first == asset) { + throw JSONRPCError(RPC_WALLET_ERROR, "Asset given is a reissuance token type and can not be reissued."); + } + } + if (reissuanceToken.IsNull()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Asset reissuance token definition could not be found in wallet."); + } + + CPubKey newKey; + CKeyID keyID; + CBitcoinAddress assetAddr; + CPubKey assetKey; + CBitcoinAddress tokenAddr; + CPubKey tokenKey; + + // Add destination for the to-be-created asset + if (!pwalletMain->GetKeyFromPool(newKey)) + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); + keyID = newKey.GetID(); + pwalletMain->SetAddressBook(keyID, "", "receive"); + assetAddr = CBitcoinAddress(keyID); + assetKey = pwalletMain->GetBlindingPubKey(GetScriptForDestination(assetAddr.Get())); + + // Add destination for tokens we are moving + if (!pwalletMain->GetKeyFromPool(newKey)) + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); + keyID = newKey.GetID(); + pwalletMain->SetAddressBook(keyID, "", "receive"); + tokenAddr = CBitcoinAddress(keyID); + tokenKey = pwalletMain->GetBlindingPubKey(GetScriptForDestination(CTxDestination(keyID))); + + // Attempt a send. + CWalletTx wtx; + SendGenerationTransaction(GetScriptForDestination(assetAddr.Get()), assetKey, GetScriptForDestination(tokenAddr.Get()), tokenKey, nAmount, -1, true, entropy, asset, reissuanceToken, wtx); + + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("txid", wtx.tx->GetHash().GetHex())); + for (uint64_t i = 0; i < wtx.tx->vin.size(); i++) { + if (!wtx.tx->vin[i].assetIssuance.IsNull()) { + obj.push_back(Pair("vin", i)); + break; + } + } + + return obj; +} + UniValue dumpassetlabels(const JSONRPCRequest& request) { if (!EnsureWalletIsAvailable(request.fHelp)) @@ -3882,6 +3970,7 @@ static const CRPCCommand commands[] = { "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom"} }, { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} }, { "wallet", "setaccount", &setaccount, true, {"address","account"} }, + { "wallet", "reissueasset", &reissueasset, true, {"asset", "assetamount"} }, { "wallet", "signblock", &signblock, true, {} }, { "wallet", "sendtomainchain", &sendtomainchain, false, {} }, { "wallet", "destroyamount", &destroyamount, false, {"asset", "amount", "comment"} },