Track STTx validity with HashRouter. (RIPD-977)

This commit is contained in:
Edward Hennis
2015-07-13 17:01:40 -04:00
parent c15394c42a
commit 2f5d721ec1
19 changed files with 145 additions and 103 deletions

View File

@@ -1150,8 +1150,10 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
newLCL, retriableTransactions, tapNONE); newLCL, retriableTransactions, tapNONE);
} }
for (auto const& item : localTx) for (auto const& item : localTx)
apply (accum, *item.second, tapNONE, getConfig(), apply (accum, *item.second, tapNONE,
deprecatedLogs().journal("LedgerConsensus")); getApp().getHashRouter().sigVerify(),
getConfig(), deprecatedLogs().
journal("LedgerConsensus"));
accum.apply(*newOL); accum.apply(*newOL);
// We have a new Last Closed Ledger and new Open Ledger // We have a new Last Closed Ledger and new Open Ledger
ledgerMaster_.pushLedger (newLCL, newOL); ledgerMaster_.pushLedger (newLCL, newOL);
@@ -1787,8 +1789,10 @@ applyTransaction (OpenView& view,
try try
{ {
auto const result = apply(view, *txn, flags, getConfig(), auto const result = apply(view, *txn, flags,
deprecatedLogs().journal("LedgerConsensus")); getApp().getHashRouter().sigVerify(),
getConfig(), deprecatedLogs().
journal("LedgerConsensus"));
if (result.second) if (result.second)
{ {
WriteLog (lsDEBUG, LedgerConsensus) WriteLog (lsDEBUG, LedgerConsensus)

View File

@@ -379,7 +379,8 @@ public:
if (getApp().getHashRouter().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD)) if (getApp().getHashRouter().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD))
flags = flags | tapNO_CHECK_SIGN; flags = flags | tapNO_CHECK_SIGN;
auto const result = apply(view, auto const result = apply(view,
*it.second, flags, getConfig(), j); *it.second, flags, getApp().getHashRouter(
).sigVerify(), getConfig(), j);
if (result.second) if (result.second)
any = true; any = true;
} }
@@ -396,9 +397,9 @@ public:
if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD)) if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD))
tepFlags = static_cast<ApplyFlags> (tepFlags | tapNO_CHECK_SIGN); tepFlags = static_cast<ApplyFlags> (tepFlags | tapNO_CHECK_SIGN);
auto const ret = apply( auto const ret = apply(view, *it.second,
view, *it.second, tepFlags, getConfig(), tepFlags, getApp().getHashRouter().sigVerify(),
deprecatedLogs().journal("LedgerMaster")); getConfig(), deprecatedLogs().journal("LedgerMaster"));
if (ret.second) if (ret.second)
++recovers; ++recovers;

View File

