mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Fix RIPD-166:
* Allow RPC commands sign and submit to sign using the regular key. * Allow command line RPC command submit to take an "offline" flag. * Mark SerializedObject.getFlags() as const.
This commit is contained in:
@@ -558,7 +558,7 @@ bool STObject::clearFlag (std::uint32_t f)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool STObject::isFlag (std::uint32_t f)
|
||||
bool STObject::isFlag (std::uint32_t f) const
|
||||
{
|
||||
return (getFlags () & f) == f;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
|
||||
bool setFlag (std::uint32_t);
|
||||
bool clearFlag (std::uint32_t);
|
||||
bool isFlag(std::uint32_t);
|
||||
bool isFlag(std::uint32_t) const;
|
||||
std::uint32_t getFlags () const;
|
||||
|
||||
uint256 getHash (std::uint32_t prefix) const;
|
||||
|
||||
@@ -82,7 +82,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
return RPC::make_param_error (std::string ("Invalid currency/issuer '") +
|
||||
return RPC::make_param_error (std::string ("Invalid currency/issuer '") +
|
||||
strCurrencyIssuer + "'");
|
||||
}
|
||||
}
|
||||
@@ -829,7 +829,7 @@ public:
|
||||
{ "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 },
|
||||
{ "sign", &RPCParser::parseSignSubmit, 2, 3 },
|
||||
{ "sms", &RPCParser::parseSMS, 1, 1 },
|
||||
{ "submit", &RPCParser::parseSignSubmit, 1, 2 },
|
||||
{ "submit", &RPCParser::parseSignSubmit, 1, 3 },
|
||||
{ "server_info", &RPCParser::parseAsIs, 0, 0 },
|
||||
{ "server_state", &RPCParser::parseAsIs, 0, 0 },
|
||||
{ "stop", &RPCParser::parseAsIs, 0, 0 },
|
||||
|
||||
@@ -58,6 +58,7 @@ enum error_code_i
|
||||
rpcACT_NOT_FOUND,
|
||||
rpcINSUF_FUNDS,
|
||||
rpcLGR_NOT_FOUND,
|
||||
rpcMASTER_DISABLED,
|
||||
rpcNICKNAME_MISSING,
|
||||
rpcNO_ACCOUNT,
|
||||
rpcNO_PATH,
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
add (rpcACT_MALFORMED, "actMalformed", "Account malformed.");
|
||||
add (rpcACT_NOT_FOUND, "actNotFound", "Account not found.");
|
||||
add (rpcBAD_BLOB, "badBlob", "Blob must be a non-empty hex string.");
|
||||
add (rpcHIGH_FEE, "highFee", "Current transaction fee exceeds your limit.");
|
||||
add (rpcBAD_FEATURE, "badFeature", "Feature unknown or invalid.");
|
||||
add (rpcBAD_ISSUER, "badIssuer", "Issuer account malformed.");
|
||||
add (rpcBAD_MARKET, "badMarket", "No such market.");
|
||||
@@ -64,10 +63,11 @@ public:
|
||||
add (rpcDST_ACT_MISSING, "dstActMissing", "Destination account does not exist.");
|
||||
add (rpcDST_AMT_MALFORMED, "dstAmtMalformed", "Destination amount/currency/issuer is malformed.");
|
||||
add (rpcDST_ISR_MALFORMED, "dstIsrMalformed", "Destination issuer is malformed.");
|
||||
add (rpcFORBIDDEN, "forbidden", "Bad credentials.");
|
||||
add (rpcFAIL_GEN_DECRYPT, "failGenDecrypt", "Failed to decrypt generator.");
|
||||
add (rpcFORBIDDEN, "forbidden", "Bad credentials.");
|
||||
add (rpcGETS_ACT_MALFORMED, "getsActMalformed", "Gets account malformed.");
|
||||
add (rpcGETS_AMT_MALFORMED, "getsAmtMalformed", "Gets amount malformed.");
|
||||
add (rpcHIGH_FEE, "highFee", "Current transaction fee exceeds your limit.");
|
||||
add (rpcHOST_IP_MALFORMED, "hostIpMalformed", "Host IP is malformed.");
|
||||
add (rpcINSUF_FUNDS, "insufFunds", "Insufficient funds.");
|
||||
add (rpcINTERNAL, "internal", "Internal error.");
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
add (rpcLGR_IDXS_INVALID, "lgrIdxsInvalid", "Ledger indexes invalid.");
|
||||
add (rpcLGR_IDX_MALFORMED, "lgrIdxMalformed", "Ledger index malformed.");
|
||||
add (rpcLGR_NOT_FOUND, "lgrNotFound", "Ledger not found.");
|
||||
add (rpcMASTER_DISABLED, "masterDisabled", "Master key is disabled.");
|
||||
add (rpcNICKNAME_MALFORMED, "nicknameMalformed", "Nickname is malformed.");
|
||||
add (rpcNICKNAME_MISSING, "nicknameMissing", "Nickname does not exist.");
|
||||
add (rpcNICKNAME_PERM, "nicknamePerm", "Account does not control nickname.");
|
||||
@@ -85,7 +86,7 @@ public:
|
||||
add (rpcNO_CURRENT, "noCurrent", "Current ledger is unavailable.");
|
||||
add (rpcNO_EVENTS, "noEvents", "Current transport does not support events.");
|
||||
add (rpcNO_GEN_DECRYPT, "noGenDecrypt", "Password failed to decrypt master public generator.");
|
||||
add (rpcNO_NETWORK, "noNetwork", "Network not available.");
|
||||
add (rpcNO_NETWORK, "noNetwork", "Not synced to Ripple network.");
|
||||
add (rpcNO_PATH, "noPath", "Unable to find a ripple path.");
|
||||
add (rpcNO_PERMISSION, "noPermission", "You don't have permission for this command.");
|
||||
add (rpcNO_PF_REQUEST, "noPathRequest", "No pathfinding request in progress.");
|
||||
|
||||
@@ -189,14 +189,14 @@ Json::Value transactionSign (
|
||||
return RPC::make_error (rpcSRC_ACT_MALFORMED,
|
||||
RPC::invalid_field_message ("tx_json.Account"));
|
||||
|
||||
bool const bOffline (
|
||||
bool const verify = !(
|
||||
params.isMember ("offline") && params["offline"].asBool ());
|
||||
|
||||
if (! tx_json.isMember ("Sequence") && bOffline)
|
||||
if (!tx_json.isMember ("Sequence") && !verify)
|
||||
return RPC::missing_field_error ("tx_json.Sequence");
|
||||
|
||||
// Check for current ledger
|
||||
if (!bOffline && !getConfig ().RUN_STANDALONE &&
|
||||
if (verify && !getConfig ().RUN_STANDALONE &&
|
||||
(getApp().getLedgerMaster().getValidatedLedgerAge() > 120))
|
||||
return rpcError (rpcNO_CURRENT);
|
||||
|
||||
@@ -205,11 +205,11 @@ Json::Value transactionSign (
|
||||
return rpcError(rpcTOO_BUSY);
|
||||
|
||||
Ledger::pointer lSnapshot = netOps.getCurrentLedger ();
|
||||
AccountState::pointer asSrc = bOffline
|
||||
AccountState::pointer asSrc = !verify
|
||||
? AccountState::pointer () // Don't look up address if offline.
|
||||
: netOps.getAccountState (lSnapshot, raSrcAddressID);
|
||||
|
||||
if (!bOffline && !asSrc)
|
||||
if (verify && !asSrc)
|
||||
{
|
||||
// If not offline and did not find account, error.
|
||||
WriteLog (lsDEBUG, RPCHandler) << boost::str (boost::format ("transactionSign: Failed to find source account in current ledger: %s")
|
||||
@@ -311,9 +311,10 @@ Json::Value transactionSign (
|
||||
|
||||
if (!tx_json.isMember ("Sequence"))
|
||||
{
|
||||
if (bOffline)
|
||||
if (!verify)
|
||||
{
|
||||
// If offline, Sequence is mandatory.
|
||||
// TODO: duplicates logic above.
|
||||
return rpcError (rpcINVALID_PARAMS);
|
||||
}
|
||||
else
|
||||
@@ -324,7 +325,7 @@ Json::Value transactionSign (
|
||||
|
||||
if (!tx_json.isMember ("Flags")) tx_json["Flags"] = tfFullyCanonicalSig;
|
||||
|
||||
if (!bOffline)
|
||||
if (verify)
|
||||
{
|
||||
SLE::pointer sleAccountRoot = netOps.getSLEi (lSnapshot,
|
||||
Ledger::getAccountRootIndex (raSrcAddressID.getAccountID ()));
|
||||
@@ -344,41 +345,35 @@ Json::Value transactionSign (
|
||||
RippleAddress naMasterGenerator = RippleAddress::createGeneratorPublic (
|
||||
naSecret);
|
||||
|
||||
// Find the index of Account from the master generator, so we can generate
|
||||
// the public and private keys.
|
||||
RippleAddress naMasterAccountPublic;
|
||||
unsigned int iIndex = 0;
|
||||
bool bFound = false;
|
||||
|
||||
// Don't look at ledger entries to determine if the account exists.
|
||||
// Don't want to leak to thin server that these accounts are related.
|
||||
while (!bFound && iIndex != getConfig ().ACCOUNT_PROBE_MAX)
|
||||
if (verify)
|
||||
{
|
||||
naMasterAccountPublic.setAccountPublic (naMasterGenerator, iIndex);
|
||||
auto masterAccountPublic = RippleAddress::createAccountPublic (
|
||||
naMasterGenerator, 0);
|
||||
auto account = masterAccountPublic.getAccountID();
|
||||
auto const& sle = asSrc->peekSLE();
|
||||
|
||||
WriteLog (lsWARNING, RPCHandler) <<
|
||||
"authorize: " << iIndex <<
|
||||
" : " << naMasterAccountPublic.humanAccountID () <<
|
||||
" : " << raSrcAddressID.humanAccountID ();
|
||||
|
||||
bFound = raSrcAddressID.getAccountID () == naMasterAccountPublic.getAccountID ();
|
||||
|
||||
if (!bFound)
|
||||
++iIndex;
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
return rpcError (rpcBAD_SECRET);
|
||||
"verify: " << masterAccountPublic.humanAccountID () <<
|
||||
" : " << raSrcAddressID.humanAccountID ();
|
||||
if (raSrcAddressID.getAccountID () == account)
|
||||
{
|
||||
if (sle.isFlag(lsfDisableMaster))
|
||||
return rpcError (rpcMASTER_DISABLED);
|
||||
}
|
||||
else if (!sle.isFieldPresent(sfRegularKey) ||
|
||||
account != sle.getFieldAccount160 (sfRegularKey))
|
||||
{
|
||||
return rpcError (rpcBAD_SECRET);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the generator to determine the associated public and private keys.
|
||||
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (
|
||||
naSecret);
|
||||
RippleAddress naAccountPublic = RippleAddress::createAccountPublic (
|
||||
naGenerator, iIndex);
|
||||
naGenerator, 0);
|
||||
RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate (
|
||||
naGenerator, naSecret, iIndex);
|
||||
naGenerator, naSecret, 0);
|
||||
|
||||
if (bHaveAuthKey
|
||||
// The generated pair must match authorized...
|
||||
@@ -386,6 +381,7 @@ Json::Value transactionSign (
|
||||
// ... or the master key must have been used.
|
||||
&& raSrcAddressID.getAccountID () != naAccountPublic.getAccountID ())
|
||||
{
|
||||
// TODO: we can't ever get here!
|
||||
// Log::out() << "iIndex: " << iIndex;
|
||||
// Log::out() << "sfAuthorizedKey: " << strHex(asSrc->getAuthorizedKey().getAccountID());
|
||||
// Log::out() << "naAccountPublic: " << strHex(naAccountPublic.getAccountID());
|
||||
|
||||
Reference in New Issue
Block a user