mirror of
https://github.com/Xahau/xahaud.git
synced 2026-09-24 22:30:17 +00:00
Compare commits
7 Commits
request-id
...
server-def
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd342dabee | ||
|
|
902ed9b492 | ||
|
|
318f941ec4 | ||
|
|
5450719bdc | ||
|
|
fb8c29cf38 | ||
|
|
3754109e4b | ||
|
|
9d125f4d19 |
@@ -116,11 +116,6 @@ message TMTransaction
|
||||
message TMTransactions
|
||||
{
|
||||
repeated TMTransaction transactions = 1;
|
||||
// Optional opaque request/response correlation ID. If present on the
|
||||
// TMGetObjectByHash(otTRANSACTIONS) request, the responder copies it
|
||||
// unchanged. This field is not routing state and does not affect message
|
||||
// processing, resource charging, duplicate suppression, or consensus.
|
||||
optional uint64 requestId = 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -272,10 +267,6 @@ message TMGetObjectByHash
|
||||
optional bytes ledgerHash = 4; // the hash of the ledger these queries are for
|
||||
optional bool fat = 5; // return related nodes
|
||||
repeated TMIndexedObject objects = 6; // the specific objects requested
|
||||
// Optional opaque request/response correlation ID. Responders copy this
|
||||
// value unchanged when forming a reply. This is distinct from the existing
|
||||
// uint32 seq field and has no protocol meaning beyond correlation.
|
||||
optional uint64 requestId = 7;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,10 +306,6 @@ message TMGetLedger
|
||||
optional uint64 requestCookie = 6;
|
||||
optional TMQueryType queryType = 7;
|
||||
optional uint32 queryDepth = 8; // How deep to go, number of extra levels
|
||||
// Optional opaque request/response correlation ID. Responders copy this
|
||||
// value unchanged into TMLedgerData. This is separate from requestCookie:
|
||||
// requestCookie is relay routing state; requestId is only correlation.
|
||||
optional uint64 requestId = 9;
|
||||
}
|
||||
|
||||
enum TMReplyError
|
||||
@@ -336,9 +323,6 @@ message TMLedgerData
|
||||
repeated TMLedgerNode nodes = 4;
|
||||
optional uint32 requestCookie = 5;
|
||||
optional TMReplyError error = 6;
|
||||
// Optional opaque request/response correlation ID copied from TMGetLedger.
|
||||
// Receivers must not use it for relay routing or data validation.
|
||||
optional uint64 requestId = 7;
|
||||
}
|
||||
|
||||
message TMPing
|
||||
@@ -351,9 +335,6 @@ message TMPing
|
||||
optional uint32 seq = 2; // detect stale replies, ensure other side is reading
|
||||
optional uint64 pingTime = 3; // know when we think we sent the ping
|
||||
optional uint64 netTime = 4;
|
||||
// Optional opaque request/response correlation ID copied from ptPING to
|
||||
// ptPONG. The existing seq field remains the ping liveness cookie.
|
||||
optional uint64 requestId = 5;
|
||||
}
|
||||
|
||||
message TMSquelch
|
||||
@@ -374,8 +355,6 @@ message TMProofPathRequest
|
||||
required bytes key = 1;
|
||||
required bytes ledgerHash = 2;
|
||||
required TMLedgerMapType type = 3;
|
||||
// Optional opaque request/response correlation ID copied into the response.
|
||||
optional uint64 requestId = 4;
|
||||
}
|
||||
|
||||
message TMProofPathResponse
|
||||
@@ -386,15 +365,11 @@ message TMProofPathResponse
|
||||
optional bytes ledgerHeader = 4;
|
||||
repeated bytes path = 5;
|
||||
optional TMReplyError error = 6;
|
||||
// Optional opaque request/response correlation ID copied from the request.
|
||||
optional uint64 requestId = 7;
|
||||
}
|
||||
|
||||
message TMReplayDeltaRequest
|
||||
{
|
||||
required bytes ledgerHash = 1;
|
||||
// Optional opaque request/response correlation ID copied into the response.
|
||||
optional uint64 requestId = 2;
|
||||
}
|
||||
|
||||
message TMReplayDeltaResponse
|
||||
@@ -403,8 +378,6 @@ message TMReplayDeltaResponse
|
||||
optional bytes ledgerHeader = 2;
|
||||
repeated bytes transaction = 3;
|
||||
optional TMReplyError error = 4;
|
||||
// Optional opaque request/response correlation ID copied from the request.
|
||||
optional uint64 requestId = 5;
|
||||
}
|
||||
|
||||
message TMHaveTransactions
|
||||
|
||||
@@ -292,7 +292,9 @@ JSS(duration_us); // out: NetworkOPs
|
||||
JSS(effective); // out: ValidatorList
|
||||
// in: UNL
|
||||
JSS(elapsed_seconds);
|
||||
JSS(enabled); // out: AmendmentTable
|
||||
JSS(enabled); // out: AmendmentTable (on-ledger);
|
||||
// ServerDefinitions (this server)
|
||||
JSS(ledger_enabled); // out: ServerDefinitions (on-ledger)
|
||||
JSS(engine_result); // out: NetworkOPs, TransactionSign, Submit
|
||||
JSS(engine_result_code); // out: NetworkOPs, TransactionSign, Submit
|
||||
JSS(engine_result_message); // out: NetworkOPs, TransactionSign, Submit
|
||||
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
void
|
||||
testNoParams(FeatureBitset features)
|
||||
{
|
||||
testcase("No Params, None Enabled");
|
||||
testcase("Default Env: config-forced, none on-ledger");
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env{*this};
|
||||
@@ -178,8 +178,6 @@ public:
|
||||
{
|
||||
if (!BEAST_EXPECT(feature.isMember(jss::name)))
|
||||
return;
|
||||
// default config - so all should be disabled, and
|
||||
// supported. Some may be vetoed.
|
||||
bool expectVeto =
|
||||
(votes.at(feature[jss::name].asString()) ==
|
||||
VoteBehavior::DefaultNo);
|
||||
@@ -188,8 +186,12 @@ public:
|
||||
VoteBehavior::Obsolete);
|
||||
BEAST_EXPECTS(
|
||||
feature.isMember(jss::enabled) &&
|
||||
!feature[jss::enabled].asBool(),
|
||||
feature[jss::enabled].asBool(),
|
||||
feature[jss::name].asString() + " enabled");
|
||||
BEAST_EXPECTS(
|
||||
feature.isMember(jss::ledger_enabled) &&
|
||||
!feature[jss::ledger_enabled].asBool(),
|
||||
feature[jss::name].asString() + " ledger_enabled");
|
||||
BEAST_EXPECTS(
|
||||
feature.isMember(jss::vetoed) &&
|
||||
feature[jss::vetoed].isBool() == !expectObsolete &&
|
||||
@@ -208,7 +210,7 @@ public:
|
||||
void
|
||||
testSomeEnabled(FeatureBitset features)
|
||||
{
|
||||
testcase("No Params, Some Enabled");
|
||||
testcase("Two config-forced, none on-ledger");
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env{
|
||||
@@ -228,7 +230,10 @@ public:
|
||||
(void)id.parseHex(it.key().asString().c_str());
|
||||
if (!BEAST_EXPECT((*it).isMember(jss::name)))
|
||||
return;
|
||||
bool expectEnabled = env.app().getAmendmentTable().isEnabled(id);
|
||||
bool const expectOnLedger =
|
||||
env.app().getAmendmentTable().isEnabled(id);
|
||||
bool const expectForced =
|
||||
id == featureDepositAuth || id == featureDepositPreauth;
|
||||
bool expectSupported =
|
||||
env.app().getAmendmentTable().isSupported(id);
|
||||
bool expectVeto =
|
||||
@@ -239,9 +244,14 @@ public:
|
||||
VoteBehavior::Obsolete);
|
||||
BEAST_EXPECTS(
|
||||
(*it).isMember(jss::enabled) &&
|
||||
(*it)[jss::enabled].asBool() == expectEnabled,
|
||||
(*it)[jss::enabled].asBool() ==
|
||||
(expectOnLedger || expectForced),
|
||||
(*it)[jss::name].asString() + " enabled");
|
||||
if (expectEnabled)
|
||||
BEAST_EXPECTS(
|
||||
(*it).isMember(jss::ledger_enabled) &&
|
||||
(*it)[jss::ledger_enabled].asBool() == expectOnLedger,
|
||||
(*it)[jss::name].asString() + " ledger_enabled");
|
||||
if (expectOnLedger)
|
||||
BEAST_EXPECTS(
|
||||
!(*it).isMember(jss::vetoed),
|
||||
(*it)[jss::name].asString() + " vetoed");
|
||||
@@ -360,12 +370,122 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testConfigForced(FeatureBitset features)
|
||||
{
|
||||
testcase("Config-forced features ([features] stanza)");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
auto const forced = featurePriceOracle;
|
||||
auto const forcedHex = to_string(forced);
|
||||
|
||||
Env env{*this, FeatureBitset(forced)};
|
||||
|
||||
auto jrr = env.rpc("server_definitions")[jss::result];
|
||||
if (!BEAST_EXPECT(jrr.isMember(jss::features)))
|
||||
return;
|
||||
|
||||
bool sawForced = false;
|
||||
for (auto it = jrr[jss::features].begin();
|
||||
it != jrr[jss::features].end();
|
||||
++it)
|
||||
{
|
||||
auto const& f = *it;
|
||||
auto const name = f[jss::name].asString();
|
||||
|
||||
if (!BEAST_EXPECTS(
|
||||
f.isMember(jss::enabled) && f.isMember(jss::ledger_enabled),
|
||||
name + " enabled/ledger_enabled"))
|
||||
return;
|
||||
|
||||
BEAST_EXPECTS(
|
||||
!f[jss::ledger_enabled].asBool(), name + " ledger_enabled");
|
||||
|
||||
if (it.key().asString() == forcedHex)
|
||||
{
|
||||
sawForced = true;
|
||||
BEAST_EXPECTS(f[jss::enabled].asBool(), name + " enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
BEAST_EXPECTS(!f[jss::enabled].asBool(), name + " enabled");
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(sawForced);
|
||||
}
|
||||
|
||||
void
|
||||
testOnLedger(FeatureBitset features)
|
||||
{
|
||||
testcase("On-ledger plus one config-forced");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
// Veto XahauGenesis: FRESH would otherwise enable it via pseudo-tx.
|
||||
auto const forced = featurePriceOracle;
|
||||
auto const forcedHex = to_string(forced);
|
||||
|
||||
Env env{
|
||||
*this,
|
||||
envconfig([](std::unique_ptr<Config> cfg) {
|
||||
cfg->START_UP = Config::FRESH;
|
||||
cfg->section(SECTION_VETO_AMENDMENTS)
|
||||
.append(to_string(featureXahauGenesis) + " XahauGenesis");
|
||||
return cfg;
|
||||
}),
|
||||
FeatureBitset(forced)};
|
||||
|
||||
auto jrr = env.rpc("server_definitions")[jss::result];
|
||||
if (!BEAST_EXPECT(jrr.isMember(jss::features)))
|
||||
return;
|
||||
|
||||
bool sawOnLedger = false;
|
||||
bool sawForced = false;
|
||||
for (auto it = jrr[jss::features].begin();
|
||||
it != jrr[jss::features].end();
|
||||
++it)
|
||||
{
|
||||
uint256 id;
|
||||
(void)id.parseHex(it.key().asString().c_str());
|
||||
auto const& f = *it;
|
||||
auto const name = f[jss::name].asString();
|
||||
|
||||
if (!BEAST_EXPECTS(
|
||||
f.isMember(jss::enabled) && f.isMember(jss::ledger_enabled),
|
||||
name + " enabled/ledger_enabled"))
|
||||
return;
|
||||
|
||||
bool const onLedger = env.app().getAmendmentTable().isEnabled(id);
|
||||
bool const isForced = it.key().asString() == forcedHex;
|
||||
|
||||
BEAST_EXPECTS(
|
||||
f[jss::ledger_enabled].asBool() == onLedger,
|
||||
name + " ledger_enabled");
|
||||
BEAST_EXPECTS(
|
||||
f[jss::enabled].asBool() == (onLedger || isForced),
|
||||
name + " enabled");
|
||||
|
||||
if (onLedger)
|
||||
sawOnLedger = true;
|
||||
if (isForced)
|
||||
{
|
||||
sawForced = true;
|
||||
BEAST_EXPECTS(!onLedger, name + " forced not on-ledger");
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(sawOnLedger);
|
||||
BEAST_EXPECT(sawForced);
|
||||
}
|
||||
|
||||
void
|
||||
testServerFeatures(FeatureBitset features)
|
||||
{
|
||||
testNoParams(features);
|
||||
testSomeEnabled(features);
|
||||
testWithMajorities(features);
|
||||
testConfigForced(features);
|
||||
testOnLedger(features);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -2439,9 +2439,6 @@ LedgerMaster::makeFetchPack(
|
||||
if (request->has_seq())
|
||||
reply.set_seq(request->seq());
|
||||
|
||||
if (request->has_requestid())
|
||||
reply.set_requestid(request->requestid());
|
||||
|
||||
reply.set_ledgerhash(request->ledgerhash());
|
||||
reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@ LedgerReplayMsgHandler::processProofPathRequest(
|
||||
protocol::TMProofPathRequest& packet = *msg;
|
||||
protocol::TMProofPathResponse reply;
|
||||
|
||||
if (packet.has_requestid())
|
||||
reply.set_requestid(packet.requestid());
|
||||
|
||||
if (!packet.has_key() || !packet.has_ledgerhash() || !packet.has_type() ||
|
||||
packet.ledgerhash().size() != uint256::size() ||
|
||||
packet.key().size() != uint256::size() ||
|
||||
@@ -185,9 +182,6 @@ LedgerReplayMsgHandler::processReplayDeltaRequest(
|
||||
protocol::TMReplayDeltaRequest& packet = *msg;
|
||||
protocol::TMReplayDeltaResponse reply;
|
||||
|
||||
if (packet.has_requestid())
|
||||
reply.set_requestid(packet.requestid());
|
||||
|
||||
if (!packet.has_ledgerhash() ||
|
||||
packet.ledgerhash().size() != uint256::size())
|
||||
{
|
||||
|
||||
@@ -30,12 +30,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TxConsequences
|
||||
ClaimReward::makeTxConsequences(PreflightContext const& ctx)
|
||||
{
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
NotTEC
|
||||
ClaimReward::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -32,15 +32,12 @@ namespace ripple {
|
||||
class ClaimReward : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit ClaimReward(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -30,12 +30,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TxConsequences
|
||||
Cron::makeTxConsequences(PreflightContext const& ctx)
|
||||
{
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
NotTEC
|
||||
Cron::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ripple {
|
||||
class Cron : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit Cron(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
@@ -39,9 +39,6 @@ public:
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -27,12 +27,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TxConsequences
|
||||
CronSet::makeTxConsequences(PreflightContext const& ctx)
|
||||
{
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
NotTEC
|
||||
CronSet::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace ripple {
|
||||
class CronSet : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CronSet(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
@@ -38,9 +38,6 @@ public:
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TxConsequences
|
||||
Invoke::makeTxConsequences(PreflightContext const& ctx)
|
||||
{
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
NotTEC
|
||||
Invoke::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ripple {
|
||||
class Invoke : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit Invoke(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
@@ -39,9 +39,6 @@ public:
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -30,12 +30,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TxConsequences
|
||||
SetRemarks::makeTxConsequences(PreflightContext const& ctx)
|
||||
{
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
NotTEC
|
||||
SetRemarks::validateRemarks(STArray const& remarks, beast::Journal const& j)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ripple {
|
||||
class SetRemarks : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit SetRemarks(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
@@ -39,9 +39,6 @@ public:
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -2436,9 +2436,6 @@ PeerImp::onMessage(std::shared_ptr<protocol::TMGetObjectByHash> const& m)
|
||||
if (packet.has_seq())
|
||||
reply.set_seq(packet.seq());
|
||||
|
||||
if (packet.has_requestid())
|
||||
reply.set_requestid(packet.requestid());
|
||||
|
||||
reply.set_type(packet.type());
|
||||
|
||||
if (packet.has_ledgerhash())
|
||||
@@ -2751,9 +2748,6 @@ PeerImp::doTransactions(
|
||||
{
|
||||
protocol::TMTransactions reply;
|
||||
|
||||
if (packet->has_requestid())
|
||||
reply.set_requestid(packet->requestid());
|
||||
|
||||
JLOG(p_journal_.trace()) << "received TMGetObjectByHash requesting tx "
|
||||
<< packet->objects_size();
|
||||
|
||||
@@ -3255,12 +3249,6 @@ PeerImp::processLedgerRequest(std::shared_ptr<protocol::TMGetLedger> const& m)
|
||||
protocol::TMLedgerData ledgerData;
|
||||
bool fatLeaves{true};
|
||||
auto const itype{m->itype()};
|
||||
auto const copyRequestMetadata = [&] {
|
||||
if (m->has_requestcookie())
|
||||
ledgerData.set_requestcookie(m->requestcookie());
|
||||
if (m->has_requestid())
|
||||
ledgerData.set_requestid(m->requestid());
|
||||
};
|
||||
|
||||
if (itype == protocol::liTS_CANDIDATE)
|
||||
{
|
||||
@@ -3272,7 +3260,8 @@ PeerImp::processLedgerRequest(std::shared_ptr<protocol::TMGetLedger> const& m)
|
||||
ledgerData.set_ledgerseq(0);
|
||||
ledgerData.set_ledgerhash(m->ledgerhash());
|
||||
ledgerData.set_type(protocol::liTS_CANDIDATE);
|
||||
copyRequestMetadata();
|
||||
if (m->has_requestcookie())
|
||||
ledgerData.set_requestcookie(m->requestcookie());
|
||||
|
||||
// We'll already have most transactions
|
||||
fatLeaves = false;
|
||||
@@ -3299,7 +3288,8 @@ PeerImp::processLedgerRequest(std::shared_ptr<protocol::TMGetLedger> const& m)
|
||||
ledgerData.set_ledgerhash(ledgerHash.begin(), ledgerHash.size());
|
||||
ledgerData.set_ledgerseq(ledger->info().seq);
|
||||
ledgerData.set_type(itype);
|
||||
copyRequestMetadata();
|
||||
if (m->has_requestcookie())
|
||||
ledgerData.set_requestcookie(m->requestcookie());
|
||||
|
||||
switch (itype)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/misc/AmendmentTable.h>
|
||||
#include <xrpld/app/misc/NetworkOPs.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/rpc/detail/TransactionSign.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/json/json_writer.h>
|
||||
@@ -545,6 +546,25 @@ doServerDefinitions(RPC::JsonContext& context)
|
||||
features[to_string(h)][jss::majority] =
|
||||
t.time_since_epoch().count();
|
||||
|
||||
// getJson's enabled is on-ledger; [features] also apply here.
|
||||
for (auto const& name : features.getMemberNames())
|
||||
{
|
||||
Json::Value& entry = features[name];
|
||||
entry[jss::ledger_enabled] = entry[jss::enabled].asBool();
|
||||
}
|
||||
for (auto const& h : context.app.config().features)
|
||||
{
|
||||
Json::Value& entry = features[to_string(h)];
|
||||
if (!entry.isMember(jss::name))
|
||||
{
|
||||
if (auto const fname = featureToName(h); !fname.empty())
|
||||
entry[jss::name] = fname;
|
||||
}
|
||||
if (!entry.isMember(jss::ledger_enabled))
|
||||
entry[jss::ledger_enabled] = false;
|
||||
entry[jss::enabled] = true;
|
||||
}
|
||||
|
||||
lastFeatures = features;
|
||||
{
|
||||
const std::string out = Json::FastWriter().write(features);
|
||||
|
||||
Reference in New Issue
Block a user