ledger rpc accepts more flags. binary options for all rpcs. tests to verify ledger and account_info

This commit is contained in:
CJ Cobb
2021-03-09 16:33:24 -05:00
parent e3a121e571
commit f781bd6c00
11 changed files with 335 additions and 76 deletions

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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,

View File

@@ -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 "

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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,

View File

@@ -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
View File

@@ -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)