Skip to content

Commit

Permalink
P2SH related RPC improvements
Browse files Browse the repository at this point in the history
* New addredeemscript and decodescript RPC calls
* validateaddress now provides redeem script
  • Loading branch information
alex authored and alex committed Aug 18, 2013
1 parent 7aed911 commit fc462f5
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 3 deletions.
38 changes: 38 additions & 0 deletions src/bitcoinrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,42 @@ std::string HexBits(unsigned int nBits)
}


//
// Utilities: convert hex-encoded Values
// (throws error if not hex).
//
uint256 ParseHashV(const Value& v, string strName)
{
string strHex;
if (v.type() == str_type)
strHex = v.get_str();
if (!IsHex(strHex)) // Note: IsHex("") is false
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
uint256 result;
result.SetHex(strHex);
return result;
}

uint256 ParseHashO(const Object& o, string strKey)
{
return ParseHashV(find_value(o, strKey), strKey);
}

vector<unsigned char> ParseHexV(const Value& v, string strName)
{
string strHex;
if (v.type() == str_type)
strHex = v.get_str();
if (!IsHex(strHex))
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
return ParseHex(strHex);
}

vector<unsigned char> ParseHexO(const Object& o, string strKey)
{
return ParseHexV(find_value(o, strKey), strKey);
}


///
/// Note: This interface may still be subject to change.
Expand Down Expand Up @@ -234,6 +270,7 @@ static const CRPCCommand vRPCCommands[] =
{ "sendfrom", &sendfrom, false, false },
{ "sendmany", &sendmany, false, false },
{ "addmultisigaddress", &addmultisigaddress, false, false },
{ "addredeemscript", &addredeemscript, false, false },
{ "getrawmempool", &getrawmempool, true, false },
{ "getblock", &getblock, false, false },
{ "getblockbynumber", &getblockbynumber, false, false },
Expand All @@ -258,6 +295,7 @@ static const CRPCCommand vRPCCommands[] =
{ "getrawtransaction", &getrawtransaction, false, false },
{ "createrawtransaction", &createrawtransaction, false, false },
{ "decoderawtransaction", &decoderawtransaction, false, false },
{ "decodescript", &decodescript, false, false },
{ "signrawtransaction", &signrawtransaction, false, false },
{ "sendrawtransaction", &sendrawtransaction, false, false },
{ "getcheckpoint", &getcheckpoint, true, false },
Expand Down
11 changes: 11 additions & 0 deletions src/bitcoinrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ extern std::string HexBits(unsigned int nBits);
extern std::string HelpRequiringPassphrase();
extern void EnsureWalletIsUnlocked();

//
// Utilities: convert hex-encoded Values
// (throws error if not hex).
//
extern uint256 ParseHashV(const json_spirit::Value& v, std::string strName);
extern uint256 ParseHashO(const json_spirit::Object& o, std::string strKey);
extern std::vector<unsigned char> ParseHexV(const json_spirit::Value& v, std::string strName);
extern std::vector<unsigned char> ParseHexO(const json_spirit::Object& o, std::string strKey);

extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp
extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp);
Expand Down Expand Up @@ -161,6 +170,7 @@ extern json_spirit::Value movecmd(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value sendfrom(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value sendmany(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value addmultisigaddress(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value addredeemscript(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listreceivedbyaddress(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listreceivedbyaccount(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listtransactions(const json_spirit::Array& params, bool fHelp);
Expand Down Expand Up @@ -188,6 +198,7 @@ extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bo
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value decodescript(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp);

Expand Down
31 changes: 28 additions & 3 deletions src/rpcrawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ using namespace boost;
using namespace boost::assign;
using namespace json_spirit;

void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
{
txnouttype type;
vector<CTxDestination> addresses;
int nRequired;

out.push_back(Pair("asm", scriptPubKey.ToString()));
out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));

if (fIncludeHex)
out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));

if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
{
Expand Down Expand Up @@ -75,7 +77,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
out.push_back(Pair("n", (boost::int64_t)i));
Object o;
ScriptPubKeyToJSON(txout.scriptPubKey, o);
ScriptPubKeyToJSON(txout.scriptPubKey, o, false);
out.push_back(Pair("scriptPubKey", o));
vout.push_back(out);
}
Expand Down Expand Up @@ -300,6 +302,29 @@ Value decoderawtransaction(const Array& params, bool fHelp)
return result;
}

Value decodescript(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"decodescript <hex string>\n"
"Decode a hex-encoded script.");

RPCTypeCheck(params, list_of(str_type));

Object r;
CScript script;
if (params[0].get_str().size() > 0){
vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
script = CScript(scriptData.begin(), scriptData.end());
} else {
// Empty scripts are valid
}
ScriptPubKeyToJSON(script, r, false);

r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
return r;
}

Value signrawtransaction(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 4)
Expand Down
24 changes: 24 additions & 0 deletions src/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,29 @@ Value addmultisigaddress(const Array& params, bool fHelp)
return CBitcoinAddress(innerID).ToString();
}

Value addredeemscript(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
{
string msg = "addredeemscript <redeemScript> [account]\n"
"Add a P2SH address with a specified redeemScript to the wallet.\n"
"If [account] is specified, assign address to [account].";
throw runtime_error(msg);
}

string strAccount;
if (params.size() > 1)
strAccount = AccountFromValue(params[1]);

// Construct using pay-to-script-hash:
vector<unsigned char> innerData = ParseHexV(params[0], "redeemScript");
CScript inner(innerData.begin(), innerData.end());
CScriptID innerID = inner.GetID();
pwalletMain->AddCScript(inner);

pwalletMain->SetAddressBookName(innerID, strAccount);
return CBitcoinAddress(innerID).ToString();
}

struct tallyitem
{
Expand Down Expand Up @@ -1541,6 +1564,7 @@ class DescribeAddressVisitor : public boost::static_visitor<Object>
int nRequired;
ExtractDestinations(subscript, whichType, addresses, nRequired);
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
Array a;
BOOST_FOREACH(const CTxDestination& addr, addresses)
a.push_back(CBitcoinAddress(addr).ToString());
Expand Down

0 comments on commit fc462f5

Please sign in to comment.