diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index 232cb4a8532..eeedbc4d0e9 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -237,6 +237,70 @@ class SField fieldMeta = c; } + static Json::Value allFieldsJson (); + + Json::Value toJson () const + { + Json::Value p(Json::objectValue); + p["name"] = jsonName; + + std::string type = ""; + switch (fieldType) { + case STI_UINT16: + type = "UInt16"; + break; + case STI_UINT32: + type = "UInt32"; + break; + case STI_UINT64: + type = "UInt64"; + break; + case STI_HASH128: + type = "Hash128"; + break; + case STI_HASH256: + type = "Hash256"; + break; + case STI_AMOUNT: + type = "Amount"; + break; + case STI_VL: + type = "Blob"; + break; + case STI_ACCOUNT: + type = "AccountID"; + break; + case STI_OBJECT: + type = "STObject"; + break; + case STI_ARRAY: + type = "STArray"; + break; + case STI_UINT8: + type = "UInt8"; + break; + case STI_HASH160: + type = "Hash160"; + break; + case STI_PATHSET: + type = "PathSet"; + break; + case STI_VECTOR256: + type = "Vector256"; + break; + default: + // TODO: + type = "Unknown(ordinal=" + std::to_string(fieldType) + ")"; + break; + } + + p["type"] = type; + p["ordinal"] = fieldValue; + p["isSigningField"] = isSigningField() && isBinary(); + p["isBinary"] = isBinary(); + return p; + } + bool shouldInclude (bool withSigningField) const { return (fieldValue < 256) && diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index a73dcd950e8..865751fbb19 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -403,4 +403,17 @@ SField::getField (std::string const& fieldName) return sfInvalid; } +Json::Value SField::allFieldsJson () +{ + Json::Value all(Json::arrayValue); + for (auto const& pair : knownCodeToField) + { + if (pair.second->isBinary()) + { + Json::Value& obj (all.append ( pair.second->toJson() )); + } + } + return all; +} + } // ripple diff --git a/src/test/protocol/STObject_test.cpp b/src/test/protocol/STObject_test.cpp index 7c7d4305f2e..7e233af3f5d 100644 --- a/src/test/protocol/STObject_test.cpp +++ b/src/test/protocol/STObject_test.cpp @@ -23,12 +23,14 @@ #include #include #include +#include #include #include #include #include #include +#include namespace ripple { @@ -648,6 +650,94 @@ class STObject_test : public beast::unit_test::suite } }; +class ProtocolJson_test : public beast::unit_test::suite +{ +public: + std::string + requirementString(SOE_Flags flags) + { + std::string requirement = ""; + switch (flags) { + case SOE_REQUIRED: + requirement = "REQUIRED"; + break; + case SOE_OPTIONAL: + requirement = "OPTIONAL"; + break; + case SOE_DEFAULT: + requirement = "DEFAULT"; + break; + default: + break; + } + return requirement; + } + + template + Json::Value + formatsJson(const KnownFormats& formats) + { + auto array = Json::Value(Json::arrayValue); + // Hacky, but avoids altering KnownFormats classes + for (int o = ((1 << 16) * -1); o < (1 << 16); o++) + { + auto format = formats.findByType(static_cast(o)); + if (format != nullptr) + { + auto& tx = array.append(Json::objectValue); + tx["name"] = format->getName(); + tx["ordinal"] = o; + auto& fields = tx["fields"] = Json::Value(Json::arrayValue); + + for (auto& p : format->elements.all()) { + auto& field = fields.append(Json::arrayValue); + field.append(p->e_field.jsonName); + field.append(requirementString(p->flags)); + } + } + } + return array; + } + + Json::Value + engineResults() { + auto engineResults = Json::Value(Json::objectValue); + for (int i = static_cast(telLOCAL_ERROR); i < 256; ++i) + { + std::string name(""), desc(""); + auto ter = static_cast(i); + if (transResultInfo(ter, name, desc)) + { + auto& resultObj = engineResults[name] = + Json::Value(Json::objectValue); + resultObj["ordinal"] = i; + resultObj["description"] = desc; + } + } + return engineResults; + } + + void + run() + { + testcase("ProtocolJson"); + Json::Value protocol (Json::objectValue); + + protocol["fields"] = SField::allFieldsJson(); + protocol["transactions"] = + formatsJson(TxFormats::getInstance()); + protocol["ledgerEntries"] = + formatsJson(LedgerFormats::getInstance()); + + protocol["engineResults"] = engineResults(); + std::ofstream outfile ("protocol.json",std::ofstream::binary); + outfile << protocol << std::endl; + outfile.close(); + pass(); + } +}; + BEAST_DEFINE_TESTSUITE(STObject,protocol,ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(ProtocolJson,protocol,ripple); } // ripple