sign_for RPC command (RIPD-182):

The sign_for RPC command returns a field suitable for
signing a multi-signed transaction.  Actual multi-signed
transactions are in the next commit.
This commit is contained in:
Scott Schurr
2015-02-06 15:55:37 -08:00
committed by Vinnie Falco
parent 64ebd64d2b
commit cf1638e6de
24 changed files with 1537 additions and 437 deletions

View File

@@ -3208,6 +3208,9 @@
<ClCompile Include="..\..\src\ripple\rpc\handlers\Sign.cpp"> <ClCompile Include="..\..\src\ripple\rpc\handlers\Sign.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\handlers\SignFor.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\handlers\Stop.cpp"> <ClCompile Include="..\..\src\ripple\rpc\handlers\Stop.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>

View File

@@ -3738,6 +3738,9 @@
<ClCompile Include="..\..\src\ripple\rpc\handlers\Sign.cpp"> <ClCompile Include="..\..\src\ripple\rpc\handlers\Sign.cpp">
<Filter>ripple\rpc\handlers</Filter> <Filter>ripple\rpc\handlers</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\handlers\SignFor.cpp">
<Filter>ripple\rpc\handlers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\handlers\Stop.cpp"> <ClCompile Include="..\..\src\ripple\rpc\handlers\Stop.cpp">
<Filter>ripple\rpc\handlers</Filter> <Filter>ripple\rpc\handlers</Filter>
</ClCompile> </ClCompile>

View File

@@ -138,6 +138,9 @@ void printHelp (const po::options_description& desc)
" version\n" " version\n"
" server_info\n" " server_info\n"
" sign\n" " sign\n"
#if RIPPLE_ENABLE_MULTI_SIGN
" sign_for\n"
#endif // RIPPLE_ENABLE_MULTI_SIGN
" stop\n" " stop\n"
" submit\n" " submit\n"
" tx <id>\n" " tx <id>\n"

View File

