Skip to content

Commit

Permalink
[BROKEN] Add issuance wallet RPCs
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenroose committed Mar 20, 2019
1 parent a361dda commit f7920d7
Show file tree
Hide file tree
Showing 3 changed files with 536 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,17 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "combineblocksigs", 1, "signatures" },
{ "sendtomainchain", 1, "amount" },
{ "sendtomainchain", 2, "subtractfeefromamount" },
{ "dumpissuanceblindingkey", 1, "vin" },
{ "importissuanceblindingkey", 1, "vin" },
{ "rawissueasset", 1, "issuances" },
{ "rawreissueasset", 1, "reissuances" },
{ "getnewblockhex", 0, "required_age" },
{ "testproposedblock", 1, "acceptnonstd" },
{ "issueasset", 0, "assetamount" },
{ "issueasset", 1, "tokenamount" },
{ "issueasset", 2, "blind" },
{ "reissueasset", 1, "assetamount" },
{ "initpegoutwallet", 1, "bip32_counter"},
{ "rawblindrawtransaction", 1, "inputblinder" },
{ "rawblindrawtransaction", 2, "inputamount" },
{ "rawblindrawtransaction", 3, "inputasset" },
Expand All @@ -177,6 +186,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "blindrawtransaction", 1, "assetcommitments" },
{ "blindrawtransaction", 2, "ignoreblindfail" },
{ "blindrawtransaction", 3, "blind_issuances" },
{ "destroyamount", 1, "amount" },
{ "sendmany", 7 , "output_assets" },
{ "sendmany", 8 , "ignoreblindfail" },
{ "sendtoaddress", 9 , "ignoreblindfail" },
Expand Down
138 changes: 138 additions & 0 deletions src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,81 @@ UniValue importblindingkey(const JSONRPCRequest& request)
return NullUniValue;
}

UniValue importissuanceblindingkey(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();

if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}

if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
"importissuanceblindingkey \"txid\" vin \"blindingkey\"\n"
"\nImports a private blinding key in hex for an asset issuance."
"\nArguments:\n"

"1. \"txid\" (string, required) The transaction id of the issuance\n"
"2. \"vin\" (numeric, required) The input number of the issuance in the transaction.\n"
"3. \"blindingkey\" (string, required) The blinding key in hex\n"
"\nExample:\n"
+ HelpExampleCli("importblindingkey", "\"my blinded CT address\" <blindinghex>")
);

LOCK2(cs_main, pwallet->cs_wallet);

if (!request.params[0].isStr() || !IsHex(request.params[0].get_str()) || request.params[0].get_str().size() != 64) {
throw JSONRPCError(RPC_TYPE_ERROR, "First argument must be a txid string");
}
std::string txidstr = request.params[0].get_str();
uint256 txid;
txid.SetHex(txidstr);

uint32_t vindex;
if (!request.params[1].isNum()) {
throw JSONRPCError(RPC_TYPE_ERROR, "vin must be an integer");
}
vindex = request.params[1].get_int();

if (!request.params[2].isStr() || !IsHex(request.params[2].get_str()) || request.params[2].get_str().size() != 64) {
throw JSONRPCError(RPC_TYPE_ERROR, "blinding key must be a hex string of length 64");
}

std::vector<unsigned char> keydata = ParseHex(request.params[2].get_str());
if (keydata.size() != 32) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid hexadecimal key length");
}
CKey key;
key.Set(keydata.begin(), keydata.end(), true);

// Process as issuance key dump
for (std::map<uint256, CWalletTx>::const_iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) {
const CWalletTx* pcoin = &(*it).second;
if (pcoin->GetHash() != txid) {
continue;
}
if (pcoin->tx->vin.size() <= vindex) {
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction is in wallet but vin does not exist");
}
if (pcoin->tx->vin[vindex].assetIssuance.IsNull()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction input has no issuance");
}

// Import the key in that slot
uint256 keyval;
memcpy(keyval.begin(), &keydata[0], 32);
CScript blindingScript(CScript() << OP_RETURN << std::vector<unsigned char>(pcoin->tx->vin[vindex].prevout.hash.begin(), pcoin->tx->vin[vindex].prevout.hash.end()) << pcoin->tx->vin[vindex].prevout.n);
if (!pwallet->AddSpecificBlindingKey(CScriptID(blindingScript), keyval)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Failed to import blinding key");
}
pwallet->MarkDirty();
return NullUniValue;
}

throw JSONRPCError(RPC_WALLET_ERROR, "Transaction is unknown to wallet.");
}

UniValue dumpblindingkey(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
Expand Down Expand Up @@ -1443,3 +1518,66 @@ UniValue dumpblindingkey(const JSONRPCRequest& request)

throw JSONRPCError(RPC_WALLET_ERROR, "Blinding key for address is unknown");
}

UniValue dumpissuanceblindingkey(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();

if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}

if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
"dumpissuanceblindingkey \"txid\" vin\n"
"\nDumps the private blinding key for an asset issuance in wallet."
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id of the issuance\n"
"2. \"vin\" (numeric, required) The input number of the issuance in the transaction.\n"
"\nResult:\n"
"\"blindingkey\" (string) The blinding key\n"
"\nExample:\n"
+ HelpExampleCli("dumpissuanceblindingkey", "\"<txid>\", 0")
);

LOCK2(cs_main, pwallet->cs_wallet);

if (!request.params[0].isStr() || !IsHex(request.params[0].get_str()) || request.params[0].get_str().size() != 64) {
throw JSONRPCError(RPC_TYPE_ERROR, "First argument must be a txid string");
}
std::string txidstr = request.params[0].get_str();
uint256 txid;
txid.SetHex(txidstr);

uint32_t vindex;
if (!request.params[1].isNum()) {
throw JSONRPCError(RPC_TYPE_ERROR, "vin must be an integer");
}
vindex = request.params[1].get_int();

// Process as issuance key dump
for (std::map<uint256, CWalletTx>::const_iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) {
const CWalletTx* pcoin = &(*it).second;
if (pcoin->tx->GetHash() != txid) {
continue;
}
if (pcoin->tx->vin.size() <= vindex) {
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction is in wallet but vin does not exist");
}
if (pcoin->tx->vin[vindex].assetIssuance.IsNull()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction input has no issuance");
}
// We can actually deblind the input
if (pcoin->GetIssuanceAmount(vindex, false) != -1 ) {
CScript blindingScript(CScript() << OP_RETURN << std::vector<unsigned char>(pcoin->tx->vin[vindex].prevout.hash.begin(), pcoin->tx->vin[vindex].prevout.hash.end()) << pcoin->tx->vin[vindex].prevout.n);
CKey key;
key = pwallet->GetBlindingKey(&blindingScript);
return HexStr(key.begin(), key.end());
} else {
// We don't know how to deblind this using our wallet
throw JSONRPCError(RPC_WALLET_ERROR, "Unable to unblind issuance with wallet blinding key.");
}
}
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction is unknown to wallet.");
}
Loading

0 comments on commit f7920d7

Please sign in to comment.