Skip to content

Commit

Permalink
add generatepegoutproof RPC call
Browse files Browse the repository at this point in the history
  • Loading branch information
instagibbs committed Mar 21, 2019
1 parent e9f6e82 commit 4d486e6
Showing 1 changed file with 99 additions and 0 deletions.
99 changes: 99 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6026,6 +6026,104 @@ UniValue destroyamount(const JSONRPCRequest& request)
return tx->GetHash().GetHex();
}

// Only used for functionary integration tests
UniValue generatepegoutproof(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(
"generatepegoutproof sumkey btcpubkey onlinepubkey\n"
"\nONLY FOR TESTING: Generates pegout authorization proof for pegout based on the summed privkey and returns in hex. Result should be passed as an argument in `sendtomainchain`. Caution: Whitelist proof-validating mempools will filter incorrect pegoutproofs but aren't consensus enforced!\n"
"\nArguments:\n"
"1. \"sumkey\" (string, required) Base58 summed key of Bitcoin and offline key\n"
"2. \"btcpubkey\" (string, required) Hex pegout destination Bitcoin pubkey\n"
"3. \"onlinepubkey\" (string, required) hex `online pubkey`\n"
"\nResult:\n"
"\"pegoutproof\" (string, hex) pegout authorization proof to be passed into sendtomainchain\n"
+ HelpExampleCli("generatepegoutproof", "\"cQtNrRngdc4RJ9CkuTVKVLyxPFsijiTJySob24xCdKXGohdFhXML\" \"02c611095119e3dc96db428a0e190a3e142237bcd2efa4fb358257497885af3ab6\" \"0390695fff5535780df1e04c1f6c10e7c0a399fa56cfce34bf8108d0a9bc7a437b\"")
+ HelpExampleRpc("generatepegoutproof", "\"cQtNrRngdc4RJ9CkuTVKVLyxPFsijiTJySob24xCdKXGohdFhXML\" \"02c611095119e3dc96db428a0e190a3e142237bcd2efa4fb358257497885af3ab6\" \"0390695fff5535780df1e04c1f6c10e7c0a399fa56cfce34bf8108d0a9bc7a437b\"")
);

LOCK2(cs_main, pwallet->cs_wallet);

if (!IsHex(request.params[1].get_str()))
throw JSONRPCError(RPC_TYPE_ERROR, "btcpubkey must be hex string");
if (!IsHex(request.params[2].get_str()))
throw JSONRPCError(RPC_TYPE_ERROR, "onlinepubkey must be hex string");

//Parse private keys

CKey summedSecret = DecodeSecret(request.params[0].get_str());
if (!summedSecret.IsValid()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid summed private key encoding");
}

std::vector<unsigned char> sumprivkeybytes(summedSecret.begin(), summedSecret.end());
std::vector<unsigned char> btcpubkeybytes = ParseHex(request.params[1].get_str());
std::vector<unsigned char> onlinepubkeybytes = ParseHex(request.params[2].get_str());

//Parse onlinepubkey
CPubKey onlinepubkey;
onlinepubkey.Set(onlinepubkeybytes.begin(), onlinepubkeybytes.end());
if (!onlinepubkey.IsFullyValid())
throw JSONRPCError(RPC_WALLET_ERROR, "Invalid online pubkey");
secp256k1_pubkey onlinepubkey_secp;
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &onlinepubkey_secp, &onlinepubkeybytes[0], onlinepubkeybytes.size()))
throw JSONRPCError(RPC_WALLET_ERROR, "Invalid online pubkey");

CPAKList paklist = g_paklist_blockchain;
if (g_paklist_config) {
paklist = *g_paklist_config;
}
if (paklist.IsReject()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pegout freeze is under effect to aid a pak transition to a new list. Please consult the network operator.");
}

//Find PAK online pubkey on PAK list
int whitelistindex=-1;
std::vector<secp256k1_pubkey> pak_online = paklist.OnlineKeys();
for (unsigned int i=0; i<pak_online.size(); i++) {
if (!memcmp((void *)&pak_online[i], (void *)&onlinepubkey_secp, sizeof(secp256k1_pubkey)))
whitelistindex = i;
}
if (whitelistindex == -1)
throw JSONRPCError(RPC_WALLET_ERROR, "Given online key is not in Pegout Authorization Key List");

CKey masterOnlineKey;
if (!pwallet->GetKey(onlinepubkey.GetID(), masterOnlineKey))
throw JSONRPCError(RPC_WALLET_ERROR, "Given online key is in master set but not in wallet");

//Parse own offline pubkey
secp256k1_pubkey btcpubkey;
if (secp256k1_ec_pubkey_parse(secp256k1_ctx, &btcpubkey, &btcpubkeybytes[0], btcpubkeybytes.size()) != 1)
throw JSONRPCError(RPC_WALLET_ERROR, "btcpubkey is invalid pubkey");

//Create, verify whitelist proof
secp256k1_whitelist_signature sig;
if(secp256k1_whitelist_sign(secp256k1_ctx, &sig, &paklist.OnlineKeys()[0], &paklist.OfflineKeys()[0], paklist.size(), &btcpubkey, masterOnlineKey.begin(), &sumprivkeybytes[0], whitelistindex, NULL, NULL) != 1)
throw JSONRPCError(RPC_WALLET_ERROR, "Pegout authorization proof signing failed");

if (secp256k1_whitelist_verify(secp256k1_ctx, &sig, &paklist.OnlineKeys()[0], &paklist.OfflineKeys()[0], paklist.size(), &btcpubkey) != 1)
throw JSONRPCError(RPC_WALLET_ERROR, "Pegout authorization proof was created and signed but is invalid");

//Serialize and return as hex
size_t expectedOutputSize = 1 + 32 * (1 + paklist.size());
const size_t preSize = expectedOutputSize;
assert(1 + 32 * (1 + 256) >= expectedOutputSize);
unsigned char output[1 + 32 * (1 + 256)];
secp256k1_whitelist_signature_serialize(secp256k1_ctx, output, &expectedOutputSize, &sig);
assert(expectedOutputSize == preSize);
std::vector<unsigned char> voutput(output, output + expectedOutputSize / sizeof(output[0]));

return HexStr(voutput.begin(), voutput.end());
}


// END ELEMENTS commands
//
Expand Down Expand Up @@ -6124,6 +6222,7 @@ static const CRPCCommand commands[] =
{ "wallet", "issueasset", &issueasset, {"assetamount", "tokenamount", "blind"}},
{ "wallet", "reissueasset", &reissueasset, {"asset", "assetamount"}},
{ "wallet", "destroyamount", &destroyamount, {"asset", "amount", "comment"} },
{ "hidden", "generatepegoutproof", &generatepegoutproof, {"sumkey", "btcpubkey", "onlinepubkey"} },
};
// clang-format on

Expand Down

0 comments on commit 4d486e6

Please sign in to comment.