Unify JSON serialization format of transactions (#4775)

* Remove include <ranges>

* Formatting fix

* Output for subscriptions

* Output from sign, submit etc.

* Output from ledger

* Output from account_tx

* Output from transaction_entry

* Output from tx

* Store close_time_iso in API v2 output

* Add small APIv2 unit test for subscribe

* Add unit test for transaction_entry

* Add unit test for tx

* Remove inLedger from API version 2

* Set ledger_hash and ledger_index

* Move isValidated from RPCHelpers to LedgerMaster

* Store closeTime in LedgerFill

* Time formatting fix

* additional tests for Subscribe unit tests

* Improved comments

* Rename mInLedger to mLedgerIndex

* Minor fixes

* Set ledger_hash on closed ledger, even if not validated

* Update API-CHANGELOG.md

* Add ledger_hash, ledger_index to transaction_entry

* Fix validated and close_time_iso in account_tx

* Fix typos

* Improve getJson for Transaction and STTx

* Minor improvements

* Replace class enum JsonOptions with struct

We may consider turning this into a general-purpose template and using it elsewhere

* simplify the extraction of transactionID from Transaction object

* Remove obsolete comments

* Unconditionally set validated in account_tx output

* Minor improvements

* Minor fixes

---------

Co-authored-by: Chenna Keshava <ckeshavabs@gmail.com>
This commit is contained in:
Bronek Kozicki
2023-11-08 18:36:24 +00:00
committed by GitHub
parent 09e0f103f4
commit 32ced493de
33 changed files with 763 additions and 234 deletions

View File

@@ -31,7 +31,62 @@
#include <utility>
namespace ripple {
enum class JsonOptions { none = 0, include_date = 1 };
/// Note, should be treated as flags that can be | and &
struct JsonOptions
{
using underlying_t = unsigned int;
underlying_t value;
enum values : underlying_t {
// clang-format off
none = 0b0000'0000,
include_date = 0b0000'0001,
disable_API_prior_V2 = 0b0000'0010,
// IMPORTANT `_all` must be union of all of the above; see also operator~
_all = 0b0000'0011
// clang-format on
};
constexpr JsonOptions(underlying_t v) noexcept : value(v)
{
}
[[nodiscard]] constexpr explicit operator underlying_t() const noexcept
{
return value;
}
[[nodiscard]] constexpr explicit operator bool() const noexcept
{
return value != 0u;
}
[[nodiscard]] constexpr auto friend
operator==(JsonOptions lh, JsonOptions rh) noexcept -> bool = default;
[[nodiscard]] constexpr auto friend
operator!=(JsonOptions lh, JsonOptions rh) noexcept -> bool = default;
/// Returns JsonOptions union of lh and rh
[[nodiscard]] constexpr JsonOptions friend
operator|(JsonOptions lh, JsonOptions rh) noexcept
{
return {lh.value | rh.value};
}
/// Returns JsonOptions intersection of lh and rh
[[nodiscard]] constexpr JsonOptions friend
operator&(JsonOptions lh, JsonOptions rh) noexcept
{
return {lh.value & rh.value};
}
/// Returns JsonOptions binary negation, can be used with & (above) for set
/// difference e.g. `(options & ~JsonOptions::include_date)`
[[nodiscard]] constexpr JsonOptions friend
operator~(JsonOptions v) noexcept
{
return {~v.value & static_cast<underlying_t>(_all)};
}
};
namespace detail {
class STVar;

View File

@@ -28,6 +28,7 @@
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/SOTemplate.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STIssue.h>
#include <ripple/protocol/STPathSet.h>
#include <ripple/protocol/STVector256.h>

View File

@@ -29,6 +29,7 @@
#include <ripple/protocol/SeqProxy.h>
#include <ripple/protocol/TxFormats.h>
#include <boost/container/flat_set.hpp>
#include <functional>
namespace ripple {
@@ -108,6 +109,7 @@ public:
Json::Value
getJson(JsonOptions options) const override;
Json::Value
getJson(JsonOptions options, bool binary) const;

View File

@@ -34,6 +34,7 @@
#include <ripple/protocol/UintTypes.h>
#include <ripple/protocol/jss.h>
#include <boost/format.hpp>
#include <array>
#include <memory>
#include <type_traits>
@@ -226,25 +227,41 @@ STTx::checkSign(
return Unexpected("Internal signature check failure.");
}
Json::Value STTx::getJson(JsonOptions) const
Json::Value
STTx::getJson(JsonOptions options) const
{
Json::Value ret = STObject::getJson(JsonOptions::none);
ret[jss::hash] = to_string(getTransactionID());
if (!(options & JsonOptions::disable_API_prior_V2))
ret[jss::hash] = to_string(getTransactionID());
return ret;
}
Json::Value
STTx::getJson(JsonOptions options, bool binary) const
{
bool const V1 = !(options & JsonOptions::disable_API_prior_V2);
if (binary)
{
Json::Value ret;
Serializer s = STObject::getSerializer();
ret[jss::tx] = strHex(s.peekData());
ret[jss::hash] = to_string(getTransactionID());
return ret;
std::string const dataBin = strHex(s.peekData());
if (V1)
{
Json::Value ret(Json::objectValue);
ret[jss::tx] = dataBin;
ret[jss::hash] = to_string(getTransactionID());
return ret;
}
else
return Json::Value{dataBin};
}
return getJson(options);
Json::Value ret = STObject::getJson(JsonOptions::none);
if (V1)
ret[jss::hash] = to_string(getTransactionID());
return ret;
}
std::string const&

View File

@@ -230,6 +230,8 @@ JSS(close); // out: BookChanges
JSS(close_flags); // out: LedgerToJson
JSS(close_time); // in: Application, out: NetworkOPs,
// RCLCxPeerPos, LedgerToJson
JSS(close_time_iso); // out: Tx, NetworkOPs, TransactionEntry
// AccountTx, LedgerToJson
JSS(close_time_estimated); // in: Application, out: LedgerToJson
JSS(close_time_human); // out: LedgerToJson
JSS(close_time_offset); // out: NetworkOPs
@@ -460,6 +462,7 @@ JSS(median_fee); // out: TxQ
JSS(median_level); // out: TxQ
JSS(message); // error.
JSS(meta); // out: NetworkOPs, AccountTx*, Tx
JSS(meta_blob); // out: NetworkOPs, AccountTx*, Tx
JSS(metaData);
JSS(metadata); // out: TransactionEntry
JSS(method); // RPC