mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-20 11:45:53 +00:00
ledger rpc accepts more flags. binary options for all rpcs. tests to verify ledger and account_info
This commit is contained in:
@@ -56,6 +56,8 @@ doAccountInfo(
|
|||||||
response["error"] = "missing account field";
|
response["error"] = "missing account field";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
bool binary =
|
||||||
|
request.contains("binary") ? request.at("binary").as_bool() : false;
|
||||||
auto ledgerSequence = ledgerSequenceFromRequest(request, backend);
|
auto ledgerSequence = ledgerSequenceFromRequest(request, backend);
|
||||||
if (!ledgerSequence)
|
if (!ledgerSequence)
|
||||||
{
|
{
|
||||||
@@ -98,7 +100,10 @@ doAccountInfo(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
response["success"] = "fetched successfully!";
|
response["success"] = "fetched successfully!";
|
||||||
response["object"] = getJson(sle);
|
if (!binary)
|
||||||
|
response["object"] = getJson(sle);
|
||||||
|
else
|
||||||
|
response["object"] = ripple::strHex(*dbResponse);
|
||||||
response["db_time"] = time;
|
response["db_time"] = time;
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ doAccountTx(boost::json::object const& request, BackendInterface const& backend)
|
|||||||
response["error"] = "account malformed";
|
response["error"] = "account malformed";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
bool binary =
|
||||||
|
request.contains("binary") ? request.at("binary").as_bool() : false;
|
||||||
|
|
||||||
std::optional<Backend::AccountTransactionsCursor> cursor;
|
std::optional<Backend::AccountTransactionsCursor> cursor;
|
||||||
if (request.contains("cursor"))
|
if (request.contains("cursor"))
|
||||||
@@ -179,9 +181,18 @@ doAccountTx(boost::json::object const& request, BackendInterface const& backend)
|
|||||||
for (auto const& txnPlusMeta : blobs)
|
for (auto const& txnPlusMeta : blobs)
|
||||||
{
|
{
|
||||||
boost::json::object obj;
|
boost::json::object obj;
|
||||||
auto [txn, meta] = deserializeTxPlusMeta(txnPlusMeta);
|
if (!binary)
|
||||||
obj["transaction"] = getJson(*txn);
|
{
|
||||||
obj["metadata"] = getJson(*meta);
|
auto [txn, meta] = deserializeTxPlusMeta(txnPlusMeta);
|
||||||
|
obj["transaction"] = getJson(*txn);
|
||||||
|
obj["metadata"] = getJson(*meta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj["transaction"] = ripple::strHex(txnPlusMeta.transaction);
|
||||||
|
obj["metadata"] = ripple::strHex(txnPlusMeta.metadata);
|
||||||
|
}
|
||||||
|
obj["ledger_sequence"] = txnPlusMeta.ledgerSequence;
|
||||||
txns.push_back(obj);
|
txns.push_back(obj);
|
||||||
}
|
}
|
||||||
response["transactions"] = txns;
|
response["transactions"] = txns;
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
#include <handlers/RPCHelpers.h>
|
#include <handlers/RPCHelpers.h>
|
||||||
#include <reporting/BackendInterface.h>
|
#include <reporting/BackendInterface.h>
|
||||||
|
std::vector<unsigned char>
|
||||||
|
ledgerInfoToBlob(ripple::LedgerInfo const& info)
|
||||||
|
{
|
||||||
|
ripple::Serializer s;
|
||||||
|
s.add32(info.seq);
|
||||||
|
s.add64(info.drops.drops());
|
||||||
|
s.addBitString(info.parentHash);
|
||||||
|
s.addBitString(info.txHash);
|
||||||
|
s.addBitString(info.accountHash);
|
||||||
|
s.add32(info.parentCloseTime.time_since_epoch().count());
|
||||||
|
s.add32(info.closeTime.time_since_epoch().count());
|
||||||
|
s.add8(info.closeTimeResolution.count());
|
||||||
|
s.add8(info.closeFlags);
|
||||||
|
// s.addBitString(info.hash);
|
||||||
|
return s.peekData();
|
||||||
|
}
|
||||||
|
|
||||||
boost::json::object
|
boost::json::object
|
||||||
doLedger(boost::json::object const& request, BackendInterface const& backend)
|
doLedger(boost::json::object const& request, BackendInterface const& backend)
|
||||||
@@ -10,6 +26,13 @@ doLedger(boost::json::object const& request, BackendInterface const& backend)
|
|||||||
response["error"] = "Please specify a ledger index";
|
response["error"] = "Please specify a ledger index";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
bool binary =
|
||||||
|
request.contains("binary") ? request.at("binary").as_bool() : false;
|
||||||
|
bool getTransactions = request.contains("transactions")
|
||||||
|
? request.at("transactions").as_bool()
|
||||||
|
: false;
|
||||||
|
bool expand =
|
||||||
|
request.contains("expand") ? request.at("expand").as_bool() : false;
|
||||||
auto ledgerSequence = ledgerSequenceFromRequest(request, backend);
|
auto ledgerSequence = ledgerSequenceFromRequest(request, backend);
|
||||||
if (!ledgerSequence)
|
if (!ledgerSequence)
|
||||||
{
|
{
|
||||||
@@ -24,35 +47,71 @@ doLedger(boost::json::object const& request, BackendInterface const& backend)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
boost::json::object header;
|
boost::json::object header;
|
||||||
header["ledger_sequence"] = lgrInfo->seq;
|
if (binary)
|
||||||
header["ledger_hash"] = ripple::strHex(lgrInfo->hash);
|
{
|
||||||
header["txns_hash"] = ripple::strHex(lgrInfo->txHash);
|
header["blob"] = ripple::strHex(ledgerInfoToBlob(*lgrInfo));
|
||||||
header["state_hash"] = ripple::strHex(lgrInfo->accountHash);
|
}
|
||||||
header["parent_hash"] = ripple::strHex(lgrInfo->parentHash);
|
else
|
||||||
header["total_coins"] = ripple::to_string(lgrInfo->drops);
|
{
|
||||||
header["close_flags"] = lgrInfo->closeFlags;
|
header["ledger_sequence"] = lgrInfo->seq;
|
||||||
|
header["ledger_hash"] = ripple::strHex(lgrInfo->hash);
|
||||||
|
header["txns_hash"] = ripple::strHex(lgrInfo->txHash);
|
||||||
|
header["state_hash"] = ripple::strHex(lgrInfo->accountHash);
|
||||||
|
header["parent_hash"] = ripple::strHex(lgrInfo->parentHash);
|
||||||
|
header["total_coins"] = ripple::to_string(lgrInfo->drops);
|
||||||
|
header["close_flags"] = lgrInfo->closeFlags;
|
||||||
|
|
||||||
// Always show fields that contribute to the ledger hash
|
// Always show fields that contribute to the ledger hash
|
||||||
header["parent_close_time"] =
|
header["parent_close_time"] =
|
||||||
lgrInfo->parentCloseTime.time_since_epoch().count();
|
lgrInfo->parentCloseTime.time_since_epoch().count();
|
||||||
header["close_time"] = lgrInfo->closeTime.time_since_epoch().count();
|
header["close_time"] = lgrInfo->closeTime.time_since_epoch().count();
|
||||||
header["close_time_resolution"] = lgrInfo->closeTimeResolution.count();
|
header["close_time_resolution"] = lgrInfo->closeTimeResolution.count();
|
||||||
auto txns = backend.fetchAllTransactionsInLedger(*ledgerSequence);
|
}
|
||||||
response["transactions"] = boost::json::value(boost::json::array_kind);
|
response["header"] = header;
|
||||||
boost::json::array& jsonTransactions =
|
if (getTransactions)
|
||||||
response.at("transactions").as_array();
|
{
|
||||||
|
response["transactions"] = boost::json::value(boost::json::array_kind);
|
||||||
std::transform(
|
boost::json::array& jsonTransactions =
|
||||||
std::move_iterator(txns.begin()),
|
response.at("transactions").as_array();
|
||||||
std::move_iterator(txns.end()),
|
if (expand)
|
||||||
std::back_inserter(jsonTransactions),
|
{
|
||||||
[](auto obj) {
|
auto txns = backend.fetchAllTransactionsInLedger(*ledgerSequence);
|
||||||
boost::json::object entry;
|
|
||||||
auto [sttx, meta] = deserializeTxPlusMeta(obj);
|
|
||||||
entry["transaction"] = getJson(*sttx);
|
|
||||||
entry["meta"] = getJson(*meta);
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
std::transform(
|
||||||
|
std::move_iterator(txns.begin()),
|
||||||
|
std::move_iterator(txns.end()),
|
||||||
|
std::back_inserter(jsonTransactions),
|
||||||
|
[binary](auto obj) {
|
||||||
|
boost::json::object entry;
|
||||||
|
if (!binary)
|
||||||
|
{
|
||||||
|
auto [sttx, meta] = deserializeTxPlusMeta(obj);
|
||||||
|
entry["transaction"] = getJson(*sttx);
|
||||||
|
entry["metadata"] = getJson(*meta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry["transaction"] = ripple::strHex(obj.transaction);
|
||||||
|
entry["metadata"] = ripple::strHex(obj.metadata);
|
||||||
|
}
|
||||||
|
entry["ledger_sequence"] = obj.ledgerSequence;
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto hashes =
|
||||||
|
backend.fetchAllTransactionHashesInLedger(*ledgerSequence);
|
||||||
|
std::transform(
|
||||||
|
std::move_iterator(hashes.begin()),
|
||||||
|
std::move_iterator(hashes.end()),
|
||||||
|
std::back_inserter(jsonTransactions),
|
||||||
|
[](auto hash) {
|
||||||
|
boost::json::object entry;
|
||||||
|
entry["hash"] = ripple::strHex(hash);
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,9 +58,20 @@ doTx(boost::json::object const& request, BackendInterface const& backend)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [sttx, meta] = deserializeTxPlusMeta(dbResponse.value());
|
bool binary =
|
||||||
response["transaction"] = getJson(*sttx);
|
request.contains("binary") ? request.at("binary").as_bool() : false;
|
||||||
response["meta"] = getJson(*meta);
|
if (!binary)
|
||||||
|
{
|
||||||
|
auto [sttx, meta] = deserializeTxPlusMeta(dbResponse.value());
|
||||||
|
response["transaction"] = getJson(*sttx);
|
||||||
|
response["metadata"] = getJson(*meta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response["transaction"] = ripple::strHex(dbResponse->transaction);
|
||||||
|
response["metadata"] = ripple::strHex(dbResponse->metadata);
|
||||||
|
}
|
||||||
|
response["ledger_sequence"] = dbResponse->ledgerSequence;
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ struct TransactionAndMetadata
|
|||||||
{
|
{
|
||||||
Blob transaction;
|
Blob transaction;
|
||||||
Blob metadata;
|
Blob metadata;
|
||||||
|
uint32_t ledgerSequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AccountTransactionsCursor
|
struct AccountTransactionsCursor
|
||||||
@@ -57,6 +58,9 @@ public:
|
|||||||
virtual std::vector<TransactionAndMetadata>
|
virtual std::vector<TransactionAndMetadata>
|
||||||
fetchAllTransactionsInLedger(uint32_t ledgerSequence) const = 0;
|
fetchAllTransactionsInLedger(uint32_t ledgerSequence) const = 0;
|
||||||
|
|
||||||
|
virtual std::vector<ripple::uint256>
|
||||||
|
fetchAllTransactionHashesInLedger(uint32_t ledgerSequence) const = 0;
|
||||||
|
|
||||||
virtual LedgerPage
|
virtual LedgerPage
|
||||||
fetchLedgerPage(
|
fetchLedgerPage(
|
||||||
std::optional<ripple::uint256> const& cursor,
|
std::optional<ripple::uint256> const& cursor,
|
||||||
|
|||||||
@@ -178,7 +178,8 @@ flatMapReadCallback(CassFuture* fut, void* cbData)
|
|||||||
|
|
||||||
if (!!result)
|
if (!!result)
|
||||||
{
|
{
|
||||||
requestParams.result = {result.getBytes(), result.getBytes()};
|
requestParams.result = {
|
||||||
|
result.getBytes(), result.getBytes(), result.getUInt32()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,10 +240,30 @@ CassandraBackend::fetchAllTransactionsInLedger(uint32_t ledgerSequence) const
|
|||||||
std::vector<TransactionAndMetadata> txns;
|
std::vector<TransactionAndMetadata> txns;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
txns.push_back({result.getBytes(), result.getBytes()});
|
txns.push_back(
|
||||||
|
{result.getBytes(), result.getBytes(), result.getUInt32()});
|
||||||
} while (result.nextRow());
|
} while (result.nextRow());
|
||||||
return txns;
|
return txns;
|
||||||
}
|
}
|
||||||
|
std::vector<ripple::uint256>
|
||||||
|
CassandraBackend::fetchAllTransactionHashesInLedger(
|
||||||
|
uint32_t ledgerSequence) const
|
||||||
|
{
|
||||||
|
CassandraStatement statement{selectAllTransactionHashesInLedger_};
|
||||||
|
statement.bindInt(ledgerSequence);
|
||||||
|
CassandraResult result = executeSyncRead(statement);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << __func__ << " - no rows";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<ripple::uint256> hashes;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
hashes.push_back(result.getUInt256());
|
||||||
|
} while (result.nextRow());
|
||||||
|
return hashes;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CassandraBackend::open()
|
CassandraBackend::open()
|
||||||
@@ -622,19 +643,25 @@ CassandraBackend::open()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
query = {};
|
query = {};
|
||||||
query << "SELECT transaction,metadata FROM " << tablePrefix
|
query << "SELECT transaction, metadata, ledger_sequence FROM "
|
||||||
<< "transactions"
|
<< tablePrefix << "transactions"
|
||||||
<< " WHERE hash = ?";
|
<< " WHERE hash = ?";
|
||||||
if (!selectTransaction_.prepareStatement(query, session_.get()))
|
if (!selectTransaction_.prepareStatement(query, session_.get()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
query = {};
|
query = {};
|
||||||
query << "SELECT transaction,metadata FROM " << tablePrefix
|
query << "SELECT transaction, metadata, ledger_sequence FROM "
|
||||||
<< "transactions"
|
<< tablePrefix << "transactions"
|
||||||
<< " WHERE ledger_sequence = ?";
|
<< " WHERE ledger_sequence = ?";
|
||||||
if (!selectAllTransactionsInLedger_.prepareStatement(
|
if (!selectAllTransactionsInLedger_.prepareStatement(
|
||||||
query, session_.get()))
|
query, session_.get()))
|
||||||
continue;
|
continue;
|
||||||
|
query = {};
|
||||||
|
query << "SELECT hash FROM " << tablePrefix << "transactions"
|
||||||
|
<< " WHERE ledger_sequence = ?";
|
||||||
|
if (!selectAllTransactionHashesInLedger_.prepareStatement(
|
||||||
|
query, session_.get()))
|
||||||
|
continue;
|
||||||
|
|
||||||
query = {};
|
query = {};
|
||||||
query << "SELECT key FROM " << tablePrefix << "keys "
|
query << "SELECT key FROM " << tablePrefix << "keys "
|
||||||
|
|||||||
@@ -542,6 +542,7 @@ private:
|
|||||||
CassandraPreparedStatement insertTransaction_;
|
CassandraPreparedStatement insertTransaction_;
|
||||||
CassandraPreparedStatement selectTransaction_;
|
CassandraPreparedStatement selectTransaction_;
|
||||||
CassandraPreparedStatement selectAllTransactionsInLedger_;
|
CassandraPreparedStatement selectAllTransactionsInLedger_;
|
||||||
|
CassandraPreparedStatement selectAllTransactionHashesInLedger_;
|
||||||
CassandraPreparedStatement selectObject_;
|
CassandraPreparedStatement selectObject_;
|
||||||
CassandraPreparedStatement selectLedgerPageKeys_;
|
CassandraPreparedStatement selectLedgerPageKeys_;
|
||||||
CassandraPreparedStatement selectLedgerPage_;
|
CassandraPreparedStatement selectLedgerPage_;
|
||||||
@@ -806,6 +807,9 @@ public:
|
|||||||
std::vector<TransactionAndMetadata>
|
std::vector<TransactionAndMetadata>
|
||||||
fetchAllTransactionsInLedger(uint32_t ledgerSequence) const override;
|
fetchAllTransactionsInLedger(uint32_t ledgerSequence) const override;
|
||||||
|
|
||||||
|
std::vector<ripple::uint256>
|
||||||
|
fetchAllTransactionHashesInLedger(uint32_t ledgerSequence) const override;
|
||||||
|
|
||||||
// Synchronously fetch the object with key key and store the result in
|
// Synchronously fetch the object with key key and store the result in
|
||||||
// pno
|
// pno
|
||||||
// @param key the key of the object
|
// @param key the key of the object
|
||||||
@@ -859,7 +863,7 @@ public:
|
|||||||
BOOST_LOG_TRIVIAL(error) << __func__ << " - no rows";
|
BOOST_LOG_TRIVIAL(error) << __func__ << " - no rows";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return {{result.getBytes(), result.getBytes()}};
|
return {{result.getBytes(), result.getBytes(), result.getUInt32()}};
|
||||||
}
|
}
|
||||||
LedgerPage
|
LedgerPage
|
||||||
fetchLedgerPage2(
|
fetchLedgerPage2(
|
||||||
@@ -1212,8 +1216,8 @@ public:
|
|||||||
, isDeleted(isDeleted)
|
, isDeleted(isDeleted)
|
||||||
, book(std::move(book))
|
, book(std::move(book))
|
||||||
{
|
{
|
||||||
if (isCreated or isDeleted)
|
// if (isCreated or isDeleted)
|
||||||
++refs;
|
// ++refs;
|
||||||
if (book)
|
if (book)
|
||||||
++refs;
|
++refs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,10 @@ PostgresBackend::fetchTransaction(ripple::uint256 const& hash) const
|
|||||||
auto res = pgQuery(sql.str().data());
|
auto res = pgQuery(sql.str().data());
|
||||||
if (checkResult(res, 3))
|
if (checkResult(res, 3))
|
||||||
{
|
{
|
||||||
return {{res.asUnHexedBlob(0, 0), res.asUnHexedBlob(0, 1)}};
|
return {
|
||||||
|
{res.asUnHexedBlob(0, 0),
|
||||||
|
res.asUnHexedBlob(0, 1),
|
||||||
|
res.asBigInt(0, 2)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@@ -281,12 +284,35 @@ PostgresBackend::fetchAllTransactionsInLedger(uint32_t ledgerSequence) const
|
|||||||
std::vector<TransactionAndMetadata> txns;
|
std::vector<TransactionAndMetadata> txns;
|
||||||
for (size_t i = 0; i < numRows; ++i)
|
for (size_t i = 0; i < numRows; ++i)
|
||||||
{
|
{
|
||||||
txns.push_back({res.asUnHexedBlob(i, 0), res.asUnHexedBlob(i, 1)});
|
txns.push_back(
|
||||||
|
{res.asUnHexedBlob(i, 0),
|
||||||
|
res.asUnHexedBlob(i, 1),
|
||||||
|
res.asBigInt(i, 2)});
|
||||||
}
|
}
|
||||||
return txns;
|
return txns;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
std::vector<ripple::uint256>
|
||||||
|
PostgresBackend::fetchAllTransactionHashesInLedger(
|
||||||
|
uint32_t ledgerSequence) const
|
||||||
|
{
|
||||||
|
PgQuery pgQuery(pgPool_);
|
||||||
|
std::stringstream sql;
|
||||||
|
sql << "SELECT hash FROM transactions WHERE "
|
||||||
|
<< "ledger_seq = " << std::to_string(ledgerSequence);
|
||||||
|
auto res = pgQuery(sql.str().data());
|
||||||
|
if (size_t numRows = checkResult(res, 3))
|
||||||
|
{
|
||||||
|
std::vector<ripple::uint256> hashes;
|
||||||
|
for (size_t i = 0; i < numRows; ++i)
|
||||||
|
{
|
||||||
|
hashes.push_back(res.asUInt256(i, 0));
|
||||||
|
}
|
||||||
|
return hashes;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
LedgerPage
|
LedgerPage
|
||||||
PostgresBackend::fetchLedgerPage(
|
PostgresBackend::fetchLedgerPage(
|
||||||
@@ -384,7 +410,9 @@ PostgresBackend::fetchTransactions(
|
|||||||
for (size_t i = 0; i < numRows; ++i)
|
for (size_t i = 0; i < numRows; ++i)
|
||||||
{
|
{
|
||||||
results.push_back(
|
results.push_back(
|
||||||
{res.asUnHexedBlob(i, 0), res.asUnHexedBlob(i, 1)});
|
{res.asUnHexedBlob(i, 0),
|
||||||
|
res.asUnHexedBlob(i, 1),
|
||||||
|
res.asBigInt(i, 2)});
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ public:
|
|||||||
std::vector<TransactionAndMetadata>
|
std::vector<TransactionAndMetadata>
|
||||||
fetchAllTransactionsInLedger(uint32_t ledgerSequence) const override;
|
fetchAllTransactionsInLedger(uint32_t ledgerSequence) const override;
|
||||||
|
|
||||||
|
std::vector<ripple::uint256>
|
||||||
|
fetchAllTransactionHashesInLedger(uint32_t ledgerSequence) const override;
|
||||||
|
|
||||||
LedgerPage
|
LedgerPage
|
||||||
fetchLedgerPage(
|
fetchLedgerPage(
|
||||||
std::optional<ripple::uint256> const& cursor,
|
std::optional<ripple::uint256> const& cursor,
|
||||||
|
|||||||
@@ -643,5 +643,7 @@ ReportingETL::ReportingETL(
|
|||||||
ioc)
|
ioc)
|
||||||
{
|
{
|
||||||
flatMapBackend_->open();
|
flatMapBackend_->open();
|
||||||
|
if (config.contains("start_sequence"))
|
||||||
|
startSequence_ = config.at("start_sequence").as_int64();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
163
test.py
163
test.py
@@ -10,55 +10,81 @@ import argparse
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
def checkAccountInfo(aldous, p2p):
|
||||||
|
return isSubset(aldous["object"], p2p["result"]["account_data"])
|
||||||
|
|
||||||
|
def isSubset(sub, sup):
|
||||||
|
for x in sub:
|
||||||
|
if x == "deserialization_time_microsecond":
|
||||||
|
continue
|
||||||
|
if not x in sup:
|
||||||
|
return False
|
||||||
|
elif not sub[x] == sup[x]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def account_info(ip, port, account, ledger):
|
def compareAccountInfo(aldous, p2p):
|
||||||
|
p2p = p2p["result"]["account_data"]
|
||||||
|
aldous = aldous["object"]
|
||||||
|
if isSubset(p2p,aldous):
|
||||||
|
print("Responses match!!")
|
||||||
|
else:
|
||||||
|
print("Response mismatch")
|
||||||
|
print(aldous)
|
||||||
|
print(p2p)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async def account_info(ip, port, account, ledger, binary):
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
|
print(binary)
|
||||||
try:
|
try:
|
||||||
async with websockets.connect(address) as ws:
|
async with websockets.connect(address) as ws:
|
||||||
if ledger is None:
|
if ledger is None:
|
||||||
await ws.send(json.dumps({"command":"account_info","account":account}))
|
await ws.send(json.dumps({"command":"account_info","account":account, "binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
else:
|
else:
|
||||||
await ws.send(json.dumps({"command":"account_info","account":account, "ledger_index":int(ledger)}))
|
await ws.send(json.dumps({"command":"account_info","account":account, "ledger_index":int(ledger), "binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
|
return res
|
||||||
except websockets.exceptions.ConnectionClosedError as e:
|
except websockets.exceptions.ConnectionClosedError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
async def account_tx(ip, port, account):
|
async def account_tx(ip, port, account, binary):
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
try:
|
try:
|
||||||
async with websockets.connect(address) as ws:
|
async with websockets.connect(address) as ws:
|
||||||
await ws.send(json.dumps({"command":"account_tx","account":account}))
|
await ws.send(json.dumps({"command":"account_tx","account":account, "binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
except websockets.exceptions.ConnectionClosedError as e:
|
except websockets.exceptions.ConnectionClosedError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
async def tx(ip, port, tx_hash):
|
async def tx(ip, port, tx_hash, binary):
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
try:
|
try:
|
||||||
async with websockets.connect(address) as ws:
|
async with websockets.connect(address) as ws:
|
||||||
await ws.send(json.dumps({"command":"tx","transaction":tx_hash}))
|
await ws.send(json.dumps({"command":"tx","transaction":tx_hash,"binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
except websockets.exceptions.connectionclosederror as e:
|
except websockets.exceptions.connectionclosederror as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
async def ledger_data(ip, port, ledger, limit):
|
async def ledger_data(ip, port, ledger, limit, binary):
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
try:
|
try:
|
||||||
async with websockets.connect(address) as ws:
|
async with websockets.connect(address) as ws:
|
||||||
await ws.send(json.dumps({"command":"ledger_data","ledger_index":int(ledger),"binary":True}))
|
await ws.send(json.dumps({"command":"ledger_data","ledger_index":int(ledger),"binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
except websockets.exceptions.connectionclosederror as e:
|
except websockets.exceptions.connectionclosederror as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
async def ledger_data_full(ip, port, ledger):
|
async def ledger_data_full(ip, port, ledger, binary):
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
try:
|
try:
|
||||||
|
|
||||||
@@ -66,12 +92,12 @@ async def ledger_data_full(ip, port, ledger):
|
|||||||
marker = None
|
marker = None
|
||||||
while True:
|
while True:
|
||||||
if marker is None:
|
if marker is None:
|
||||||
await ws.send(json.dumps({"command":"ledger_data","ledger_index":int(ledger),"binary":True}))
|
await ws.send(json.dumps({"command":"ledger_data","ledger_index":int(ledger),"binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
await ws.send(json.dumps({"command":"ledger_data","ledger_index":int(ledger),"cursor":marker, "binary":True}))
|
await ws.send(json.dumps({"command":"ledger_data","ledger_index":int(ledger),"cursor":marker, "binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
|
|
||||||
if "cursor" in res:
|
if "cursor" in res:
|
||||||
@@ -87,7 +113,7 @@ async def ledger_data_full(ip, port, ledger):
|
|||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
async def book_offers(ip, port, ledger, pay_currency, pay_issuer, get_currency, get_issuer):
|
async def book_offers(ip, port, ledger, pay_currency, pay_issuer, get_currency, get_issuer, binary):
|
||||||
|
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
try:
|
try:
|
||||||
@@ -100,23 +126,77 @@ async def book_offers(ip, port, ledger, pay_currency, pay_issuer, get_currency,
|
|||||||
if pay_issuer is not None:
|
if pay_issuer is not None:
|
||||||
taker_pays["issuer"] = pay_issuer
|
taker_pays["issuer"] = pay_issuer
|
||||||
|
|
||||||
await ws.send(json.dumps({"command":"book_offers","ledger_index":int(ledger), "taker_pays":taker_pays, "taker_gets":taker_gets}))
|
await ws.send(json.dumps({"command":"book_offers","ledger_index":int(ledger), "taker_pays":taker_pays, "taker_gets":taker_gets, "binary":bool(binary)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
|
|
||||||
except websockets.exceptions.connectionclosederror as e:
|
except websockets.exceptions.connectionclosederror as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
async def ledger(ip, port, ledger):
|
def compareLedger(aldous, p2p):
|
||||||
|
p2p = p2p["result"]["ledger"]
|
||||||
|
p2pHeader = p2p["ledger_data"]
|
||||||
|
aldousHeader = aldous["header"]["blob"]
|
||||||
|
if p2pHeader == aldousHeader:
|
||||||
|
print("Headers match!!!")
|
||||||
|
else:
|
||||||
|
print("Header mismatch")
|
||||||
|
print(aldousHeader)
|
||||||
|
print(p2pHeader)
|
||||||
|
return
|
||||||
|
|
||||||
|
p2pTxns = []
|
||||||
|
p2pMetas = []
|
||||||
|
for x in p2p["transactions"]:
|
||||||
|
p2pTxns.append(x["tx_blob"])
|
||||||
|
p2pMetas.append(x["meta"])
|
||||||
|
aldousTxns = []
|
||||||
|
aldousMetas = []
|
||||||
|
for x in aldous["transactions"]:
|
||||||
|
aldousTxns.append(x["transaction"])
|
||||||
|
aldousMetas.append(x["metadata"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
p2pTxns.sort()
|
||||||
|
p2pMetas.sort()
|
||||||
|
aldousTxns.sort()
|
||||||
|
aldousMetas.sort()
|
||||||
|
if p2pTxns == aldousTxns and p2pMetas == aldousMetas:
|
||||||
|
print("Responses match!!!")
|
||||||
|
else:
|
||||||
|
print("Mismatch responses")
|
||||||
|
print(aldous)
|
||||||
|
print(p2p)
|
||||||
|
|
||||||
|
|
||||||
|
def getHashes(res):
|
||||||
|
if "result" in res:
|
||||||
|
res = res["result"]["ledger"]
|
||||||
|
|
||||||
|
hashes = []
|
||||||
|
for x in res["transactions"]:
|
||||||
|
if "hash" in x:
|
||||||
|
hashes.append(x["hash"])
|
||||||
|
elif "transaction" in x and "hash" in x["transaction"]:
|
||||||
|
hashes.append(x["transaction"]["hash"])
|
||||||
|
return hashes
|
||||||
|
|
||||||
|
|
||||||
|
async def ledger(ip, port, ledger, binary, transactions, expand):
|
||||||
|
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
|
hashes = []
|
||||||
try:
|
try:
|
||||||
async with websockets.connect(address) as ws:
|
async with websockets.connect(address) as ws:
|
||||||
await ws.send(json.dumps({"command":"ledger","ledger_index":int(ledger)}))
|
await ws.send(json.dumps({"command":"ledger","ledger_index":int(ledger),"binary":bool(binary), "transactions":bool(transactions),"expand":bool(expand)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(res)
|
||||||
|
return res
|
||||||
|
|
||||||
except websockets.exceptions.connectionclosederror as e:
|
except websockets.exceptions.connectionclosederror as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
return hashes
|
||||||
async def ledger_range(ip, port):
|
async def ledger_range(ip, port):
|
||||||
address = 'ws://' + str(ip) + ':' + str(port)
|
address = 'ws://' + str(ip) + ':' + str(port)
|
||||||
try:
|
try:
|
||||||
@@ -124,6 +204,11 @@ async def ledger_range(ip, port):
|
|||||||
await ws.send(json.dumps({"command":"ledger_range"}))
|
await ws.send(json.dumps({"command":"ledger_range"}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(json.dumps(res,indent=4,sort_keys=True))
|
print(json.dumps(res,indent=4,sort_keys=True))
|
||||||
|
if "error" in res:
|
||||||
|
await ws.send(json.dumps({"command":"server_info"}))
|
||||||
|
res = json.loads(await ws.recv())
|
||||||
|
print(res)
|
||||||
|
return res["result"]["info"]["validated_ledger"]["seq"]
|
||||||
return res["ledger_index_max"]
|
return res["ledger_index_max"]
|
||||||
except websockets.exceptions.connectionclosederror as e:
|
except websockets.exceptions.connectionclosederror as e:
|
||||||
print(e)
|
print(e)
|
||||||
@@ -133,13 +218,19 @@ parser.add_argument('action', choices=["account_info", "tx", "account_tx", "ledg
|
|||||||
parser.add_argument('--ip', default='127.0.0.1')
|
parser.add_argument('--ip', default='127.0.0.1')
|
||||||
parser.add_argument('--port', default='8080')
|
parser.add_argument('--port', default='8080')
|
||||||
parser.add_argument('--hash')
|
parser.add_argument('--hash')
|
||||||
parser.add_argument('--account', default="rLC64xxNif3GiY9FQnbaM4kcE6VvDhwRod")
|
parser.add_argument('--account', default="rw2ciyaNshpHe7bCHo4bRWq6pqqynnWKQg")
|
||||||
parser.add_argument('--ledger')
|
parser.add_argument('--ledger')
|
||||||
parser.add_argument('--limit', default='200')
|
parser.add_argument('--limit', default='200')
|
||||||
parser.add_argument('--taker_pays_issuer',default='rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B')
|
parser.add_argument('--taker_pays_issuer',default='rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B')
|
||||||
parser.add_argument('--taker_pays_currency',default='USD')
|
parser.add_argument('--taker_pays_currency',default='USD')
|
||||||
parser.add_argument('--taker_gets_issuer')
|
parser.add_argument('--taker_gets_issuer')
|
||||||
parser.add_argument('--taker_gets_currency',default='XRP')
|
parser.add_argument('--taker_gets_currency',default='XRP')
|
||||||
|
parser.add_argument('--p2pIp', default='127.0.0.1')
|
||||||
|
parser.add_argument('--p2pPort', default='6005')
|
||||||
|
parser.add_argument('--verify',default=False)
|
||||||
|
parser.add_argument('--binary',default=False)
|
||||||
|
parser.add_argument('--expand',default=False)
|
||||||
|
parser.add_argument('--transactions',default=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -147,35 +238,49 @@ parser.add_argument('--taker_gets_currency',default='XRP')
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||||
if(args.ledger is None):
|
if(args.ledger is None):
|
||||||
args.ledger = asyncio.get_event_loop().run_until_complete(ledger_range(args.ip, args.port));
|
args.ledger = asyncio.get_event_loop().run_until_complete(ledger_range(args.ip, args.port));
|
||||||
asyncio.set_event_loop(asyncio.new_event_loop())
|
|
||||||
if args.action == "account_info":
|
if args.action == "account_info":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
res1 = asyncio.get_event_loop().run_until_complete(
|
||||||
account_info(args.ip, args.port, args.account, args.ledger))
|
account_info(args.ip, args.port, args.account, args.ledger, args.binary))
|
||||||
|
if args.verify:
|
||||||
|
res2 = asyncio.get_event_loop().run_until_complete(
|
||||||
|
account_info(args.p2pIp, args.p2pPort, args.account, args.ledger, args.binary))
|
||||||
|
print(compareAccountInfo(res1,res2))
|
||||||
elif args.action == "tx":
|
elif args.action == "tx":
|
||||||
|
if args.hash is None:
|
||||||
|
args.hash = getHashes(asyncio.get_event_loop().run_until_complete(ledger(args.ip,args.port,args.ledger,False,True,False)))[0]
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
tx(args.ip, args.port, args.hash))
|
tx(args.ip, args.port, args.hash, args.binary))
|
||||||
elif args.action == "account_tx":
|
elif args.action == "account_tx":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
account_tx(args.ip, args.port, args.account))
|
account_tx(args.ip, args.port, args.account, args.binary))
|
||||||
elif args.action == "ledger_data":
|
elif args.action == "ledger_data":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
ledger_data(args.ip, args.port, args.ledger, args.limit))
|
ledger_data(args.ip, args.port, args.ledger, args.limit, args.binary))
|
||||||
elif args.action == "ledger_data_full":
|
elif args.action == "ledger_data_full":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
ledger_data_full(args.ip, args.port, args.ledger))
|
ledger_data_full(args.ip, args.port, args.ledger, args.binary))
|
||||||
elif args.action == "ledger":
|
elif args.action == "ledger":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
|
||||||
ledger(args.ip, args.port, args.ledger))
|
res = asyncio.get_event_loop().run_until_complete(
|
||||||
|
ledger(args.ip, args.port, args.ledger, args.binary, args.transactions, args.expand))
|
||||||
|
if args.verify:
|
||||||
|
res2 = asyncio.get_event_loop().run_until_complete(
|
||||||
|
ledger(args.p2pIp, args.p2pPort, args.ledger, args.binary, args.transactions, args.expand))
|
||||||
|
print(compareLedger(res,res2))
|
||||||
|
|
||||||
elif args.action == "ledger_range":
|
elif args.action == "ledger_range":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
ledger_range(args.ip, args.port))
|
ledger_range(args.ip, args.port))
|
||||||
elif args.action == "book_offers":
|
elif args.action == "book_offers":
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
book_offers(args.ip, args.port, args.ledger, args.taker_pays_currency, args.taker_pays_issuer, args.taker_gets_currency, args.taker_gets_issuer))
|
book_offers(args.ip, args.port, args.ledger, args.taker_pays_currency, args.taker_pays_issuer, args.taker_gets_currency, args.taker_gets_issuer, args.binary))
|
||||||
else:
|
else:
|
||||||
print("incorrect arguments")
|
print("incorrect arguments")
|
||||||
|
|
||||||
run(args)
|
|
||||||
|
|
||||||
|
|
||||||
|
run(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user