@@ -111,7 +111,8 @@ OpenLedger::accept(Rules const& rules,
// Apply local tx // Apply local tx
for (auto const& item : locals) for (auto const& item : locals)
ripple::apply(*next, *item.second, ripple::apply(*next, *item.second,
flags, config_, j_); flags, router.sigVerify(),
config_, j_);
// Switch to the new open view // Switch to the new open view
std::lock_guard< std::lock_guard<
std::mutex> lock2(current_mutex_); std::mutex> lock2(current_mutex_);
@@ -144,7 +145,8 @@ OpenLedger::apply_one (OpenView& view,
SF_SIGGOOD) SF_SIGGOOD)
flags = flags | tapNO_CHECK_SIGN; flags = flags | tapNO_CHECK_SIGN;
auto const result = ripple::apply( auto const result = ripple::apply(
view, *tx, flags, config, j); view, *tx, flags, router.
sigVerify(), config, j);
if (result.second) if (result.second)
return Result::success; return Result::success;
if (isTefFailure (result.first) || if (isTefFailure (result.first) ||

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/misc/IHashRouter.h> #include <ripple/app/misc/IHashRouter.h>
#include <ripple/protocol/STTx.h>
#include <ripple/basics/CountedObject.h> #include <ripple/basics/CountedObject.h>
#include <ripple/basics/UnorderedContainers.h> #include <ripple/basics/UnorderedContainers.h>
#include <ripple/basics/UptimeTimer.h> #include <ripple/basics/UptimeTimer.h>
@@ -95,15 +96,18 @@ public:
{ {
} }
bool addSuppression (uint256 const& index); bool addSuppression (uint256 const& index) override;
bool addSuppressionPeer (uint256 const& index, PeerShortID peer); bool addSuppressionPeer (uint256 const& index, PeerShortID peer) override;
bool addSuppressionPeer (uint256 const& index, PeerShortID peer, int& flags); bool addSuppressionPeer (uint256 const& index, PeerShortID peer, int& flags) override;
bool addSuppressionFlags (uint256 const& index, int flag); bool addSuppressionFlags (uint256 const& index, int flag) override;
bool setFlag (uint256 const& index, int flag); bool setFlag (uint256 const& index, int flag) override;
int getFlags (uint256 const& index); int getFlags (uint256 const& index) override;
bool swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag); bool swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag) override;
std::function<bool(STTx const&, std::function<bool(STTx const&)>)>
sigVerify() override;
private: private:
Entry getEntry (uint256 const& ); Entry getEntry (uint256 const& );
@@ -125,6 +129,28 @@ private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
std::function<bool(STTx const&, std::function<bool(STTx const&)>)>
HashRouter::sigVerify()
{
return
[&] (STTx const& tx, std::function<bool(STTx const&)> sigCheck)
{
auto const id = tx.getTransactionID();
auto const flags = getFlags(id);
if (flags & SF_SIGGOOD)
return true;
if (flags & SF_BAD)
return false;
if (! sigCheck(tx))
{
setFlag(id, SF_BAD);
return false;
}
setFlag(id, SF_SIGGOOD);
return true;
};
}
HashRouter::Entry& HashRouter::findCreateEntry (uint256 const& index, bool& created) HashRouter::Entry& HashRouter::findCreateEntry (uint256 const& index, bool& created)
{ {
hash_map<uint256, Entry>::iterator fit = mSuppressionMap.find (index); hash_map<uint256, Entry>::iterator fit = mSuppressionMap.find (index);

View File

@@ -22,10 +22,13 @@
#include <ripple/basics/base_uint.h> #include <ripple/basics/base_uint.h>
#include <cstdint> #include <cstdint>
#include <functional>
#include <set> #include <set>
namespace ripple { namespace ripple {
class STTx;
// VFALCO NOTE Are these the flags?? Why aren't we using a packed struct? // VFALCO NOTE Are these the flags?? Why aren't we using a packed struct?
// VFALCO TODO convert these macros to int constants // VFALCO TODO convert these macros to int constants
#define SF_RELAYED 0x01 // Has already been relayed to other nodes #define SF_RELAYED 0x01 // Has already been relayed to other nodes
@@ -80,6 +83,15 @@ public:
virtual int getFlags (uint256 const& index) = 0; virtual int getFlags (uint256 const& index) = 0;
virtual bool swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag) = 0; virtual bool swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag) = 0;
/**
Function wrapper that will check the signature status
of a STTx before calling an expensive signature
checking function.
*/
virtual
std::function<bool(STTx const&, std::function<bool(STTx const&)>)>
sigVerify() = 0;
}; };
} // ripple } // ripple

View File

