mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
Add delivered amount to the ledger RPC command
This commit is contained in:
@@ -1998,6 +1998,7 @@ else ()
|
|||||||
src/ripple/rpc/handlers/ValidatorListSites.cpp
|
src/ripple/rpc/handlers/ValidatorListSites.cpp
|
||||||
src/ripple/rpc/handlers/Validators.cpp
|
src/ripple/rpc/handlers/Validators.cpp
|
||||||
src/ripple/rpc/handlers/WalletPropose.cpp
|
src/ripple/rpc/handlers/WalletPropose.cpp
|
||||||
|
src/ripple/rpc/impl/DeliveredAmount.cpp
|
||||||
src/ripple/rpc/impl/Handler.cpp
|
src/ripple/rpc/impl/Handler.cpp
|
||||||
src/ripple/rpc/impl/LegacyPathFind.cpp
|
src/ripple/rpc/impl/LegacyPathFind.cpp
|
||||||
src/ripple/rpc/impl/RPCHandler.cpp
|
src/ripple/rpc/impl/RPCHandler.cpp
|
||||||
@@ -2268,6 +2269,7 @@ else ()
|
|||||||
src/test/rpc/AmendmentBlocked_test.cpp
|
src/test/rpc/AmendmentBlocked_test.cpp
|
||||||
src/test/rpc/Book_test.cpp
|
src/test/rpc/Book_test.cpp
|
||||||
src/test/rpc/DepositAuthorized_test.cpp
|
src/test/rpc/DepositAuthorized_test.cpp
|
||||||
|
src/test/rpc/DeliveredAmount_test.cpp
|
||||||
src/test/rpc/Feature_test.cpp
|
src/test/rpc/Feature_test.cpp
|
||||||
src/test/rpc/GatewayBalances_test.cpp
|
src/test/rpc/GatewayBalances_test.cpp
|
||||||
src/test/rpc/GetCounts_test.cpp
|
src/test/rpc/GetCounts_test.cpp
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ AcceptedLedgerTx::AcceptedLedgerTx (
|
|||||||
: mLedger (ledger)
|
: mLedger (ledger)
|
||||||
, mTxn (txn)
|
, mTxn (txn)
|
||||||
, mMeta (std::make_shared<TxMeta> (
|
, mMeta (std::make_shared<TxMeta> (
|
||||||
txn->getTransactionID(), ledger->seq(), *met, logs.journal ("View")))
|
txn->getTransactionID(), ledger->seq(), *met))
|
||||||
, mAffected (mMeta->getAffectedAccounts ())
|
, mAffected (mMeta->getAffectedAccounts (logs.journal("View")))
|
||||||
, accountCache_ (accountCache)
|
, accountCache_ (accountCache)
|
||||||
, logs_ (logs)
|
, logs_ (logs)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,13 +170,13 @@ log_metadata_difference(
|
|||||||
uint256 const& tx,
|
uint256 const& tx,
|
||||||
beast::Journal j)
|
beast::Journal j)
|
||||||
{
|
{
|
||||||
auto getMeta = [j](ReadView const& ledger,
|
auto getMeta = [](ReadView const& ledger,
|
||||||
uint256 const& txID) -> std::shared_ptr<TxMeta>
|
uint256 const& txID) -> std::shared_ptr<TxMeta>
|
||||||
{
|
{
|
||||||
auto meta = ledger.txRead(txID).second;
|
auto meta = ledger.txRead(txID).second;
|
||||||
if (!meta)
|
if (!meta)
|
||||||
return {};
|
return {};
|
||||||
return std::make_shared<TxMeta> (txID, ledger.seq(), *meta, j);
|
return std::make_shared<TxMeta> (txID, ledger.seq(), *meta);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto validMetaData = getMeta (validLedger, tx);
|
auto validMetaData = getMeta (validLedger, tx);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#include <ripple/app/misc/TxQ.h>
|
#include <ripple/app/misc/TxQ.h>
|
||||||
#include <ripple/basics/base_uint.h>
|
#include <ripple/basics/base_uint.h>
|
||||||
#include <ripple/basics/date.h>
|
#include <ripple/basics/date.h>
|
||||||
|
#include <ripple/rpc/Context.h>
|
||||||
|
#include <ripple/rpc/DeliveredAmount.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -97,49 +99,63 @@ void fillJsonBinary(Object& json, bool closed, LedgerInfo const& info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value fillJsonTx (LedgerFill const& fill,
|
Json::Value
|
||||||
bool bBinary, bool bExpanded,
|
fillJsonTx(
|
||||||
std::pair<std::shared_ptr<STTx const>,
|
LedgerFill const& fill,
|
||||||
std::shared_ptr<STObject const>> const i)
|
bool bBinary,
|
||||||
|
bool bExpanded,
|
||||||
|
std::shared_ptr<STTx const> const& txn,
|
||||||
|
std::shared_ptr<STObject const> const& stMeta)
|
||||||
{
|
{
|
||||||
if (! bExpanded)
|
if (!bExpanded)
|
||||||
|
return to_string(txn->getTransactionID());
|
||||||
|
|
||||||
|
Json::Value txJson{Json::objectValue};
|
||||||
|
auto const txnType = txn->getTxnType();
|
||||||
|
if (bBinary)
|
||||||
{
|
{
|
||||||
return to_string(i.first->getTransactionID());
|
txJson[jss::tx_blob] = serializeHex(*txn);
|
||||||
|
if (stMeta)
|
||||||
|
txJson[jss::meta] = serializeHex(*stMeta);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Json::Value txJson{ Json::objectValue };
|
copyFrom(txJson, txn->getJson(0));
|
||||||
if (bBinary)
|
if (stMeta)
|
||||||
{
|
{
|
||||||
txJson[jss::tx_blob] = serializeHex(*i.first);
|
txJson[jss::metaData] = stMeta->getJson(0);
|
||||||
if (i.second)
|
if (txnType == ttPAYMENT || txnType == ttCHECK_CASH)
|
||||||
txJson[jss::meta] = serializeHex(*i.second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
copyFrom(txJson, i.first->getJson(0));
|
|
||||||
if (i.second)
|
|
||||||
txJson[jss::metaData] = i.second->getJson(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fill.options & LedgerFill::ownerFunds) &&
|
|
||||||
i.first->getTxnType() == ttOFFER_CREATE)
|
|
||||||
{
|
|
||||||
auto const account = i.first->getAccountID(sfAccount);
|
|
||||||
auto const amount = i.first->getFieldAmount(sfTakerGets);
|
|
||||||
|
|
||||||
// If the offer create is not self funded then add the
|
|
||||||
// owner balance
|
|
||||||
if (account != amount.getIssuer())
|
|
||||||
{
|
{
|
||||||
auto const ownerFunds = accountFunds(fill.ledger,
|
// Insert delivered amount
|
||||||
account, amount, fhIGNORE_FREEZE,
|
auto txMeta = std::make_shared<TxMeta>(
|
||||||
beast::Journal {beast::Journal::getNullSink()});
|
txn->getTransactionID(), fill.ledger.seq(), *stMeta);
|
||||||
txJson[jss::owner_funds] = ownerFunds.getText ();
|
RPC::insertDeliveredAmount(
|
||||||
|
txJson[jss::metaData], fill.ledger, txn, *txMeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return txJson;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((fill.options & LedgerFill::ownerFunds) &&
|
||||||
|
txn->getTxnType() == ttOFFER_CREATE)
|
||||||
|
{
|
||||||
|
auto const account = txn->getAccountID(sfAccount);
|
||||||
|
auto const amount = txn->getFieldAmount(sfTakerGets);
|
||||||
|
|
||||||
|
// If the offer create is not self funded then add the
|
||||||
|
// owner balance
|
||||||
|
if (account != amount.getIssuer())
|
||||||
|
{
|
||||||
|
auto const ownerFunds = accountFunds(
|
||||||
|
fill.ledger,
|
||||||
|
account,
|
||||||
|
amount,
|
||||||
|
fhIGNORE_FREEZE,
|
||||||
|
beast::Journal{beast::Journal::getNullSink()});
|
||||||
|
txJson[jss::owner_funds] = ownerFunds.getText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return txJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Object>
|
template <class Object>
|
||||||
@@ -153,7 +169,7 @@ void fillJsonTx (Object& json, LedgerFill const& fill)
|
|||||||
{
|
{
|
||||||
for (auto& i: fill.ledger.txs)
|
for (auto& i: fill.ledger.txs)
|
||||||
{
|
{
|
||||||
txns.append(fillJsonTx(fill, bBinary, bExpanded, i));
|
txns.append(fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception const&)
|
catch (std::exception const&)
|
||||||
@@ -219,8 +235,7 @@ void fillJsonQueue(Object& json, LedgerFill const& fill)
|
|||||||
if (tx.lastResult)
|
if (tx.lastResult)
|
||||||
txJson["last_result"] = transToken(*tx.lastResult);
|
txJson["last_result"] = transToken(*tx.lastResult);
|
||||||
|
|
||||||
txJson[jss::tx] = fillJsonTx(fill, bBinary, bExpanded,
|
txJson[jss::tx] = fillJsonTx(fill, bBinary, bExpanded, tx.txn, nullptr);
|
||||||
std::make_pair(tx.txn, nullptr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2063,7 +2063,7 @@ void ApplicationImp::addTxnSeqField ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxMeta m (transID, 0, txnMeta, journal ("TxMeta"));
|
TxMeta m (transID, 0, txnMeta);
|
||||||
txIDs.push_back (std::make_pair (transID, m.getIndex ()));
|
txIDs.push_back (std::make_pair (transID, m.getIndex ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
#include <ripple/overlay/predicates.h>
|
#include <ripple/overlay/predicates.h>
|
||||||
#include <ripple/protocol/BuildInfo.h>
|
#include <ripple/protocol/BuildInfo.h>
|
||||||
#include <ripple/resource/ResourceManager.h>
|
#include <ripple/resource/ResourceManager.h>
|
||||||
|
#include <ripple/rpc/DeliveredAmount.h>
|
||||||
#include <ripple/beast/rfc2616.h>
|
#include <ripple/beast/rfc2616.h>
|
||||||
#include <ripple/beast/core/LexicalCast.h>
|
#include <ripple/beast/core/LexicalCast.h>
|
||||||
#include <ripple/beast/utility/rngfill.h>
|
#include <ripple/beast/utility/rngfill.h>
|
||||||
@@ -1963,9 +1964,10 @@ NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (txn)
|
if (txn)
|
||||||
ret.emplace_back (txn, std::make_shared<TxMeta> (
|
ret.emplace_back(
|
||||||
txn->getID (), txn->getLedger (), txnMeta,
|
txn,
|
||||||
app_.journal("TxMeta")));
|
std::make_shared<TxMeta>(
|
||||||
|
txn->getID(), txn->getLedger(), txnMeta));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2556,9 +2558,16 @@ void NetworkOPsImp::pubValidatedTransaction (
|
|||||||
std::shared_ptr<ReadView const> const& alAccepted,
|
std::shared_ptr<ReadView const> const& alAccepted,
|
||||||
const AcceptedLedgerTx& alTx)
|
const AcceptedLedgerTx& alTx)
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<STTx const> stTxn = alTx.getTxn();
|
||||||
Json::Value jvObj = transJson (
|
Json::Value jvObj = transJson (
|
||||||
*alTx.getTxn (), alTx.getResult (), true, alAccepted);
|
*stTxn, alTx.getResult (), true, alAccepted);
|
||||||
jvObj[jss::meta] = alTx.getMeta ()->getJson (0);
|
|
||||||
|
if (auto const txMeta = alTx.getMeta())
|
||||||
|
{
|
||||||
|
jvObj[jss::meta] = txMeta->getJson(0);
|
||||||
|
RPC::insertDeliveredAmount(
|
||||||
|
jvObj[jss::meta], *alAccepted, stTxn, *txMeta);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ScopedLockType sl (mSubLock);
|
ScopedLockType sl (mSubLock);
|
||||||
@@ -2666,11 +2675,19 @@ void NetworkOPsImp::pubAccountTransaction (
|
|||||||
|
|
||||||
if (!notify.empty ())
|
if (!notify.empty ())
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<STTx const> stTxn = alTx.getTxn();
|
||||||
Json::Value jvObj = transJson (
|
Json::Value jvObj = transJson (
|
||||||
*alTx.getTxn (), alTx.getResult (), bAccepted, lpCurrent);
|
*stTxn, alTx.getResult (), bAccepted, lpCurrent);
|
||||||
|
|
||||||
if (alTx.isApplied ())
|
if (alTx.isApplied ())
|
||||||
jvObj[jss::meta] = alTx.getMeta ()->getJson (0);
|
{
|
||||||
|
if (auto const txMeta = alTx.getMeta())
|
||||||
|
{
|
||||||
|
jvObj[jss::meta] = txMeta->getJson(0);
|
||||||
|
RPC::insertDeliveredAmount(
|
||||||
|
jvObj[jss::meta], *lpCurrent, stTxn, *txMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (InfoSub::ref isrListener : notify)
|
for (InfoSub::ref isrListener : notify)
|
||||||
isrListener->send (jvObj, true);
|
isrListener->send (jvObj, true);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ convertBlobsToTxResult (
|
|||||||
tr->setLedger (ledger_index);
|
tr->setLedger (ledger_index);
|
||||||
|
|
||||||
auto metaset = std::make_shared<TxMeta> (
|
auto metaset = std::make_shared<TxMeta> (
|
||||||
tr->getID (), tr->getLedger (), rawMeta, app.journal ("TxMeta"));
|
tr->getID (), tr->getLedger (), rawMeta);
|
||||||
|
|
||||||
to.emplace_back(std::move(tr), metaset);
|
to.emplace_back(std::move(tr), metaset);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,29 +42,26 @@ private:
|
|||||||
explicit CtorHelper() = default;
|
explicit CtorHelper() = default;
|
||||||
};
|
};
|
||||||
template<class T>
|
template<class T>
|
||||||
TxMeta (uint256 const& txID, std::uint32_t ledger, T const& data, beast::Journal j,
|
TxMeta (uint256 const& txID, std::uint32_t ledger, T const& data, CtorHelper);
|
||||||
CtorHelper);
|
|
||||||
public:
|
public:
|
||||||
TxMeta (beast::Journal j)
|
TxMeta ()
|
||||||
: mLedger (0)
|
: mLedger (0)
|
||||||
, mIndex (static_cast<std::uint32_t> (-1))
|
, mIndex (static_cast<std::uint32_t> (-1))
|
||||||
, mResult (255)
|
, mResult (255)
|
||||||
, j_ (j)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TxMeta (uint256 const& txID, std::uint32_t ledger, std::uint32_t index, beast::Journal j)
|
TxMeta (uint256 const& txID, std::uint32_t ledger, std::uint32_t index)
|
||||||
: mTransactionID (txID)
|
: mTransactionID (txID)
|
||||||
, mLedger (ledger)
|
, mLedger (ledger)
|
||||||
, mIndex (static_cast<std::uint32_t> (-1))
|
, mIndex (static_cast<std::uint32_t> (-1))
|
||||||
, mResult (255)
|
, mResult (255)
|
||||||
, j_(j)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TxMeta (uint256 const& txID, std::uint32_t ledger, Blob const&, beast::Journal j);
|
TxMeta (uint256 const& txID, std::uint32_t ledger, Blob const&);
|
||||||
TxMeta (uint256 const& txID, std::uint32_t ledger, std::string const&, beast::Journal j);
|
TxMeta (uint256 const& txID, std::uint32_t ledger, std::string const&);
|
||||||
TxMeta (uint256 const& txID, std::uint32_t ledger, STObject const&, beast::Journal j);
|
TxMeta (uint256 const& txID, std::uint32_t ledger, STObject const&);
|
||||||
|
|
||||||
void init (uint256 const& transactionID, std::uint32_t ledger);
|
void init (uint256 const& transactionID, std::uint32_t ledger);
|
||||||
void clear ()
|
void clear ()
|
||||||
@@ -103,7 +100,7 @@ public:
|
|||||||
|
|
||||||
/** Return a list of accounts affected by this transaction */
|
/** Return a list of accounts affected by this transaction */
|
||||||
boost::container::flat_set<AccountID>
|
boost::container::flat_set<AccountID>
|
||||||
getAffectedAccounts() const;
|
getAffectedAccounts(beast::Journal j) const;
|
||||||
|
|
||||||
Json::Value getJson (int p) const
|
Json::Value getJson (int p) const
|
||||||
{
|
{
|
||||||
@@ -144,8 +141,6 @@ private:
|
|||||||
boost::optional <STAmount> mDelivered;
|
boost::optional <STAmount> mDelivered;
|
||||||
|
|
||||||
STArray mNodes;
|
STArray mNodes;
|
||||||
|
|
||||||
beast::Journal j_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ ApplyStateTable::apply (OpenView& to,
|
|||||||
std::shared_ptr<Serializer> sMeta;
|
std::shared_ptr<Serializer> sMeta;
|
||||||
if (!to.open())
|
if (!to.open())
|
||||||
{
|
{
|
||||||
TxMeta meta(j);
|
TxMeta meta;
|
||||||
// VFALCO Shouldn't TxMeta ctor do this?
|
// VFALCO Shouldn't TxMeta ctor do this?
|
||||||
meta.init (tx.getTransactionID(), to.seq());
|
meta.init (tx.getTransactionID(), to.seq());
|
||||||
if (deliver)
|
if (deliver)
|
||||||
|
|||||||
@@ -30,11 +30,10 @@ namespace ripple {
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
TxMeta::TxMeta (uint256 const& txid,
|
TxMeta::TxMeta (uint256 const& txid,
|
||||||
std::uint32_t ledger, T const& data, beast::Journal j, CtorHelper)
|
std::uint32_t ledger, T const& data, CtorHelper)
|
||||||
: mTransactionID (txid)
|
: mTransactionID (txid)
|
||||||
, mLedger (ledger)
|
, mLedger (ledger)
|
||||||
, mNodes (sfAffectedNodes, 32)
|
, mNodes (sfAffectedNodes, 32)
|
||||||
, j_ (j)
|
|
||||||
{
|
{
|
||||||
SerialIter sit (makeSlice(data));
|
SerialIter sit (makeSlice(data));
|
||||||
|
|
||||||
@@ -47,12 +46,10 @@ TxMeta::TxMeta (uint256 const& txid,
|
|||||||
setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
|
setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
TxMeta::TxMeta (uint256 const& txid, std::uint32_t ledger, STObject const& obj,
|
TxMeta::TxMeta (uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
||||||
beast::Journal j)
|
|
||||||
: mTransactionID (txid)
|
: mTransactionID (txid)
|
||||||
, mLedger (ledger)
|
, mLedger (ledger)
|
||||||
, mNodes (obj.getFieldArray (sfAffectedNodes))
|
, mNodes (obj.getFieldArray (sfAffectedNodes))
|
||||||
, j_ (j)
|
|
||||||
{
|
{
|
||||||
mResult = obj.getFieldU8 (sfTransactionResult);
|
mResult = obj.getFieldU8 (sfTransactionResult);
|
||||||
mIndex = obj.getFieldU32 (sfTransactionIndex);
|
mIndex = obj.getFieldU32 (sfTransactionIndex);
|
||||||
@@ -69,17 +66,15 @@ TxMeta::TxMeta (uint256 const& txid, std::uint32_t ledger, STObject const& obj,
|
|||||||
|
|
||||||
TxMeta::TxMeta (uint256 const& txid,
|
TxMeta::TxMeta (uint256 const& txid,
|
||||||
std::uint32_t ledger,
|
std::uint32_t ledger,
|
||||||
Blob const& vec,
|
Blob const& vec)
|
||||||
beast::Journal j)
|
: TxMeta (txid, ledger, vec, CtorHelper ())
|
||||||
: TxMeta (txid, ledger, vec, j, CtorHelper ())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TxMeta::TxMeta (uint256 const& txid,
|
TxMeta::TxMeta (uint256 const& txid,
|
||||||
std::uint32_t ledger,
|
std::uint32_t ledger,
|
||||||
std::string const& data,
|
std::string const& data)
|
||||||
beast::Journal j)
|
: TxMeta (txid, ledger, data, CtorHelper ())
|
||||||
: TxMeta (txid, ledger, data, j, CtorHelper ())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +112,7 @@ void TxMeta::setAffectedNode (uint256 const& node, SField const& type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::container::flat_set<AccountID>
|
boost::container::flat_set<AccountID>
|
||||||
TxMeta::getAffectedAccounts() const
|
TxMeta::getAffectedAccounts(beast::Journal j) const
|
||||||
{
|
{
|
||||||
boost::container::flat_set<AccountID> list;
|
boost::container::flat_set<AccountID> list;
|
||||||
list.reserve (10);
|
list.reserve (10);
|
||||||
@@ -156,7 +151,7 @@ TxMeta::getAffectedAccounts() const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JLOG (j_.fatal()) << "limit is not amount " << field.getJson (0);
|
JLOG (j.fatal()) << "limit is not amount " << field.getJson (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ JSS ( dbKBLedger ); // out: getCounts
|
|||||||
JSS ( dbKBTotal ); // out: getCounts
|
JSS ( dbKBTotal ); // out: getCounts
|
||||||
JSS ( dbKBTransaction ); // out: getCounts
|
JSS ( dbKBTransaction ); // out: getCounts
|
||||||
JSS ( debug_signing ); // in: TransactionSign
|
JSS ( debug_signing ); // in: TransactionSign
|
||||||
JSS ( delivered_amount ); // out: addPaymentDeliveredAmount
|
JSS ( delivered_amount ); // out: insertDeliveredAmount
|
||||||
JSS ( deposit_authorized ); // out: deposit_authorized
|
JSS ( deposit_authorized ); // out: deposit_authorized
|
||||||
JSS ( deposit_preauth ); // in: AccountObjects, LedgerData
|
JSS ( deposit_preauth ); // in: AccountObjects, LedgerData
|
||||||
JSS ( deprecated ); // out
|
JSS ( deprecated ); // out
|
||||||
|
|||||||
68
src/ripple/rpc/DeliveredAmount.h
Normal file
68
src/ripple/rpc/DeliveredAmount.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2019 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.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_RPC_DELIVEREDAMOUNT_H_INCLUDED
|
||||||
|
#define RIPPLE_RPC_DELIVEREDAMOUNT_H_INCLUDED
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
class Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
class ReadView;
|
||||||
|
class Transaction;
|
||||||
|
class TxMeta;
|
||||||
|
class STTx;
|
||||||
|
|
||||||
|
namespace RPC {
|
||||||
|
|
||||||
|
struct Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add a `delivered_amount` field to the `meta` input/output parameter.
|
||||||
|
The field is only added to successful payment and check cash transactions.
|
||||||
|
If a delivered amount field is available in the TxMeta parameter, that value
|
||||||
|
is used. Otherwise, the transaction's `Amount` field is used. If neither is available,
|
||||||
|
then the delivered amount is set to "unavailable".
|
||||||
|
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
insertDeliveredAmount(
|
||||||
|
Json::Value& meta,
|
||||||
|
ReadView const&,
|
||||||
|
std::shared_ptr<STTx const> serializedTx,
|
||||||
|
TxMeta const&);
|
||||||
|
|
||||||
|
void
|
||||||
|
insertDeliveredAmount(
|
||||||
|
Json::Value& meta,
|
||||||
|
Context&,
|
||||||
|
std::shared_ptr<Transaction>,
|
||||||
|
TxMeta const&);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
} // RPC
|
||||||
|
} // ripple
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <ripple/protocol/UintTypes.h>
|
#include <ripple/protocol/UintTypes.h>
|
||||||
#include <ripple/resource/Fees.h>
|
#include <ripple/resource/Fees.h>
|
||||||
#include <ripple/rpc/Context.h>
|
#include <ripple/rpc/Context.h>
|
||||||
|
#include <ripple/rpc/DeliveredAmount.h>
|
||||||
#include <ripple/rpc/impl/RPCHelpers.h>
|
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||||
#include <ripple/rpc/Role.h>
|
#include <ripple/rpc/Role.h>
|
||||||
|
|
||||||
@@ -166,7 +167,7 @@ Json::Value doAccountTx (RPC::Context& context)
|
|||||||
if (it.second)
|
if (it.second)
|
||||||
{
|
{
|
||||||
auto meta = it.second->getJson (1);
|
auto meta = it.second->getJson (1);
|
||||||
addPaymentDeliveredAmount (meta, context, it.first, it.second);
|
insertDeliveredAmount (meta, context, it.first, *it.second);
|
||||||
jvObj[jss::meta] = std::move(meta);
|
jvObj[jss::meta] = std::move(meta);
|
||||||
|
|
||||||
std::uint32_t uLedgerIndex = it.second->getLgrSeq ();
|
std::uint32_t uLedgerIndex = it.second->getLgrSeq ();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <ripple/protocol/JsonFields.h>
|
#include <ripple/protocol/JsonFields.h>
|
||||||
#include <ripple/resource/Fees.h>
|
#include <ripple/resource/Fees.h>
|
||||||
#include <ripple/rpc/Context.h>
|
#include <ripple/rpc/Context.h>
|
||||||
|
#include <ripple/rpc/DeliveredAmount.h>
|
||||||
#include <ripple/rpc/impl/RPCHelpers.h>
|
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||||
#include <ripple/rpc/Role.h>
|
#include <ripple/rpc/Role.h>
|
||||||
|
|
||||||
@@ -183,7 +184,7 @@ Json::Value doAccountTxOld (RPC::Context& context)
|
|||||||
std::uint32_t uLedgerIndex = it->second->getLgrSeq ();
|
std::uint32_t uLedgerIndex = it->second->getLgrSeq ();
|
||||||
|
|
||||||
auto meta = it->second->getJson(0);
|
auto meta = it->second->getJson(0);
|
||||||
addPaymentDeliveredAmount(meta, context, it->first, it->second);
|
insertDeliveredAmount(meta, context, it->first, *it->second);
|
||||||
jvObj[jss::meta] = std::move(meta);
|
jvObj[jss::meta] = std::move(meta);
|
||||||
|
|
||||||
jvObj[jss::validated]
|
jvObj[jss::validated]
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <ripple/protocol/ErrorCodes.h>
|
#include <ripple/protocol/ErrorCodes.h>
|
||||||
#include <ripple/protocol/JsonFields.h>
|
#include <ripple/protocol/JsonFields.h>
|
||||||
#include <ripple/rpc/Context.h>
|
#include <ripple/rpc/Context.h>
|
||||||
|
#include <ripple/rpc/DeliveredAmount.h>
|
||||||
#include <ripple/rpc/impl/RPCHelpers.h>
|
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -126,12 +127,12 @@ Json::Value doTx (RPC::Context& context)
|
|||||||
auto rawMeta = lgr->txRead (txn->getID()).second;
|
auto rawMeta = lgr->txRead (txn->getID()).second;
|
||||||
if (rawMeta)
|
if (rawMeta)
|
||||||
{
|
{
|
||||||
auto txMeta = std::make_shared<TxMeta> (txn->getID (),
|
auto txMeta = std::make_shared<TxMeta>(
|
||||||
lgr->seq (), *rawMeta, context.app.journal ("TxMeta"));
|
txn->getID(), lgr->seq(), *rawMeta);
|
||||||
okay = true;
|
okay = true;
|
||||||
auto meta = txMeta->getJson (0);
|
auto meta = txMeta->getJson (0);
|
||||||
addPaymentDeliveredAmount (meta, context, txn, txMeta);
|
insertDeliveredAmount (meta, context, txn, *txMeta);
|
||||||
ret[jss::meta] = meta;
|
ret[jss::meta] = std::move(meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
173
src/ripple/rpc/impl/DeliveredAmount.cpp
Normal file
173
src/ripple/rpc/impl/DeliveredAmount.cpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2019 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 <ripple/rpc/DeliveredAmount.h>
|
||||||
|
|
||||||
|
#include <ripple/app/ledger/LedgerMaster.h>
|
||||||
|
#include <ripple/app/ledger/OpenLedger.h>
|
||||||
|
#include <ripple/app/misc/Transaction.h>
|
||||||
|
#include <ripple/ledger/View.h>
|
||||||
|
#include <ripple/net/RPCErr.h>
|
||||||
|
#include <ripple/protocol/AccountID.h>
|
||||||
|
#include <ripple/protocol/Feature.h>
|
||||||
|
#include <ripple/rpc/Context.h>
|
||||||
|
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||||
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace RPC {
|
||||||
|
|
||||||
|
/*
|
||||||
|
GetLedgerIndex and GetCloseTime are lambdas that allow the close time and
|
||||||
|
ledger index to be lazily calculated. Without these lambdas, these values
|
||||||
|
would be calculated even when not needed, and in some circumstances they are
|
||||||
|
not trivial to compute.
|
||||||
|
|
||||||
|
GetFix1623Enabled is a callable that returns a bool
|
||||||
|
GetLedgerIndex is a callable that returns a LedgerIndex
|
||||||
|
GetCloseTime is a callable that returns a
|
||||||
|
boost::optional<NetClock::time_point>
|
||||||
|
*/
|
||||||
|
template<class GetFix1623Enabled, class GetLedgerIndex, class GetCloseTime>
|
||||||
|
void
|
||||||
|
insertDeliveredAmount(
|
||||||
|
Json::Value& meta,
|
||||||
|
GetFix1623Enabled const& getFix1623Enabled,
|
||||||
|
GetLedgerIndex const& getLedgerIndex,
|
||||||
|
GetCloseTime const& getCloseTime,
|
||||||
|
std::shared_ptr<STTx const> serializedTx,
|
||||||
|
TxMeta const& transactionMeta)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TxType const tt{serializedTx->getTxnType()};
|
||||||
|
if (tt != ttPAYMENT &&
|
||||||
|
tt != ttCHECK_CASH)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tt == ttCHECK_CASH &&
|
||||||
|
!getFix1623Enabled())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the transaction failed nothing could have been delivered.
|
||||||
|
if (transactionMeta.getResultTER() != tesSUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (transactionMeta.hasDeliveredAmount())
|
||||||
|
{
|
||||||
|
meta[jss::delivered_amount] =
|
||||||
|
transactionMeta.getDeliveredAmount().getJson(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serializedTx->isFieldPresent(sfAmount))
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
// Ledger 4594095 is the first ledger in which the DeliveredAmount field
|
||||||
|
// was present when a partial payment was made and its absence indicates
|
||||||
|
// that the amount delivered is listed in the Amount field.
|
||||||
|
//
|
||||||
|
// If the ledger closed long after the DeliveredAmount code was deployed
|
||||||
|
// then its absence indicates that the amount delivered is listed in the
|
||||||
|
// Amount field. DeliveredAmount went live January 24, 2014.
|
||||||
|
// 446000000 is in Feb 2014, well after DeliveredAmount went live
|
||||||
|
if (getLedgerIndex() >= 4594095 ||
|
||||||
|
getCloseTime() > NetClock::time_point{446000000s})
|
||||||
|
{
|
||||||
|
meta[jss::delivered_amount] =
|
||||||
|
serializedTx->getFieldAmount(sfAmount).getJson(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// report "unavailable" which cannot be parsed into a sensible amount.
|
||||||
|
meta[jss::delivered_amount] = Json::Value("unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
insertDeliveredAmount(
|
||||||
|
Json::Value& meta,
|
||||||
|
ReadView const& ledger,
|
||||||
|
std::shared_ptr<STTx const> serializedTx,
|
||||||
|
TxMeta const& transactionMeta)
|
||||||
|
{
|
||||||
|
if (!serializedTx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto const info = ledger.info();
|
||||||
|
auto const getFix1623Enabled = [&ledger] {
|
||||||
|
return ledger.rules().enabled(fix1623);
|
||||||
|
};
|
||||||
|
auto const getLedgerIndex = [&info] {
|
||||||
|
return info.seq;
|
||||||
|
};
|
||||||
|
auto const getCloseTime = [&info] {
|
||||||
|
return info.closeTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
insertDeliveredAmount(
|
||||||
|
meta,
|
||||||
|
getFix1623Enabled,
|
||||||
|
getLedgerIndex,
|
||||||
|
getCloseTime,
|
||||||
|
std::move(serializedTx),
|
||||||
|
transactionMeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
insertDeliveredAmount(
|
||||||
|
Json::Value& meta,
|
||||||
|
RPC::Context& context,
|
||||||
|
std::shared_ptr<Transaction> transaction,
|
||||||
|
TxMeta const& transactionMeta)
|
||||||
|
{
|
||||||
|
if (!transaction)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto const serializedTx = transaction->getSTransaction ();
|
||||||
|
if (! serializedTx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
// These lambdas are used to compute the values lazily
|
||||||
|
auto const getFix1623Enabled = [&context]() -> bool {
|
||||||
|
auto const view = context.app.openLedger().current();
|
||||||
|
if (!view)
|
||||||
|
return false;
|
||||||
|
return view->rules().enabled(fix1623);
|
||||||
|
};
|
||||||
|
auto const getLedgerIndex = [&transaction]() -> LedgerIndex {
|
||||||
|
return transaction->getLedger();
|
||||||
|
};
|
||||||
|
auto const getCloseTime =
|
||||||
|
[&context, &transaction]() -> boost::optional<NetClock::time_point> {
|
||||||
|
return context.ledgerMaster.getCloseTimeBySeq(transaction->getLedger());
|
||||||
|
};
|
||||||
|
|
||||||
|
insertDeliveredAmount(
|
||||||
|
meta,
|
||||||
|
getFix1623Enabled,
|
||||||
|
getLedgerIndex,
|
||||||
|
getCloseTime,
|
||||||
|
std::move(serializedTx),
|
||||||
|
transactionMeta);
|
||||||
|
}
|
||||||
|
} // RPC
|
||||||
|
} // ripple
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <ripple/protocol/AccountID.h>
|
#include <ripple/protocol/AccountID.h>
|
||||||
#include <ripple/protocol/Feature.h>
|
#include <ripple/protocol/Feature.h>
|
||||||
#include <ripple/rpc/Context.h>
|
#include <ripple/rpc/Context.h>
|
||||||
|
#include <ripple/rpc/DeliveredAmount.h>
|
||||||
#include <ripple/rpc/impl/RPCHelpers.h>
|
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
|
||||||
@@ -393,86 +394,6 @@ parseAccountIds(Json::Value const& jvArray)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
addPaymentDeliveredAmount(Json::Value& meta, RPC::Context& context,
|
|
||||||
std::shared_ptr<Transaction> transaction, TxMeta::pointer transactionMeta)
|
|
||||||
{
|
|
||||||
// We only want to add a "delivered_amount" field if the transaction
|
|
||||||
// succeeded - otherwise nothing could have been delivered.
|
|
||||||
if (! transaction)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto const serializedTx = transaction->getSTransaction ();
|
|
||||||
if (! serializedTx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
{
|
|
||||||
// Only include this field for Payment and CheckCash transactions.
|
|
||||||
TxType const tt {serializedTx->getTxnType()};
|
|
||||||
if ((tt != ttPAYMENT) && (tt != ttCHECK_CASH))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Only include this field for CheckCash transactions if the fix
|
|
||||||
// is enabled.
|
|
||||||
if (tt == ttCHECK_CASH)
|
|
||||||
{
|
|
||||||
auto const view = context.app.openLedger().current();
|
|
||||||
if (!view || !view->rules().enabled (fix1623))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transactionMeta)
|
|
||||||
{
|
|
||||||
if (transactionMeta->getResultTER() != tesSUCCESS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If the transaction explicitly specifies a DeliveredAmount in the
|
|
||||||
// metadata then we use it.
|
|
||||||
if (transactionMeta->hasDeliveredAmount ())
|
|
||||||
{
|
|
||||||
meta[jss::delivered_amount] =
|
|
||||||
transactionMeta->getDeliveredAmount ().getJson (1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (transaction->getResult() != tesSUCCESS)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serializedTx->isFieldPresent (sfAmount))
|
|
||||||
{
|
|
||||||
// Ledger 4594095 is the first ledger in which the DeliveredAmount field
|
|
||||||
// was present when a partial payment was made and its absence indicates
|
|
||||||
// that the amount delivered is listed in the Amount field.
|
|
||||||
if (transaction->getLedger () >= 4594095)
|
|
||||||
{
|
|
||||||
meta[jss::delivered_amount] =
|
|
||||||
serializedTx->getFieldAmount (sfAmount).getJson (1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the ledger closed long after the DeliveredAmount code was deployed
|
|
||||||
// then its absence indicates that the amount delivered is listed in the
|
|
||||||
// Amount field. DeliveredAmount went live January 24, 2014.
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
auto const ct =
|
|
||||||
context.ledgerMaster.getCloseTimeBySeq (transaction->getLedger ());
|
|
||||||
if (ct && (*ct > NetClock::time_point{446000000s}))
|
|
||||||
{
|
|
||||||
// 446000000 is in Feb 2014, well after DeliveredAmount went live
|
|
||||||
meta[jss::delivered_amount] =
|
|
||||||
serializedTx->getFieldAmount (sfAmount).getJson (1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise we report "unavailable" which cannot be parsed into a
|
|
||||||
// sensible amount.
|
|
||||||
meta[jss::delivered_amount] = Json::Value ("unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
injectSLE(Json::Value& jv, SLE const& sle)
|
injectSLE(Json::Value& jv, SLE const& sle)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -86,10 +86,6 @@ lookupLedger (std::shared_ptr<ReadView const>&, Context&, Json::Value& result);
|
|||||||
hash_set <AccountID>
|
hash_set <AccountID>
|
||||||
parseAccountIds(Json::Value const& jvArray);
|
parseAccountIds(Json::Value const& jvArray);
|
||||||
|
|
||||||
void
|
|
||||||
addPaymentDeliveredAmount(Json::Value&, Context&,
|
|
||||||
std::shared_ptr<Transaction>, TxMeta::pointer);
|
|
||||||
|
|
||||||
/** Inject JSON describing ledger entry
|
/** Inject JSON describing ledger entry
|
||||||
|
|
||||||
Effects:
|
Effects:
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#include <ripple/rpc/handlers/ValidatorListSites.cpp>
|
#include <ripple/rpc/handlers/ValidatorListSites.cpp>
|
||||||
#include <ripple/rpc/handlers/WalletPropose.cpp>
|
#include <ripple/rpc/handlers/WalletPropose.cpp>
|
||||||
|
|
||||||
|
#include <ripple/rpc/impl/DeliveredAmount.cpp>
|
||||||
#include <ripple/rpc/impl/Handler.cpp>
|
#include <ripple/rpc/impl/Handler.cpp>
|
||||||
#include <ripple/rpc/impl/LegacyPathFind.cpp>
|
#include <ripple/rpc/impl/LegacyPathFind.cpp>
|
||||||
#include <ripple/rpc/impl/Role.cpp>
|
#include <ripple/rpc/impl/Role.cpp>
|
||||||
|
|||||||
341
src/test/rpc/DeliveredAmount_test.cpp
Normal file
341
src/test/rpc/DeliveredAmount_test.cpp
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2019 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 <ripple/beast/unit_test.h>
|
||||||
|
#include <ripple/protocol/Feature.h>
|
||||||
|
#include <ripple/protocol/JsonFields.h>
|
||||||
|
#include <test/jtx.h>
|
||||||
|
#include <test/jtx/WSClient.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
// Helper class to track the expected number `delivered_amount` results.
|
||||||
|
class CheckDeliveredAmount
|
||||||
|
{
|
||||||
|
// If the test occurs before or after the switch time
|
||||||
|
bool afterSwitchTime_;
|
||||||
|
// number of payments expected 'delivered_amount' available
|
||||||
|
int numExpectedAvailable_ = 0;
|
||||||
|
// Number of payments with field with `delivered_amount` set to the
|
||||||
|
// string "unavailable"
|
||||||
|
int numExpectedSetUnavailable_ = 0;
|
||||||
|
// Number of payments with no `delivered_amount` field
|
||||||
|
int numExpectedNotSet_ = 0;
|
||||||
|
|
||||||
|
// Increment one of the expected numExpected{Available_, Unavailable_, NotSet_} values.
|
||||||
|
// Which value to increment depends on:
|
||||||
|
// 1) If the ledger is before or after the switch time
|
||||||
|
// 2) If the tx is a partial payment
|
||||||
|
// 3) If the payment is successful or not
|
||||||
|
void
|
||||||
|
adjCounters(bool success, bool partial)
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
++numExpectedNotSet_;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!afterSwitchTime_)
|
||||||
|
{
|
||||||
|
if (partial)
|
||||||
|
++numExpectedAvailable_;
|
||||||
|
else
|
||||||
|
++numExpectedSetUnavailable_;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// normal case: after switch time & successful transaction
|
||||||
|
++numExpectedAvailable_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CheckDeliveredAmount(bool afterSwitchTime)
|
||||||
|
: afterSwitchTime_(afterSwitchTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
adjCountersSuccess()
|
||||||
|
{
|
||||||
|
adjCounters(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
adjCountersFail()
|
||||||
|
{
|
||||||
|
adjCounters(false, false);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
adjCountersPartialPayment()
|
||||||
|
{
|
||||||
|
adjCounters(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After all the txns are checked, all the `numExpected` variables should be
|
||||||
|
// zero. The `checkTxn` function decrements these variables.
|
||||||
|
bool
|
||||||
|
checkExpectedCounters() const
|
||||||
|
{
|
||||||
|
return !numExpectedAvailable_ && !numExpectedNotSet_ &&
|
||||||
|
!numExpectedSetUnavailable_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the transaction has `delivered_amount` in the metaData as
|
||||||
|
// expected from our rules. Decrements the appropriate `numExpected`
|
||||||
|
// variable. After all the txns are checked, all the `numExpected` variables
|
||||||
|
// should be zero.
|
||||||
|
bool
|
||||||
|
checkTxn(Json::Value const& t, Json::Value const& metaData)
|
||||||
|
{
|
||||||
|
if (t[jss::TransactionType].asString() != "Payment")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool isSet = metaData.isMember(jss::delivered_amount);
|
||||||
|
bool isSetUnavailable = false;
|
||||||
|
bool isSetAvailable = false;
|
||||||
|
if (isSet)
|
||||||
|
{
|
||||||
|
if (metaData[jss::delivered_amount] != "unavailable")
|
||||||
|
isSetAvailable = true;
|
||||||
|
else
|
||||||
|
isSetUnavailable = true;
|
||||||
|
}
|
||||||
|
if (isSetAvailable)
|
||||||
|
--numExpectedAvailable_;
|
||||||
|
else if (isSetUnavailable)
|
||||||
|
--numExpectedSetUnavailable_;
|
||||||
|
else if (!isSet)
|
||||||
|
--numExpectedNotSet_;
|
||||||
|
|
||||||
|
if (isSet)
|
||||||
|
{
|
||||||
|
if (metaData.isMember(sfDeliveredAmount.jsonName))
|
||||||
|
{
|
||||||
|
if (metaData[jss::delivered_amount] !=
|
||||||
|
metaData[sfDeliveredAmount.jsonName])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (afterSwitchTime_)
|
||||||
|
{
|
||||||
|
if (metaData[jss::delivered_amount] != t[jss::Amount])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (metaData[jss::delivered_amount] != "unavailable")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metaData[sfTransactionResult.jsonName] != "tesSUCCESS")
|
||||||
|
{
|
||||||
|
if (isSet)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (afterSwitchTime_)
|
||||||
|
{
|
||||||
|
if (!isSetAvailable)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (metaData.isMember(sfDeliveredAmount.jsonName))
|
||||||
|
{
|
||||||
|
if (!isSetAvailable)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isSetUnavailable)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DeliveredAmount_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
void
|
||||||
|
testAccountDeliveredAmountSubscribe()
|
||||||
|
{
|
||||||
|
testcase("Ledger Request Subscribe DeliveredAmount");
|
||||||
|
|
||||||
|
using namespace test::jtx;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
Account const alice("alice");
|
||||||
|
Account const bob("bob");
|
||||||
|
Account const carol("carol");
|
||||||
|
auto const gw = Account("gateway");
|
||||||
|
auto const USD = gw["USD"];
|
||||||
|
|
||||||
|
for (bool const afterSwitchTime : {true, false})
|
||||||
|
{
|
||||||
|
Env env{*this};
|
||||||
|
env.fund(XRP(10000), alice, bob, carol, gw);
|
||||||
|
env.trust(USD(1000), alice, bob, carol);
|
||||||
|
if (afterSwitchTime)
|
||||||
|
env.close(NetClock::time_point{446000000s});
|
||||||
|
else
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
CheckDeliveredAmount checkDeliveredAmount{afterSwitchTime};
|
||||||
|
{
|
||||||
|
// add payments, but do no close until subscribed
|
||||||
|
|
||||||
|
// normal payments
|
||||||
|
env(pay(gw, alice, USD(50)));
|
||||||
|
checkDeliveredAmount.adjCountersSuccess();
|
||||||
|
env(pay(gw, alice, XRP(50)));
|
||||||
|
checkDeliveredAmount.adjCountersSuccess();
|
||||||
|
|
||||||
|
// partial payment
|
||||||
|
env(pay(gw, bob, USD(9999999)), txflags(tfPartialPayment));
|
||||||
|
checkDeliveredAmount.adjCountersPartialPayment();
|
||||||
|
env.require(balance(bob, USD(1000)));
|
||||||
|
|
||||||
|
// failed payment
|
||||||
|
env(pay(bob, carol, USD(9999999)), ter(tecPATH_PARTIAL));
|
||||||
|
checkDeliveredAmount.adjCountersFail();
|
||||||
|
env.require(balance(carol, USD(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto wsc = makeWSClient(env.app().config());
|
||||||
|
|
||||||
|
{
|
||||||
|
Json::Value stream;
|
||||||
|
// RPC subscribe to ledger stream
|
||||||
|
stream[jss::streams] = Json::arrayValue;
|
||||||
|
stream[jss::streams].append("ledger");
|
||||||
|
stream[jss::accounts] = Json::arrayValue;
|
||||||
|
stream[jss::accounts].append(toBase58(alice.id()));
|
||||||
|
stream[jss::accounts].append(toBase58(bob.id()));
|
||||||
|
stream[jss::accounts].append(toBase58(carol.id()));
|
||||||
|
auto jv = wsc->invoke("subscribe", stream);
|
||||||
|
if (wsc->version() == 2)
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(
|
||||||
|
jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||||
|
BEAST_EXPECT(
|
||||||
|
jv.isMember(jss::ripplerpc) &&
|
||||||
|
jv[jss::ripplerpc] == "2.0");
|
||||||
|
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||||
|
}
|
||||||
|
BEAST_EXPECT(jv[jss::result][jss::ledger_index] == 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
env.close();
|
||||||
|
// Check stream update
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto const r = wsc->findMsg(1s, [&](auto const& jv) {
|
||||||
|
return jv[jss::ledger_index] == 4;
|
||||||
|
});
|
||||||
|
if (!r)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!r->isMember(jss::transaction))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BEAST_EXPECT(checkDeliveredAmount.checkTxn(
|
||||||
|
(*r)[jss::transaction], (*r)[jss::meta]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BEAST_EXPECT(checkDeliveredAmount.checkExpectedCounters());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void
|
||||||
|
testTxDeliveredAmountRPC()
|
||||||
|
{
|
||||||
|
testcase("Ledger Request RPC DeliveredAmount");
|
||||||
|
|
||||||
|
using namespace test::jtx;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
Account const alice("alice");
|
||||||
|
Account const bob("bob");
|
||||||
|
Account const carol("carol");
|
||||||
|
auto const gw = Account("gateway");
|
||||||
|
auto const USD = gw["USD"];
|
||||||
|
|
||||||
|
for (bool const afterSwitchTime : {true, false})
|
||||||
|
{
|
||||||
|
Env env{*this};
|
||||||
|
env.fund(XRP(10000), alice, bob, carol, gw);
|
||||||
|
env.trust(USD(1000), alice, bob, carol);
|
||||||
|
if (afterSwitchTime)
|
||||||
|
env.close(NetClock::time_point{446000000s});
|
||||||
|
else
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
CheckDeliveredAmount checkDeliveredAmount{afterSwitchTime};
|
||||||
|
// normal payments
|
||||||
|
env(pay(gw, alice, USD(50)));
|
||||||
|
checkDeliveredAmount.adjCountersSuccess();
|
||||||
|
env(pay(gw, alice, XRP(50)));
|
||||||
|
checkDeliveredAmount.adjCountersSuccess();
|
||||||
|
|
||||||
|
// partial payment
|
||||||
|
env(pay(gw, bob, USD(9999999)), txflags(tfPartialPayment));
|
||||||
|
checkDeliveredAmount.adjCountersPartialPayment();
|
||||||
|
env.require(balance(bob, USD(1000)));
|
||||||
|
|
||||||
|
// failed payment
|
||||||
|
env(pay(gw, carol, USD(9999999)), ter(tecPATH_PARTIAL));
|
||||||
|
checkDeliveredAmount.adjCountersFail();
|
||||||
|
env.require(balance(carol, USD(0)));
|
||||||
|
|
||||||
|
env.close();
|
||||||
|
std::string index;
|
||||||
|
Json::Value jvParams;
|
||||||
|
jvParams[jss::ledger_index] = 4u;
|
||||||
|
jvParams[jss::transactions] = true;
|
||||||
|
jvParams[jss::expand] = true;
|
||||||
|
auto const jtxn = env.rpc(
|
||||||
|
"json",
|
||||||
|
"ledger",
|
||||||
|
to_string(
|
||||||
|
jvParams))[jss::result][jss::ledger][jss::transactions];
|
||||||
|
for (auto const& t : jtxn)
|
||||||
|
BEAST_EXPECT(
|
||||||
|
checkDeliveredAmount.checkTxn(t, t[jss::metaData]));
|
||||||
|
BEAST_EXPECT(checkDeliveredAmount.checkExpectedCounters());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
testTxDeliveredAmountRPC();
|
||||||
|
testAccountDeliveredAmountSubscribe();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(DeliveredAmount, app, ripple);
|
||||||
|
|
||||||
|
} // namespace test
|
||||||
|
} // namespace ripple
|
||||||
@@ -651,6 +651,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
testServer();
|
testServer();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <test/rpc/AmendmentBlocked_test.cpp>
|
#include <test/rpc/AmendmentBlocked_test.cpp>
|
||||||
#include <test/rpc/Book_test.cpp>
|
#include <test/rpc/Book_test.cpp>
|
||||||
#include <test/rpc/DepositAuthorized_test.cpp>
|
#include <test/rpc/DepositAuthorized_test.cpp>
|
||||||
|
#include <test/rpc/DeliveredAmount_test.cpp>
|
||||||
#include <test/rpc/Feature_test.cpp>
|
#include <test/rpc/Feature_test.cpp>
|
||||||
#include <test/rpc/GatewayBalances_test.cpp>
|
#include <test/rpc/GatewayBalances_test.cpp>
|
||||||
#include <test/rpc/GetCounts_test.cpp>
|
#include <test/rpc/GetCounts_test.cpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user