@@ -211,19 +211,16 @@ public:
Job&, STTx::pointer, Job&, STTx::pointer,
stCallback callback = stCallback ()) override; stCallback callback = stCallback ()) override;
Transaction::pointer submitTransactionSync (
Transaction::ref tpTrans,
bool bAdmin, bool bLocal, bool bFailHard, bool bSubmit) override;
Transaction::pointer processTransactionCb ( Transaction::pointer processTransactionCb (
Transaction::pointer, Transaction::pointer,
bool bAdmin, bool bLocal, bool bFailHard, stCallback) override; bool bAdmin, bool bLocal, FailHard failType, stCallback) override;
Transaction::pointer processTransaction ( Transaction::pointer processTransaction (
Transaction::pointer transaction, Transaction::pointer transaction,
bool bAdmin, bool bLocal, bool bFailHard) override bool bAdmin, bool bLocal, FailHard failType) override
{ {
return processTransactionCb ( return processTransactionCb (
transaction, bAdmin, bLocal, bFailHard, stCallback ()); transaction, bAdmin, bLocal, failType, stCallback ());
} }
// VFALCO Workaround for MSVC std::function which doesn't swallow return // VFALCO Workaround for MSVC std::function which doesn't swallow return
@@ -232,9 +229,9 @@ public:
private: private:
void processTransactionCbVoid ( void processTransactionCbVoid (
Transaction::pointer p, Transaction::pointer p,
bool bAdmin, bool bLocal, bool bFailHard, stCallback cb) bool bAdmin, bool bLocal, FailHard failType, stCallback cb)
{ {
processTransactionCb (p, bAdmin, bLocal, bFailHard, cb); processTransactionCb (p, bAdmin, bLocal, failType, cb);
} }
public: public:
@@ -943,51 +940,13 @@ void NetworkOPsImp::submitTransaction (
std::make_shared<Transaction> (trans, Validate::NO, reason), std::make_shared<Transaction> (trans, Validate::NO, reason),
false, false,
false, false,
false, FailHard::no,
callback)); callback));
} }
// Sterilize transaction through serialization.
// This is fully synchronous and deprecated
Transaction::pointer NetworkOPsImp::submitTransactionSync (
Transaction::ref tpTrans,
bool bAdmin, bool bLocal, bool bFailHard, bool bSubmit)
{
Serializer s;
tpTrans->getSTransaction ()->add (s);
auto tpTransNew = Transaction::sharedTransaction (
s.getData (), Validate::YES);
if (!tpTransNew)
{
// Could not construct transaction.
return tpTransNew;
}
if (tpTransNew->getSTransaction ()->isEquivalent (
*tpTrans->getSTransaction ()))
{
if (bSubmit)
processTransaction (tpTransNew, bAdmin, bLocal, bFailHard);
}
else
{
m_journal.fatal << "Transaction reconstruction failure";
m_journal.fatal << tpTransNew->getSTransaction ()->getJson (0);
m_journal.fatal << tpTrans->getSTransaction ()->getJson (0);
// assert (false); "1e-95" as amount can trigger this
tpTransNew.reset ();
}
return tpTransNew;
}
Transaction::pointer NetworkOPsImp::processTransactionCb ( Transaction::pointer NetworkOPsImp::processTransactionCb (
Transaction::pointer trans, Transaction::pointer trans,
bool bAdmin, bool bLocal, bool bFailHard, stCallback callback) bool bAdmin, bool bLocal, FailHard failType, stCallback callback)
{ {
auto ev = m_job_queue.getLoadEventAP (jtTXN_PROC, "ProcessTXN"); auto ev = m_job_queue.getLoadEventAP (jtTXN_PROC, "ProcessTXN");
int newFlags = getApp().getHashRouter ().getFlags (trans->getID ()); int newFlags = getApp().getHashRouter ().getFlags (trans->getID ());
@@ -1065,7 +1024,7 @@ Transaction::pointer NetworkOPsImp::processTransactionCb (
} }
else if (isTerRetry (r)) else if (isTerRetry (r))
{ {
if (bFailHard) if (failType == FailHard::yes)
addLocal = false; addLocal = false;
else else
{ {
@@ -1088,7 +1047,8 @@ Transaction::pointer NetworkOPsImp::processTransactionCb (
trans->getSTransaction ()); trans->getSTransaction ());
} }
if (didApply || ((mMode != omFULL) && !bFailHard && bLocal)) if (didApply ||
((mMode != omFULL) && (failType != FailHard::yes) && bLocal))
{ {
std::set<Peer::id_t> peers; std::set<Peer::id_t> peers;

View File

@@ -91,6 +91,16 @@ public:
omFULL = 4 // we have the ledger and can even validate omFULL = 4 // we have the ledger and can even validate
}; };
enum class FailHard : unsigned char
{
no,
yes
};
static inline FailHard doFailHard (bool noMeansDont)
{
return noMeansDont ? FailHard::yes : FailHard::no;
}
// VFALCO TODO Fix OrderBookDB to not need this unrelated type. // VFALCO TODO Fix OrderBookDB to not need this unrelated type.
// //
typedef hash_map <std::uint64_t, InfoSub::wptr> SubMapType; typedef hash_map <std::uint64_t, InfoSub::wptr> SubMapType;
@@ -149,12 +159,10 @@ public:
typedef std::function<void (Transaction::pointer, TER)> stCallback; typedef std::function<void (Transaction::pointer, TER)> stCallback;
virtual void submitTransaction (Job&, STTx::pointer, virtual void submitTransaction (Job&, STTx::pointer,
stCallback callback = stCallback ()) = 0; stCallback callback = stCallback ()) = 0;
virtual Transaction::pointer submitTransactionSync (Transaction::ref tpTrans,
bool bAdmin, bool bLocal, bool bFailHard, bool bSubmit) = 0;
virtual Transaction::pointer processTransactionCb (Transaction::pointer, virtual Transaction::pointer processTransactionCb (Transaction::pointer,
bool bAdmin, bool bLocal, bool bFailHard, stCallback) = 0; bool bAdmin, bool bLocal, FailHard failType, stCallback) = 0;
virtual Transaction::pointer processTransaction (Transaction::pointer transaction, virtual Transaction::pointer processTransaction (Transaction::pointer transaction,
bool bAdmin, bool bLocal, bool bFailHard) = 0; bool bAdmin, bool bLocal, FailHard failType) = 0;
virtual Transaction::pointer findTransactionByID (uint256 const& transactionID) = 0; virtual Transaction::pointer findTransactionByID (uint256 const& transactionID) = 0;
virtual int findTransactionsByDestination (std::list<Transaction::pointer>&, virtual int findTransactionsByDestination (std::list<Transaction::pointer>&,
RippleAddress const& destinationAccount, std::uint32_t startLedgerSeq, RippleAddress const& destinationAccount, std::uint32_t startLedgerSeq,

View File

@@ -420,6 +420,30 @@ private:
return jvRequest; return jvRequest;
} }
// sign_for
Json::Value parseSignFor (Json::Value const& jvParams)
{
Json::Value txJSON;
Json::Reader reader;
if ((4 == jvParams.size ())
&& reader.parse (jvParams[3u].asString (), txJSON))
{
if (txJSON.type () == Json::objectValue)
{
// Return SigningFor object for the submitted transaction.
Json::Value jvRequest;
jvRequest["signing_for"] = jvParams[0u].asString ();
jvRequest["account"] = jvParams[1u].asString ();
jvRequest["secret"] = jvParams[2u].asString ();
jvRequest["tx_json"] = txJSON;
return jvRequest;
}
}
return rpcError (rpcINVALID_PARAMS);
}
// json <command> <json> // json <command> <json>
Json::Value parseJson (Json::Value const& jvParams) Json::Value parseJson (Json::Value const& jvParams)
{ {
@@ -605,7 +629,7 @@ private:
{ {
Json::Value txJSON; Json::Value txJSON;
Json::Reader reader; Json::Reader reader;
bool bOffline = 3 == jvParams.size () && jvParams[2u].asString () == "offline"; bool const bOffline = 3 == jvParams.size () && jvParams[2u].asString () == "offline";
if (1 == jvParams.size ()) if (1 == jvParams.size ())
{ {
@@ -831,6 +855,9 @@ public:
{ "random", &RPCParser::parseAsIs, 0, 0 }, { "random", &RPCParser::parseAsIs, 0, 0 },
{ "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 }, { "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 },
{ "sign", &RPCParser::parseSignSubmit, 2, 3 }, { "sign", &RPCParser::parseSignSubmit, 2, 3 },
#if RIPPLE_ENABLE_MULTI_SIGN
{ "sign_for", &RPCParser::parseSignFor, 4, 4 },
#endif // RIPPLE_ENABLE_MULTI_SIGN
{ "submit", &RPCParser::parseSignSubmit, 1, 3 }, { "submit", &RPCParser::parseSignSubmit, 1, 3 },
{ "server_info", &RPCParser::parseAsIs, 0, 0 }, { "server_info", &RPCParser::parseAsIs, 0, 0 },
{ "server_state", &RPCParser::parseAsIs, 0, 0 }, { "server_state", &RPCParser::parseAsIs, 0, 0 },

View File

@@ -1652,7 +1652,8 @@ PeerImp::checkTransaction (Job&, int flags,
} }
bool const trusted (flags & SF_TRUSTED); bool const trusted (flags & SF_TRUSTED);
getApp().getOPs ().processTransaction (tx, trusted, false, false); getApp().getOPs ().processTransaction (
tx, trusted, false, NetworkOPs::FailHard::no);
} }
catch (...) catch (...)
{ {

View File

@@ -100,6 +100,7 @@ enum error_code_i
rpcPAYS_AMT_MALFORMED, rpcPAYS_AMT_MALFORMED,
rpcPORT_MALFORMED, rpcPORT_MALFORMED,
rpcPUBLIC_MALFORMED, rpcPUBLIC_MALFORMED,
rpcSIGN_FOR_MALFORMED,
rpcSRC_ACT_MALFORMED, rpcSRC_ACT_MALFORMED,
rpcSRC_ACT_MISSING, rpcSRC_ACT_MISSING,
rpcSRC_ACT_NOT_FOUND, rpcSRC_ACT_NOT_FOUND,

View File

@@ -84,6 +84,9 @@ public:
/** inner transaction to sign */ /** inner transaction to sign */
static HashPrefix const txSign; static HashPrefix const txSign;
/** inner transaction to multi-sign */
static HashPrefix const txMultiSign;
/** validation for signing */ /** validation for signing */
static HashPrefix const validation; static HashPrefix const validation;

View File

@@ -387,7 +387,7 @@ extern SField const sfMinimumOffer;
extern SField const sfRippleEscrow; extern SField const sfRippleEscrow;
extern SField const sfDeliveredAmount; extern SField const sfDeliveredAmount;
// variable length // variable length (common)
extern TypedField<STBlob> const sfPublicKey; extern TypedField<STBlob> const sfPublicKey;
extern SField const sfMessageKey; extern SField const sfMessageKey;
extern TypedField<STBlob> const sfSigningPubKey; extern TypedField<STBlob> const sfSigningPubKey;
@@ -402,6 +402,9 @@ extern SField const sfMemoType;
extern SField const sfMemoData; extern SField const sfMemoData;
extern SField const sfMemoFormat; extern SField const sfMemoFormat;
// variable length (uncommon)
extern SField const sfMultiSignature;
// account // account
extern SField const sfAccount; extern SField const sfAccount;
extern SField const sfOwner; extern SField const sfOwner;
@@ -430,11 +433,13 @@ extern SField const sfNewFields;
extern SField const sfTemplateEntry; extern SField const sfTemplateEntry;
extern SField const sfMemo; extern SField const sfMemo;
extern SField const sfSignerEntry; extern SField const sfSignerEntry;
extern SField const sfSigningAccount;
extern SField const sfSigningFor;
// array of objects // array of objects
// ARRAY/1 is reserved for end of array // ARRAY/1 is reserved for end of array
extern SField const sfSigningAccounts; extern SField const sfSigningAccounts;
extern SField const sfTxnSignatures; extern SField const sfMultiSigners;
extern SField const sfSignerEntries; extern SField const sfSignerEntries;
extern SField const sfTemplate; extern SField const sfTemplate;
extern SField const sfNecessary; extern SField const sfNecessary;

View File

@@ -212,6 +212,17 @@ public:
uint256 getHash (std::uint32_t prefix) const; uint256 getHash (std::uint32_t prefix) const;
uint256 getSigningHash (std::uint32_t prefix) const; uint256 getSigningHash (std::uint32_t prefix) const;
// Break the multi-signing hash computation into 2 parts for optimization.
Serializer startMultiSigningData () const;
void finishMultiSigningData (
RippleAddress const& signingForID,
RippleAddress const& signingID, Serializer& s) const;
// Get data to compute a complete multi-signature.
Serializer getMultiSigningData (
RippleAddress const& signingForID,
RippleAddress const& signingID) const;
const STBase& peekAtIndex (int offset) const const STBase& peekAtIndex (int offset) const
{ {
return v_[offset].get(); return v_[offset].get();

View File

@@ -98,6 +98,7 @@ public:
add (rpcPORT_MALFORMED, "portMalformed", "Port is malformed."); add (rpcPORT_MALFORMED, "portMalformed", "Port is malformed.");
add (rpcPUBLIC_MALFORMED, "publicMalformed", "Public key is malformed."); add (rpcPUBLIC_MALFORMED, "publicMalformed", "Public key is malformed.");
add (rpcQUALITY_MALFORMED, "qualityMalformed", "Quality malformed."); add (rpcQUALITY_MALFORMED, "qualityMalformed", "Quality malformed.");
add (rpcSIGN_FOR_MALFORMED, "signForMalformed", "Signing for account is malformed.");
add (rpcSLOW_DOWN, "slowDown", "You are placing too much load on the server."); add (rpcSLOW_DOWN, "slowDown", "You are placing too much load on the server.");
add (rpcSRC_ACT_MALFORMED, "srcActMalformed", "Source account is malformed."); add (rpcSRC_ACT_MALFORMED, "srcActMalformed", "Source account is malformed.");
add (rpcSRC_ACT_MISSING, "srcActMissing", "Source account not provided."); add (rpcSRC_ACT_MISSING, "srcActMissing", "Source account not provided.");

View File

@@ -31,6 +31,7 @@ HashPrefix const HashPrefix::leafNode ('M', 'L', 'N');
HashPrefix const HashPrefix::innerNode ('M', 'I', 'N'); HashPrefix const HashPrefix::innerNode ('M', 'I', 'N');
HashPrefix const HashPrefix::ledgerMaster ('L', 'W', 'R'); HashPrefix const HashPrefix::ledgerMaster ('L', 'W', 'R');
HashPrefix const HashPrefix::txSign ('S', 'T', 'X'); HashPrefix const HashPrefix::txSign ('S', 'T', 'X');
HashPrefix const HashPrefix::txMultiSign ('S', 'M', 'T');
HashPrefix const HashPrefix::validation ('V', 'A', 'L'); HashPrefix const HashPrefix::validation ('V', 'A', 'L');
HashPrefix const HashPrefix::proposal ('P', 'R', 'P'); HashPrefix const HashPrefix::proposal ('P', 'R', 'P');

View File

@@ -175,7 +175,7 @@ SField const sfMinimumOffer = make::one(&sfMinimumOffer, STI_AMOUNT, 16, "
SField const sfRippleEscrow = make::one(&sfRippleEscrow, STI_AMOUNT, 17, "RippleEscrow"); SField const sfRippleEscrow = make::one(&sfRippleEscrow, STI_AMOUNT, 17, "RippleEscrow");
SField const sfDeliveredAmount = make::one(&sfDeliveredAmount, STI_AMOUNT, 18, "DeliveredAmount"); SField const sfDeliveredAmount = make::one(&sfDeliveredAmount, STI_AMOUNT, 18, "DeliveredAmount");
// variable length // variable length (common)
TypedField<STBlob> const sfPublicKey = make::one<STBlob>(&sfPublicKey, STI_VL, 1, "PublicKey"); TypedField<STBlob> const sfPublicKey = make::one<STBlob>(&sfPublicKey, STI_VL, 1, "PublicKey");
TypedField<STBlob> const sfSigningPubKey = make::one<STBlob>(&sfSigningPubKey, STI_VL, 3, "SigningPubKey"); TypedField<STBlob> const sfSigningPubKey = make::one<STBlob>(&sfSigningPubKey, STI_VL, 3, "SigningPubKey");
TypedField<STBlob> const sfSignature = make::one<STBlob>(&sfSignature, STI_VL, 6, "Signature", SField::sMD_Default, SField::notSigning); TypedField<STBlob> const sfSignature = make::one<STBlob>(&sfSignature, STI_VL, 6, "Signature", SField::sMD_Default, SField::notSigning);
@@ -190,6 +190,9 @@ SField const sfMemoType = make::one(&sfMemoType, STI_VL
SField const sfMemoData = make::one(&sfMemoData, STI_VL, 13, "MemoData"); SField const sfMemoData = make::one(&sfMemoData, STI_VL, 13, "MemoData");
SField const sfMemoFormat = make::one(&sfMemoFormat, STI_VL, 14, "MemoFormat"); SField const sfMemoFormat = make::one(&sfMemoFormat, STI_VL, 14, "MemoFormat");
// variable length (uncommon)
SField const sfMultiSignature = make::one(&sfMultiSignature, STI_VL, 16, "MultiSignature");
// account // account
SField const sfAccount = make::one(&sfAccount, STI_ACCOUNT, 1, "Account"); SField const sfAccount = make::one(&sfAccount, STI_ACCOUNT, 1, "Account");
SField const sfOwner = make::one(&sfOwner, STI_ACCOUNT, 2, "Owner"); SField const sfOwner = make::one(&sfOwner, STI_ACCOUNT, 2, "Owner");
@@ -219,10 +222,14 @@ SField const sfTemplateEntry = make::one(&sfTemplateEntry, STI_OBJEC
SField const sfMemo = make::one(&sfMemo, STI_OBJECT, 10, "Memo"); SField const sfMemo = make::one(&sfMemo, STI_OBJECT, 10, "Memo");
SField const sfSignerEntry = make::one(&sfSignerEntry, STI_OBJECT, 11, "SignerEntry"); SField const sfSignerEntry = make::one(&sfSignerEntry, STI_OBJECT, 11, "SignerEntry");
// inner object (uncommon)
SField const sfSigningAccount = make::one(&sfSigningAccount, STI_OBJECT, 16, "SigningAccount");
SField const sfSigningFor = make::one(&sfSigningFor, STI_OBJECT, 17, "SigningFor");
// array of objects // array of objects
// ARRAY/1 is reserved for end of array // ARRAY/1 is reserved for end of array
SField const sfSigningAccounts = make::one(&sfSigningAccounts, STI_ARRAY, 2, "SigningAccounts"); SField const sfSigningAccounts = make::one(&sfSigningAccounts, STI_ARRAY, 2, "SigningAccounts");
SField const sfTxnSignatures = make::one(&sfTxnSignatures, STI_ARRAY, 3, "TxnSignatures", SField::sMD_Default, SField::notSigning); SField const sfMultiSigners = make::one(&sfMultiSigners, STI_ARRAY, 3, "MultiSigners", SField::sMD_Default, SField::notSigning);
SField const sfSignerEntries = make::one(&sfSignerEntries, STI_ARRAY, 4, "SignerEntries"); SField const sfSignerEntries = make::one(&sfSignerEntries, STI_ARRAY, 4, "SignerEntries");
SField const sfTemplate = make::one(&sfTemplate, STI_ARRAY, 5, "Template"); SField const sfTemplate = make::one(&sfTemplate, STI_ARRAY, 5, "Template");
SField const sfNecessary = make::one(&sfNecessary, STI_ARRAY, 6, "Necessary"); SField const sfNecessary = make::one(&sfNecessary, STI_ARRAY, 6, "Necessary");

View File

@@ -21,6 +21,7 @@
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/json/json_reader.h> #include <ripple/json/json_reader.h>
#include <ripple/json/to_string.h> #include <ripple/json/to_string.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/InnerObjectFormats.h> #include <ripple/protocol/InnerObjectFormats.h>
#include <ripple/protocol/STBase.h> #include <ripple/protocol/STBase.h>
#include <ripple/protocol/STAccount.h> #include <ripple/protocol/STAccount.h>
@@ -337,6 +338,34 @@ uint256 STObject::getSigningHash (std::uint32_t prefix) const
return s.getSHA512Half (); return s.getSHA512Half ();
} }
Serializer
STObject::startMultiSigningData () const
{
Serializer s;
s.add32 (HashPrefix::txMultiSign);
add (s, false);
return s;
}
void
STObject::finishMultiSigningData (
RippleAddress const& signingForID,
RippleAddress const& signingID,
Serializer& s) const
{
s.add160 (signingForID.getAccountID ());
s.add160 (signingID.getAccountID ());
}
Serializer
STObject::getMultiSigningData (
RippleAddress const& signingForID, RippleAddress const& signingID) const
{
Serializer s (startMultiSigningData ());
finishMultiSigningData (signingForID, signingID, s);
return s;
}
int STObject::getFieldIndex (SField const& field) const int STObject::getFieldIndex (SField const& field) const
{ {
if (mType != nullptr) if (mType != nullptr)

View File

@@ -62,6 +62,7 @@ Json::Value doServerState (RPC::Context&); // for machines
Json::Value doSessionClose (RPC::Context&); Json::Value doSessionClose (RPC::Context&);
Json::Value doSessionOpen (RPC::Context&); Json::Value doSessionOpen (RPC::Context&);
Json::Value doSign (RPC::Context&); Json::Value doSign (RPC::Context&);
Json::Value doSignFor (RPC::Context&);
Json::Value doStop (RPC::Context&); Json::Value doStop (RPC::Context&);
Json::Value doSubmit (RPC::Context&); Json::Value doSubmit (RPC::Context&);
Json::Value doSubscribe (RPC::Context&); Json::Value doSubscribe (RPC::Context&);

View File

@@ -29,10 +29,13 @@ namespace ripple {
Json::Value doSign (RPC::Context& context) Json::Value doSign (RPC::Context& context)
{ {
context.loadType = Resource::feeHighBurdenRPC; context.loadType = Resource::feeHighBurdenRPC;
bool bFailHard = context.params.isMember (jss::fail_hard) NetworkOPs::FailHard const failType =
&& context.params[jss::fail_hard].asBool (); NetworkOPs::doFailHard (
context.params.isMember (jss::fail_hard)
&& context.params[jss::fail_hard].asBool ());
return RPC::transactionSign ( return RPC::transactionSign (
context.params, false, bFailHard, context.netOps, context.role); context.params, failType, context.netOps, context.role);
} }
} // ripple } // ripple

View File

@@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2014 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/rpc/impl/TransactionSign.h>
namespace ripple {
// {
// tx_json: <object>,
// account: <signing account>
// secret: <secret of signing account>
// }
Json::Value doSignFor (RPC::Context& context)
{
context.loadType = Resource::feeHighBurdenRPC;
NetworkOPs::FailHard const failType =
NetworkOPs::doFailHard (
context.params.isMember ("fail_hard")
&& context.params["fail_hard"].asBool ());
return RPC::transactionSignFor (
context.params, failType, context.netOps, context.role);
}
} // ripple

View File

@@ -23,6 +23,13 @@
namespace ripple { namespace ripple {
static NetworkOPs::FailHard getFailHard (RPC::Context const& context)
{
return NetworkOPs::doFailHard (
context.params.isMember ("fail_hard")
&& context.params["fail_hard"].asBool ());
}
// { // {
// tx_json: <object>, // tx_json: <object>,
// secret: <secret> // secret: <secret>
@@ -33,10 +40,10 @@ Json::Value doSubmit (RPC::Context& context)
if (!context.params.isMember (jss::tx_blob)) if (!context.params.isMember (jss::tx_blob))
{ {
bool bFailHard = context.params.isMember (jss::fail_hard) auto const failType = getFailHard (context);
&& context.params[jss::fail_hard].asBool ();
return RPC::transactionSign ( return RPC::transactionSubmit (
context.params, true, bFailHard, context.netOps, context.role); context.params, failType, context.netOps, context.role);
} }
Json::Value jvResult; Json::Value jvResult;
@@ -76,10 +83,10 @@ Json::Value doSubmit (RPC::Context& context)
try try
{ {
(void) context.netOps.processTransaction ( auto const failType = getFailHard (context);
tpTrans, context.role == Role::ADMIN, true,
context.params.isMember (jss::fail_hard) context.netOps.processTransaction (
&& context.params[jss::fail_hard].asBool ()); tpTrans, context.role == Role::ADMIN, true, failType);
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@@ -133,6 +133,9 @@ HandlerTable HANDLERS({
{ "random", byRef (&doRandom), Role::USER, NO_CONDITION }, { "random", byRef (&doRandom), Role::USER, NO_CONDITION },
{ "ripple_path_find", byRef (&doRipplePathFind), Role::USER, NO_CONDITION }, { "ripple_path_find", byRef (&doRipplePathFind), Role::USER, NO_CONDITION },
{ "sign", byRef (&doSign), Role::USER, NO_CONDITION }, { "sign", byRef (&doSign), Role::USER, NO_CONDITION },
#if RIPPLE_ENABLE_MULTI_SIGN
{ "sign_for", byRef (&doSignFor), Role::USER, NO_CONDITION },
#endif // RIPPLE_ENABLE_MULTI_SIGN
{ "submit", byRef (&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER }, { "submit", byRef (&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER },
{ "server_info", byRef (&doServerInfo), Role::USER, NO_CONDITION }, { "server_info", byRef (&doServerInfo), Role::USER, NO_CONDITION },
{ "server_state", byRef (&doServerState), Role::USER, NO_CONDITION }, { "server_state", byRef (&doServerState), Role::USER, NO_CONDITION },

File diff suppressed because it is too large Load Diff

View File

@@ -23,10 +23,10 @@
namespace ripple { namespace ripple {
namespace RPC { namespace RPC {
namespace RPCDetail { namespace detail {
// A class that allows these methods to be called with or without a // A class that allows these methods to be called with or without a
// real NetworkOPs instance. This allows for unit testing. // real NetworkOPs instance. This allows for unit testing.
class LedgerFacade class TxnSignApiFacade
{ {
private: private:
NetworkOPs* const netOPs_; NetworkOPs* const netOPs_;
@@ -40,21 +40,21 @@ public:
noNetOPs noNetOPs
}; };
LedgerFacade () = delete; TxnSignApiFacade () = delete;
LedgerFacade (LedgerFacade const&) = delete; TxnSignApiFacade (TxnSignApiFacade const&) = delete;
LedgerFacade& operator= (LedgerFacade const&) = delete; TxnSignApiFacade& operator= (TxnSignApiFacade const&) = delete;
// For use in non unit testing circumstances. // For use in non unit testing circumstances.
explicit LedgerFacade (NetworkOPs& netOPs) explicit TxnSignApiFacade (NetworkOPs& netOPs)
: netOPs_ (&netOPs) : netOPs_ (&netOPs)
{ } { }
// For testTransactionRPC unit tests. // For testTransactionRPC unit tests.
explicit LedgerFacade (NoNetworkOPs noOPs) explicit TxnSignApiFacade (NoNetworkOPs noOPs)
: netOPs_ (nullptr) { } : netOPs_ (nullptr) { }
// For testAutoFillFees unit tests. // For testAutoFillFees unit tests.
LedgerFacade (NoNetworkOPs noOPs, Ledger::pointer ledger) TxnSignApiFacade (NoNetworkOPs noOPs, Ledger::pointer ledger)
: netOPs_ (nullptr) : netOPs_ (nullptr)
, ledger_ (ledger) , ledger_ (ledger)
{ } { }
@@ -74,12 +74,11 @@ public:
STPathSet& pathsOut, STPathSet& pathsOut,
STPath& fullLiquidityPath) const; STPath& fullLiquidityPath) const;
Transaction::pointer submitTransactionSync ( Transaction::pointer processTransaction (
Transaction::ref tpTrans, Transaction::ref tpTrans,
bool bAdmin, bool bAdmin,
bool bLocal, bool bLocal,
bool bFailHard, NetworkOPs::FailHard failType);
bool bSubmit);
std::uint64_t scaleFeeBase (std::uint64_t fee) const; std::uint64_t scaleFeeBase (std::uint64_t fee) const;
@@ -87,35 +86,86 @@ public:
bool hasAccountRoot () const; bool hasAccountRoot () const;
bool accountMasterDisabled () const; error_code_i singleAcctMatchesPubKey (
RippleAddress const& publicKey) const;
bool accountMatchesRegularKey (Account account) const; error_code_i multiAcctMatchesPubKey (
RippleAddress const& acctID,
RippleAddress const& publicKey) const;
int getValidatedLedgerAge () const; int getValidatedLedgerAge () const;
bool isLoadedCluster () const; bool isLoadedCluster () const;
}; };
} // namespace RPCDetail // A function to auto-fill fees.
enum class AutoFill : unsigned char
{
dont,
might
};
static Json::Value checkFee (
Json::Value& request,
TxnSignApiFacade& apiFacade,
Role const role,
AutoFill const doAutoFill);
} // namespace detail
/** Returns a Json::objectValue. */ /** Returns a Json::objectValue. */
Json::Value transactionSign ( Json::Value transactionSign (
Json::Value params, Json::Value params, // Passed by value so it can be modified locally.
bool bSubmit, NetworkOPs::FailHard failType,
bool bFailHard, detail::TxnSignApiFacade& apiFacade,
RPCDetail::LedgerFacade& ledgerFacade,
Role role); Role role);
/** Returns a Json::objectValue. */
inline Json::Value transactionSign ( inline Json::Value transactionSign (
Json::Value params, Json::Value const& params,
bool bSubmit, NetworkOPs::FailHard failType,
bool bFailHard,
NetworkOPs& netOPs, NetworkOPs& netOPs,
Role role) Role role)
{ {
RPCDetail::LedgerFacade ledgerFacade (netOPs); detail::TxnSignApiFacade apiFacade (netOPs);
return transactionSign (params, bSubmit, bFailHard, ledgerFacade, role); return transactionSign (params, failType, apiFacade, role);
}
/** Returns a Json::objectValue. */
Json::Value transactionSubmit (
Json::Value params, // Passed by value so it can be modified locally.
NetworkOPs::FailHard failType,
detail::TxnSignApiFacade& apiFacade,
Role role);
/** Returns a Json::objectValue. */
Json::Value transactionSubmit (
Json::Value const& params,
NetworkOPs::FailHard failType,
NetworkOPs& netOPs,
Role role)
{
detail::TxnSignApiFacade apiFacade (netOPs);
return transactionSubmit (params, failType, apiFacade, role);
}
/** Returns a Json::objectValue. */
Json::Value transactionSignFor (
Json::Value params, // Passed by value so it can be modified locally.
NetworkOPs::FailHard failType,
detail::TxnSignApiFacade& apiFacade,
Role role);
/** Returns a Json::objectValue. */
Json::Value transactionSignFor (
Json::Value const& params,
NetworkOPs::FailHard failType,
NetworkOPs& netOPs,
Role role)
{
detail::TxnSignApiFacade apiFacade (netOPs);
return transactionSignFor (params, failType, apiFacade, role);
} }
} // RPC } // RPC

File diff suppressed because it is too large Load Diff

View File

@@ -73,6 +73,7 @@
#include <ripple/rpc/handlers/ServerInfo.cpp> #include <ripple/rpc/handlers/ServerInfo.cpp>
#include <ripple/rpc/handlers/ServerState.cpp> #include <ripple/rpc/handlers/ServerState.cpp>
#include <ripple/rpc/handlers/Sign.cpp> #include <ripple/rpc/handlers/Sign.cpp>
#include <ripple/rpc/handlers/SignFor.cpp>
#include <ripple/rpc/handlers/Stop.cpp> #include <ripple/rpc/handlers/Stop.cpp>
#include <ripple/rpc/handlers/Submit.cpp> #include <ripple/rpc/handlers/Submit.cpp>
#include <ripple/rpc/handlers/Subscribe.cpp> #include <ripple/rpc/handlers/Subscribe.cpp>