@@ -697,7 +697,8 @@ void NetworkOPsImp::submitTransaction (Job&, STTx::pointer iTrans)
m_job_queue.addJob (jtTRANSACTION, "submitTxn", m_job_queue.addJob (jtTRANSACTION, "submitTxn",
std::bind (&NetworkOPsImp::processTransaction, std::bind (&NetworkOPsImp::processTransaction,
this, this,
std::make_shared<Transaction> (trans, Validate::NO, reason), std::make_shared<Transaction> (trans, Validate::NO,
directSigVerify, reason),
false, false,
false, false,
FailHard::no)); FailHard::no));
@@ -722,7 +723,7 @@ void NetworkOPsImp::processTransaction (Transaction::pointer& transaction,
// signature not checked // signature not checked
std::string reason; std::string reason;
if (! transaction->checkSign (reason)) if (! transaction->checkSign (reason, directSigVerify))
{ {
m_journal.info << "Transaction has bad signature: " << reason; m_journal.info << "Transaction has bad signature: " << reason;
transaction->setStatus (INVALID); transaction->setStatus (INVALID);
@@ -870,8 +871,9 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
std::tie (e.result, e.applied) = std::tie (e.result, e.applied) =
ripple::apply (*accum, ripple::apply (*accum,
*e.transaction->getSTransaction(), flags, *e.transaction->getSTransaction(), flags,
getConfig(), deprecatedLogs().journal( getApp().getHashRouter().sigVerify(),
"NetworkOPs")); getConfig(), deprecatedLogs().journal(
"NetworkOPs"));
applied |= e.applied; applied |= e.applied;
#if RIPPLE_OPEN_LEDGER #if RIPPLE_OPEN_LEDGER
@@ -881,8 +883,9 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
[&](OpenView& view, beast::Journal j) [&](OpenView& view, beast::Journal j)
{ {
auto const result = ripple::apply( auto const result = ripple::apply(
view, *e.transaction->getSTransaction(), view, *e.transaction->getSTransaction(), flags,
flags, getConfig(), j); getApp().getHashRouter().sigVerify(),
getConfig(), j);
if (result.first != e.result) if (result.first != e.result)
mismatch(sle1, e.result, sle2, result.first, mismatch(sle1, e.result, sle2, result.first,
e.transaction->getSTransaction(), j); e.transaction->getSTransaction(), j);

View File

@@ -42,7 +42,8 @@ convertBlobsToTxResult (
STTx::pointer txn = std::make_shared<STTx> (it); STTx::pointer txn = std::make_shared<STTx> (it);
std::string reason; std::string reason;
auto tr = std::make_shared<Transaction> (txn, Validate::NO, reason); auto tr = std::make_shared<Transaction> (txn, Validate::NO,
directSigVerify, reason);
tr->setStatus (Transaction::sqlTransactionStatus(status)); tr->setStatus (Transaction::sqlTransactionStatus(status));
tr->setLedger (ledger_index); tr->setLedger (ledger_index);

View File

@@ -62,7 +62,7 @@ public:
using ref = const pointer&; using ref = const pointer&;
public: public:
Transaction (STTx::ref, Validate, std::string&) noexcept; Transaction (STTx::ref, Validate, SigVerify, std::string&) noexcept;
static static
Transaction::pointer Transaction::pointer
@@ -80,7 +80,7 @@ public:
TransStatus TransStatus
sqlTransactionStatus(boost::optional<std::string> const& status); sqlTransactionStatus(boost::optional<std::string> const& status);
bool checkSign (std::string&) const; bool checkSign (std::string&, SigVerify) const;
STTx::ref getSTransaction () STTx::ref getSTransaction ()
{ {

View File

@@ -39,7 +39,7 @@ namespace ripple {
*/ */
TER TER
preflight (Rules const& rules, STTx const& tx, preflight (Rules const& rules, STTx const& tx,
ApplyFlags flags, ApplyFlags flags, SigVerify verify,
Config const& config, beast::Journal j); Config const& config, beast::Journal j);
/** Apply a prechecked transaction to an OpenView. /** Apply a prechecked transaction to an OpenView.
@@ -86,8 +86,9 @@ doapply(OpenView& view, STTx const& tx,
std::pair<TER, bool> std::pair<TER, bool>
apply (OpenView& view, apply (OpenView& view,
STTx const& tx, ApplyFlags flags, STTx const& tx, ApplyFlags flags,
Config const& config, SigVerify verify,
beast::Journal journal); Config const& config,
beast::Journal journal);
} // ripple } // ripple

View File

@@ -23,12 +23,14 @@
#include <ripple/core/DatabaseCon.h> #include <ripple/core/DatabaseCon.h>
#include <ripple/app/ledger/LedgerMaster.h> #include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/app/misc/IHashRouter.h>
#include <ripple/protocol/JsonFields.h> #include <ripple/protocol/JsonFields.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
namespace ripple { namespace ripple {
Transaction::Transaction (STTx::ref stx, Validate validate, std::string& reason) Transaction::Transaction (STTx::ref stx, Validate validate,
SigVerify sigVerify, std::string& reason)
noexcept noexcept
: mTransaction (stx) : mTransaction (stx)
{ {
@@ -50,7 +52,8 @@ Transaction::Transaction (STTx::ref stx, Validate validate, std::string& reason)
} }
if (validate == Validate::NO || if (validate == Validate::NO ||
(passesLocalChecks (*mTransaction, reason) && checkSign (reason))) (passesLocalChecks (*mTransaction, reason) &&
checkSign (reason, sigVerify)))
{ {
mStatus = NEW; mStatus = NEW;
} }
@@ -65,7 +68,7 @@ Transaction::pointer Transaction::sharedTransaction (
std::string reason; std::string reason;
return std::make_shared<Transaction> (std::make_shared<STTx> (sit), return std::make_shared<Transaction> (std::make_shared<STTx> (sit),
validate, reason); validate, getApp().getHashRouter().sigVerify(), reason);
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@@ -84,11 +87,14 @@ Transaction::pointer Transaction::sharedTransaction (
// Misc. // Misc.
// //
bool Transaction::checkSign (std::string& reason) const bool Transaction::checkSign (std::string& reason, SigVerify sigVerify) const
{ {
if (! mFromPubKey.isValid ()) if (! mFromPubKey.isValid ())
reason = "Transaction has bad source public key"; reason = "Transaction has bad source public key";
else if (! mTransaction->checkSign ()) else if (!sigVerify(*mTransaction, [] (STTx const& tx)
{
return tx.checkSign();
}))
reason = "Transaction has bad signature"; reason = "Transaction has bad signature";
else else
return true; return true;
@@ -133,7 +139,8 @@ Transaction::pointer Transaction::transactionFromSQL (
SerialIter it (makeSlice(rawTxn)); SerialIter it (makeSlice(rawTxn));
auto txn = std::make_shared<STTx> (it); auto txn = std::make_shared<STTx> (it);
std::string reason; std::string reason;
auto tr = std::make_shared<Transaction> (txn, validate, reason); auto tr = std::make_shared<Transaction> (txn, validate,
getApp().getHashRouter().sigVerify(), reason);
tr->setStatus (sqlTransactionStatus (status)); tr->setStatus (sqlTransactionStatus (status));
tr->setLedger (inLedger); tr->setLedger (inLedger);

View File

@@ -52,24 +52,22 @@ Transactor::preflight (PreflightContext const& ctx)
auto const pk = auto const pk =
RippleAddress::createAccountPublic( RippleAddress::createAccountPublic(
tx.getSigningPubKey()); tx.getSigningPubKey());
if (!tx.isKnownGood ())
{ if(! ctx.verify(tx,
if (tx.isKnownBad () || [&, ctx] (STTx const& tx)
(! (ctx.flags & tapNO_CHECK_SIGN) && !tx.checkSign( {
( return (ctx.flags & tapNO_CHECK_SIGN) ||
tx.checkSign(
#if RIPPLE_ENABLE_MULTI_SIGN #if RIPPLE_ENABLE_MULTI_SIGN
true true
#else #else
ctx.flags & tapENABLE_TESTING ctx.flags & tapENABLE_TESTING
#endif #endif
)))) );
{ }))
tx.setBad(); {
j.debug << "apply: Invalid transaction (bad signature)"; JLOG(j.debug) << "apply: Invalid transaction (bad signature)";
return temINVALID; return temINVALID;
}
tx.setGood();
} }
return tesSUCCESS; return tesSUCCESS;

View File

@@ -31,12 +31,12 @@ struct PreflightContext
public: public:
explicit PreflightContext(STTx const& tx_, explicit PreflightContext(STTx const& tx_,
Rules const& rules_, ApplyFlags flags_, Rules const& rules_, ApplyFlags flags_,
//SigVerify verify_, SigVerify verify_,
beast::Journal j_ = {}) beast::Journal j_ = {})
: tx(tx_) : tx(tx_)
, rules(rules_) , rules(rules_)
, flags(flags_) , flags(flags_)
//, verify(verify_) , verify(verify_)
, j(j_) , j(j_)
{ {
} }
@@ -44,7 +44,7 @@ public:
STTx const& tx; STTx const& tx;
Rules const& rules; Rules const& rules;
ApplyFlags flags; ApplyFlags flags;
//SigVerify verify; SigVerify verify;
beast::Journal j; beast::Journal j;
}; };

View File

@@ -81,13 +81,13 @@ invoke_apply (ApplyContext& ctx)
TER TER
preflight (Rules const& rules, STTx const& tx, preflight (Rules const& rules, STTx const& tx,
ApplyFlags flags, ApplyFlags flags, SigVerify verify,
Config const& config, beast::Journal j) Config const& config, beast::Journal j)
{ {
try try
{ {
PreflightContext pfctx( PreflightContext pfctx(
tx, rules, flags, j); tx, rules, flags, verify, j);
return invoke_preflight(pfctx); return invoke_preflight(pfctx);
} }
catch (std::exception const& e) catch (std::exception const& e)
@@ -131,11 +131,11 @@ doapply(OpenView& view, STTx const& tx,
std::pair<TER, bool> std::pair<TER, bool>
apply (OpenView& view, STTx const& tx, apply (OpenView& view, STTx const& tx,
ApplyFlags flags, ApplyFlags flags, SigVerify verify,
Config const& config, beast::Journal j) Config const& config, beast::Journal j)
{ {
auto pfresult = preflight(view.rules(), auto pfresult = preflight(view.rules(),
tx, flags, config, j); tx, flags, verify, config, j);
if (pfresult != tesSUCCESS) if (pfresult != tesSUCCESS)
return { pfresult, false }; return { pfresult, false };
return doapply(view, tx, flags, config, j); return doapply(view, tx, flags, config, j);

View File

@@ -1707,7 +1707,9 @@ PeerImp::checkTransaction (Job&, int flags,
auto validate = (flags & SF_SIGGOOD) ? Validate::NO : Validate::YES; auto validate = (flags & SF_SIGGOOD) ? Validate::NO : Validate::YES;
std::string reason; std::string reason;
auto tx = std::make_shared<Transaction> (stx, validate, reason); auto tx = std::make_shared<Transaction> (stx, validate,
directSigVerify,
reason);
if (tx->getStatus () == INVALID) if (tx->getStatus () == INVALID)
{ {

View File

@@ -129,23 +129,6 @@ public:
#endif #endif
) const; ) const;
bool isKnownGood () const
{
return (sig_state_ == true);
}
bool isKnownBad () const
{
return (sig_state_ == false);
}
void setGood () const
{
sig_state_ = true;
}
void setBad () const
{
sig_state_ = false;
}
// SQL Functions with metadata. // SQL Functions with metadata.
static static
std::string const& std::string const&
@@ -165,12 +148,18 @@ private:
bool checkMultiSign () const; bool checkMultiSign () const;
TxType tx_type_; TxType tx_type_;
mutable boost::tribool sig_state_;
}; };
bool passesLocalChecks (STObject const& st, std::string&); bool passesLocalChecks (STObject const& st, std::string&);
using SigVerify = std::function < bool(STTx const&, std::function<bool(STTx const&)>) > ;
inline
bool directSigVerify(STTx const& tx, std::function<bool(STTx const&)> sigCheck)
{
return sigCheck(tx);
}
} // ripple } // ripple
#endif #endif

View File

@@ -39,7 +39,6 @@ namespace ripple {
STTx::STTx (TxType type) STTx::STTx (TxType type)
: STObject (sfTransaction) : STObject (sfTransaction)
, tx_type_ (type) , tx_type_ (type)
, sig_state_ (boost::indeterminate)
{ {
auto format = TxFormats::getInstance().findByType (type); auto format = TxFormats::getInstance().findByType (type);
@@ -56,7 +55,6 @@ STTx::STTx (TxType type)
STTx::STTx (STObject&& object) STTx::STTx (STObject&& object)
: STObject (std::move (object)) : STObject (std::move (object))
, sig_state_ (boost::indeterminate)
{ {
tx_type_ = static_cast <TxType> (getFieldU16 (sfTransactionType)); tx_type_ = static_cast <TxType> (getFieldU16 (sfTransactionType));
@@ -79,7 +77,6 @@ STTx::STTx (STObject&& object)
STTx::STTx (SerialIter& sit) STTx::STTx (SerialIter& sit)
: STObject (sfTransaction) : STObject (sfTransaction)
, sig_state_ (boost::indeterminate)
{ {
int length = sit.getBytesLeft (); int length = sit.getBytesLeft ();
@@ -186,33 +183,27 @@ void STTx::sign (RippleAddress const& private_key)
bool STTx::checkSign(bool allowMultiSign) const bool STTx::checkSign(bool allowMultiSign) const
{ {
if (boost::indeterminate (sig_state_)) bool sigGood = false;
try
{ {
try if (allowMultiSign)
{ {
if (allowMultiSign) // Determine whether we're single- or multi-signing by looking
{ // at the SigningPubKey. It it's empty we must be multi-signing.
// Determine whether we're single- or multi-signing by looking // Otherwise we're single-signing.
// at the SigningPubKey. It it's empty we must be multi-signing. Blob const& signingPubKey = getFieldVL (sfSigningPubKey);
// Otherwise we're single-signing. sigGood = signingPubKey.empty () ?
Blob const& signingPubKey = getFieldVL (sfSigningPubKey); checkMultiSign () : checkSingleSign ();
sig_state_ = signingPubKey.empty () ?
checkMultiSign () : checkSingleSign ();
}
else
{
sig_state_ = checkSingleSign ();
}
} }
catch (...) else
{ {
sig_state_ = false; sigGood = checkSingleSign ();
} }
} }
catch (...)
assert (!boost::indeterminate (sig_state_)); {
}
return static_cast<bool> (sig_state_); return sigGood;
} }
void STTx::setSigningPubKey (RippleAddress const& naSignPubKey) void STTx::setSigningPubKey (RippleAddress const& naSignPubKey)

View File

@@ -18,7 +18,9 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/NetworkOPs.h> #include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/IHashRouter.h>
#include <ripple/basics/StringUtilities.h> #include <ripple/basics/StringUtilities.h>
#include <ripple/basics/strHex.h> #include <ripple/basics/strHex.h>
#include <ripple/net/RPCErr.h> #include <ripple/net/RPCErr.h>
@@ -79,7 +81,8 @@ Json::Value doSubmit (RPC::Context& context)
Transaction::pointer tpTrans; Transaction::pointer tpTrans;
std::string reason; std::string reason;
tpTrans = std::make_shared<Transaction> (stpTrans, Validate::YES, reason); tpTrans = std::make_shared<Transaction> (stpTrans, Validate::YES,
getApp().getHashRouter().sigVerify(), reason);
if (tpTrans->getStatus() != NEW) if (tpTrans->getStatus() != NEW)
{ {
jvResult[jss::error] = "invalidTransaction"; jvResult[jss::error] = "invalidTransaction";

View File

@@ -721,7 +721,8 @@ transactionConstructImpl (STTx::pointer stpTrans)
Transaction::pointer tpTrans; Transaction::pointer tpTrans;
{ {
std::string reason; std::string reason;
tpTrans = std::make_shared<Transaction>(stpTrans, Validate::NO, reason); tpTrans = std::make_shared<Transaction>(stpTrans, Validate::NO,
directSigVerify, reason);
if (tpTrans->getStatus () != NEW) if (tpTrans->getStatus () != NEW)
{ {
ret.first = RPC::make_error (rpcINTERNAL, ret.first = RPC::make_error (rpcINTERNAL,

View File

@@ -262,8 +262,9 @@ Env::submit (JTx const& jt)
[&](OpenView& view, beast::Journal j) [&](OpenView& view, beast::Journal j)
{ {
std::tie(ter, didApply) = ripple::apply( std::tie(ter, didApply) = ripple::apply(
view, *stx, applyFlags(), config, view, *stx, applyFlags(),
beast::Journal{}); directSigVerify, config,
beast::Journal{});
return didApply; return didApply;
}); });
} }