Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

z_embedstring and z_readstring #66

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/rpcclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getnetworkhashps", 1 },
{ "sendtoaddress", 1 },
{ "sendtoaddress", 4 },
{ "z_embedstring", 1 },
{ "settxfee", 0 },
{ "getreceivedbyaddress", 1 },
{ "getreceivedbyaccount", 1 },
Expand Down Expand Up @@ -73,6 +74,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getblockheader", 1 },
{ "gettransaction", 1 },
{ "getrawtransaction", 1 },
{ "z_readstring", 0 },
{ "createrawtransaction", 0 },
{ "createrawtransaction", 1 },
{ "signrawtransaction", 1 },
Expand Down
67 changes: 67 additions & 0 deletions src/rpcrawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,73 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp)
return result;
}

UniValue z_readstring(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"z_readstring \"txid\"\n"
"\nNOTE: By default this function only works sometimes. This is when the tx is in the mempool\n"
"or there is an unspent output in the utxo for this transaction. To make it always work,\n"
"you need to maintain a transaction index, using the -txindex command line option.\n"
"\nReturn the string embedded into the transaction with z_embedstring (as a json object).\n"

"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id\n"


"\nResult:\n"
"\"embedded-string\" (string) The embedded string.\n"

"\nExamples:\n"
+ HelpExampleCli("z_readstring", "\"mytxid\"")
);

LOCK(cs_main);

uint256 hash = ParseHashV(params[0], "parameter 1");

CTransaction tx;
uint256 hashBlock;
if (!GetTransaction(hash, tx, hashBlock, true))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");

UniValue bad_txn = JSONRPCError(RPC_INVALID_PARAMETER, "It doesn't look like this transaction was created with z_embedstring.");

if (tx.vout.size() < 1 || tx.vjoinsplit.size() > 0) {
throw bad_txn;
}

// Find the first script beginning with OP_RETURN.
for (size_t i = 0; i < tx.vout.size(); i++) {
CScript script = tx.vout[i].scriptPubKey;
opcodetype opcode;
std::vector<unsigned char> vch;
CScript::const_iterator pc = script.begin();

if (!script.GetOp(pc, opcode, vch)) {
throw bad_txn;
}
if (opcode == OP_RETURN) {
// Next should come the embedded string.
if (!script.GetOp(pc, opcode, vch)) {
throw bad_txn;
}
if (opcode < 0 || opcode > OP_PUSHDATA4) {
throw bad_txn;
}

// Make sure there there's nothing else after the embedded string.
if (pc < script.end()) {
throw bad_txn;
}
return std::string(vch.begin(), vch.end());
}
}

// Didn't find an OP_RETURN.
throw bad_txn;
}

UniValue gettxoutproof(const UniValue& params, bool fHelp)
{
if (fHelp || (params.size() != 1 && params.size() != 2))
Expand Down
2 changes: 2 additions & 0 deletions src/rpcserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ static const CRPCCommand vRPCCommands[] =
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, true },
{ "rawtransactions", "decodescript", &decodescript, true },
{ "rawtransactions", "getrawtransaction", &getrawtransaction, true },
{ "rawtransactions", "z_readstring", &z_readstring, true },
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, false },
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */
#ifdef ENABLE_WALLET
Expand Down Expand Up @@ -373,6 +374,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "sendfrom", &sendfrom, false },
{ "wallet", "sendmany", &sendmany, false },
{ "wallet", "sendtoaddress", &sendtoaddress, false },
{ "wallet", "z_embedstring", &z_embedstring, false },
{ "wallet", "setaccount", &setaccount, true },
{ "wallet", "settxfee", &settxfee, true },
{ "wallet", "signmessage", &signmessage, true },
Expand Down
2 changes: 2 additions & 0 deletions src/rpcserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ extern UniValue setaccount(const UniValue& params, bool fHelp);
extern UniValue getaccount(const UniValue& params, bool fHelp);
extern UniValue getaddressesbyaccount(const UniValue& params, bool fHelp);
extern UniValue sendtoaddress(const UniValue& params, bool fHelp);
extern UniValue z_embedstring(const UniValue& params, bool fHelp);
extern UniValue signmessage(const UniValue& params, bool fHelp);
extern UniValue verifymessage(const UniValue& params, bool fHelp);
extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp);
Expand Down Expand Up @@ -247,6 +248,7 @@ extern UniValue zc_raw_receive(const UniValue& params, bool fHelp);
extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp);

extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rcprawtransaction.cpp
extern UniValue z_readstring(const UniValue& params, bool fHelp); // in rcprawtransaction.cpp
extern UniValue listunspent(const UniValue& params, bool fHelp);
extern UniValue lockunspent(const UniValue& params, bool fHelp);
extern UniValue listlockunspent(const UniValue& params, bool fHelp);
Expand Down
50 changes: 46 additions & 4 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
return ret;
}

static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
static void SendMoney(const CScript &scriptPubKey, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
{
CAmount curBalance = pwalletMain->GetBalance();

Expand All @@ -377,8 +377,9 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
if (nValue > curBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");

// TODO: no longer needed?
// Parse Hush address
CScript scriptPubKey = GetScriptForDestination(address);
//CScript scriptPubKey = GetScriptForDestination(address);

// Create and send the transaction
CReserveKey reservekey(pwalletMain);
Expand Down Expand Up @@ -450,7 +451,48 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)

EnsureWalletIsUnlocked();

SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
SendMoney(GetScriptForDestination(address.Get()), nAmount, fSubtractFeeFromAmount, wtx);

return wtx.GetHash().GetHex();
}

UniValue z_embedstring(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;

if (fHelp || params.size() != 2)
throw runtime_error(
"z_embedstring \"string-to-embed\" amount\n"
"\nEmbed a string into the blockchain (requires paying a fee).\n"
+ HelpRequiringPassphrase() +
"\nArguments:\n"
"1. \"string-to-embed\" (string, required) The string to embed into the blockchain.\n"
"2. \"amount\" (numeric, required) The amount in zcash to burn (not including fee). eg 0.0001\n"
"\nResult:\n"
"\"transactionid\" (string) The transaction id.\n"
"\nExamples:\n"
+ HelpExampleCli("z_embedstring", "\"Hello, world!")
);

LOCK2(cs_main, pwalletMain->cs_wallet);

// String to embed
std::string string_to_embed = params[0].get_str();
std::vector<unsigned char> bytes_to_embed(string_to_embed.begin(), string_to_embed.end());

// TODO: Are zero-valued TXOUTs disallowed by consensus, or can we safely
// remove the 'amount' from this RPC and always have zero-value TXOUT?
CAmount nAmount = AmountFromValue(params[1]);
//if (nAmount <= 0)
// throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
// Daira says they are supported, -- Duke

EnsureWalletIsUnlocked();

CWalletTx wtx;
CScript opreturn;
SendMoney(CScript() << OP_RETURN << bytes_to_embed, nAmount, false, wtx);

return wtx.GetHash().GetHex();
}
Expand Down Expand Up @@ -928,7 +970,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");

SendMoney(address.Get(), nAmount, false, wtx);
SendMoney(GetScriptForDestination(address.Get()), nAmount, false, wtx);

return wtx.GetHash().GetHex();
}
Expand Down