Merge pull request #1690 from gavinandresen/signrawtx_null
Allow signrawtransaction '...' null null 'hashtype'
This commit is contained in:
commit
4a4a0c1196
3 changed files with 28 additions and 22 deletions
|
@ -74,7 +74,8 @@ Object JSONRPCError(int code, const string& message)
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCTypeCheck(const Array& params,
|
void RPCTypeCheck(const Array& params,
|
||||||
const list<Value_type>& typesExpected)
|
const list<Value_type>& typesExpected,
|
||||||
|
bool fAllowNull)
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
BOOST_FOREACH(Value_type t, typesExpected)
|
BOOST_FOREACH(Value_type t, typesExpected)
|
||||||
|
@ -82,8 +83,8 @@ void RPCTypeCheck(const Array& params,
|
||||||
if (params.size() <= i)
|
if (params.size() <= i)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const Value& v = params[i];
|
const Value& v = params[i];
|
||||||
if (v.type() != t)
|
if (!((v.type() == t) || (fAllowNull && (v.type() == null_type))))
|
||||||
{
|
{
|
||||||
string err = strprintf("Expected type %s, got %s",
|
string err = strprintf("Expected type %s, got %s",
|
||||||
Value_type_name[t], Value_type_name[v.type()]);
|
Value_type_name[t], Value_type_name[v.type()]);
|
||||||
|
@ -94,14 +95,16 @@ void RPCTypeCheck(const Array& params,
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCTypeCheck(const Object& o,
|
void RPCTypeCheck(const Object& o,
|
||||||
const map<string, Value_type>& typesExpected)
|
const map<string, Value_type>& typesExpected,
|
||||||
|
bool fAllowNull)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected)
|
BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected)
|
||||||
{
|
{
|
||||||
const Value& v = find_value(o, t.first);
|
const Value& v = find_value(o, t.first);
|
||||||
if (v.type() == null_type)
|
if (!fAllowNull && v.type() == null_type)
|
||||||
throw JSONRPCError(-3, strprintf("Missing %s", t.first.c_str()));
|
throw JSONRPCError(-3, strprintf("Missing %s", t.first.c_str()));
|
||||||
if (v.type() != t.second)
|
|
||||||
|
if (!((v.type() == t.second) || (fAllowNull && (v.type() == null_type))))
|
||||||
{
|
{
|
||||||
string err = strprintf("Expected type %s for %s, got %s",
|
string err = strprintf("Expected type %s for %s, got %s",
|
||||||
Value_type_name[t.second], t.first.c_str(), Value_type_name[v.type()]);
|
Value_type_name[t.second], t.first.c_str(), Value_type_name[v.type()]);
|
||||||
|
@ -2694,8 +2697,10 @@ Object CallRPC(const string& strMethod, const Array& params)
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ConvertTo(Value& value)
|
void ConvertTo(Value& value, bool fAllowNull=false)
|
||||||
{
|
{
|
||||||
|
if (fAllowNull && value.type() == null_type)
|
||||||
|
return;
|
||||||
if (value.type() == str_type)
|
if (value.type() == str_type)
|
||||||
{
|
{
|
||||||
// reinterpret string as unquoted json value
|
// reinterpret string as unquoted json value
|
||||||
|
@ -2703,7 +2708,8 @@ void ConvertTo(Value& value)
|
||||||
string strJSON = value.get_str();
|
string strJSON = value.get_str();
|
||||||
if (!read_string(strJSON, value2))
|
if (!read_string(strJSON, value2))
|
||||||
throw runtime_error(string("Error parsing JSON:")+strJSON);
|
throw runtime_error(string("Error parsing JSON:")+strJSON);
|
||||||
value = value2.get_value<T>();
|
ConvertTo<T>(value2, fAllowNull);
|
||||||
|
value = value2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2754,8 +2760,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
|
||||||
if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||||
if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
|
if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
|
||||||
if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
|
if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
|
||||||
if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1]);
|
if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
|
||||||
if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2]);
|
if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true);
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,13 @@ json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vec
|
||||||
Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type));
|
Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type));
|
||||||
*/
|
*/
|
||||||
void RPCTypeCheck(const json_spirit::Array& params,
|
void RPCTypeCheck(const json_spirit::Array& params,
|
||||||
const std::list<json_spirit::Value_type>& typesExpected);
|
const std::list<json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
|
||||||
/*
|
/*
|
||||||
Check for expected keys/value types in an Object.
|
Check for expected keys/value types in an Object.
|
||||||
Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type));
|
Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type));
|
||||||
*/
|
*/
|
||||||
void RPCTypeCheck(const json_spirit::Object& o,
|
void RPCTypeCheck(const json_spirit::Object& o,
|
||||||
const std::map<std::string, json_spirit::Value_type>& typesExpected);
|
const std::map<std::string, json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
|
||||||
|
|
||||||
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
|
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
|
||||||
|
|
||||||
|
|
|
@ -280,21 +280,18 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n"
|
"signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n"
|
||||||
"Sign inputs for raw transaction (serialized, hex-encoded).\n"
|
"Sign inputs for raw transaction (serialized, hex-encoded).\n"
|
||||||
"Second optional argument is an array of previous transaction outputs that\n"
|
"Second optional argument (may be null) is an array of previous transaction outputs that\n"
|
||||||
"this transaction depends on but may not yet be in the blockchain.\n"
|
"this transaction depends on but may not yet be in the blockchain.\n"
|
||||||
"Third optional argument is an array of base58-encoded private\n"
|
"Third optional argument (may be null) is an array of base58-encoded private\n"
|
||||||
"keys that, if given, will be the only keys used to sign the transaction.\n"
|
"keys that, if given, will be the only keys used to sign the transaction.\n"
|
||||||
"Fourth option is a string that is one of six values; ALL, NONE, SINGLE or\n"
|
"Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
|
||||||
"ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
|
"ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
|
||||||
"Returns json object with keys:\n"
|
"Returns json object with keys:\n"
|
||||||
" hex : raw transaction with signature(s) (hex-encoded string)\n"
|
" hex : raw transaction with signature(s) (hex-encoded string)\n"
|
||||||
" complete : 1 if transaction has a complete set of signature (0 if not)"
|
" complete : 1 if transaction has a complete set of signature (0 if not)"
|
||||||
+ HelpRequiringPassphrase());
|
+ HelpRequiringPassphrase());
|
||||||
|
|
||||||
if (params.size() < 3)
|
RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
|
||||||
EnsureWalletIsUnlocked();
|
|
||||||
|
|
||||||
RPCTypeCheck(params, list_of(str_type)(array_type)(array_type));
|
|
||||||
|
|
||||||
vector<unsigned char> txData(ParseHex(params[0].get_str()));
|
vector<unsigned char> txData(ParseHex(params[0].get_str()));
|
||||||
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
@ -343,7 +340,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add previous txouts given in the RPC call:
|
// Add previous txouts given in the RPC call:
|
||||||
if (params.size() > 1)
|
if (params.size() > 1 && params[1].type() != null_type)
|
||||||
{
|
{
|
||||||
Array prevTxs = params[1].get_array();
|
Array prevTxs = params[1].get_array();
|
||||||
BOOST_FOREACH(Value& p, prevTxs)
|
BOOST_FOREACH(Value& p, prevTxs)
|
||||||
|
@ -390,7 +387,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
||||||
|
|
||||||
bool fGivenKeys = false;
|
bool fGivenKeys = false;
|
||||||
CBasicKeyStore tempKeystore;
|
CBasicKeyStore tempKeystore;
|
||||||
if (params.size() > 2)
|
if (params.size() > 2 && params[2].type() != null_type)
|
||||||
{
|
{
|
||||||
fGivenKeys = true;
|
fGivenKeys = true;
|
||||||
Array keys = params[2].get_array();
|
Array keys = params[2].get_array();
|
||||||
|
@ -407,10 +404,13 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
||||||
tempKeystore.AddKey(key);
|
tempKeystore.AddKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
EnsureWalletIsUnlocked();
|
||||||
|
|
||||||
const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
|
const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
|
||||||
|
|
||||||
int nHashType = SIGHASH_ALL;
|
int nHashType = SIGHASH_ALL;
|
||||||
if (params.size() > 3)
|
if (params.size() > 3 && params[3].type() != null_type)
|
||||||
{
|
{
|
||||||
static map<string, int> mapSigHashValues =
|
static map<string, int> mapSigHashValues =
|
||||||
boost::assign::map_list_of
|
boost::assign::map_list_of
|
||||||
|
|
Loading…
Reference in a new issue