mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
@@ -133,7 +133,6 @@ struct Amendments {
|
||||
REGISTER(AMMClawback);
|
||||
REGISTER(Credentials);
|
||||
REGISTER(DynamicNFT);
|
||||
// TODO: Add PermissionedDomains related RPC changes
|
||||
REGISTER(PermissionedDomains);
|
||||
|
||||
// Obsolete but supported by libxrpl
|
||||
|
||||
@@ -89,6 +89,7 @@ getErrorInfo(ClioError code)
|
||||
{.code = ClioError::RpcMalformedAuthorizedCredentials,
|
||||
.error = "malformedAuthorizedCredentials",
|
||||
.message = "Malformed authorized credentials."},
|
||||
|
||||
// special system errors
|
||||
{.code = ClioError::RpcInvalidApiVersion, .error = JS(invalid_API_version), .message = "Invalid API version."},
|
||||
{.code = ClioError::RpcCommandIsMissing,
|
||||
|
||||
@@ -179,6 +179,12 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
ripple::uint192{std::string_view(boost::json::value_to<std::string>(input.mptoken->at(JS(mpt_issuance_id))))
|
||||
};
|
||||
key = ripple::keylet::mptoken(mptIssuanceID, *holder).key;
|
||||
} else if (input.permissionedDomain) {
|
||||
auto const account = ripple::parseBase58<ripple::AccountID>(
|
||||
boost::json::value_to<std::string>(input.permissionedDomain->at(JS(account)))
|
||||
);
|
||||
auto const seq = input.permissionedDomain->at(JS(seq)).as_int64();
|
||||
key = ripple::keylet::permissionedDomain(*account, seq).key;
|
||||
} else {
|
||||
// Must specify 1 of the following fields to indicate what type
|
||||
if (ctx.apiVersion == 1)
|
||||
@@ -313,6 +319,7 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
{JS(oracle), ripple::ltORACLE},
|
||||
{JS(credential), ripple::ltCREDENTIAL},
|
||||
{JS(mptoken), ripple::ltMPTOKEN},
|
||||
{JS(permissioned_domain), ripple::ltPERMISSIONED_DOMAIN}
|
||||
};
|
||||
|
||||
auto const parseBridgeFromJson = [](boost::json::value const& bridgeJson) {
|
||||
@@ -399,6 +406,8 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
input.credential = parseCredentialFromJson(jv.at(JS(credential)));
|
||||
} else if (jsonObject.contains(JS(mptoken))) {
|
||||
input.mptoken = jv.at(JS(mptoken)).as_object();
|
||||
} else if (jsonObject.contains(JS(permissioned_domain))) {
|
||||
input.permissionedDomain = jv.at(JS(permissioned_domain)).as_object();
|
||||
}
|
||||
|
||||
if (jsonObject.contains("include_deleted"))
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
std::optional<boost::json::object> ticket;
|
||||
std::optional<boost::json::object> amm;
|
||||
std::optional<boost::json::object> mptoken;
|
||||
std::optional<boost::json::object> permissionedDomain;
|
||||
std::optional<ripple::STXChainBridge> bridge;
|
||||
std::optional<std::string> bridgeAccount;
|
||||
std::optional<uint32_t> chainClaimId;
|
||||
@@ -374,6 +375,23 @@ public:
|
||||
},
|
||||
},
|
||||
}},
|
||||
{JS(permissioned_domain),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(ClioError::RpcMalformedRequest)
|
||||
},
|
||||
meta::IfType<std::string>{kMALFORMED_REQUEST_HEX_STRING_VALIDATOR},
|
||||
meta::IfType<boost::json::object>{meta::Section{
|
||||
{JS(seq),
|
||||
meta::WithCustomError{validation::Required{}, Status(ClioError::RpcMalformedRequest)},
|
||||
meta::WithCustomError{validation::Type<uint32_t>{}, Status(ClioError::RpcMalformedRequest)}},
|
||||
{
|
||||
JS(account),
|
||||
meta::WithCustomError{validation::Required{}, Status(ClioError::RpcMalformedRequest)},
|
||||
meta::WithCustomError{
|
||||
validation::CustomValidators::accountBase58Validator, Status(ClioError::RpcMalformedAddress)
|
||||
},
|
||||
},
|
||||
}}},
|
||||
{JS(ledger), check::Deprecated{}},
|
||||
{"include_deleted", validation::Type<bool>{}},
|
||||
};
|
||||
|
||||
@@ -117,6 +117,7 @@ class LedgerTypes {
|
||||
LedgerTypeAttribute::chainLedgerType(JS(nunl), ripple::ltNEGATIVE_UNL),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(mpt_issuance), ripple::ltMPTOKEN_ISSUANCE),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(mptoken), ripple::ltMPTOKEN),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(permissioned_domain), ripple::ltPERMISSIONED_DOMAIN),
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -1485,6 +1485,30 @@ createMpTokenObject(std::string_view accountId, ripple::uint192 issuanceID, std:
|
||||
return mptoken;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
createPermissionedDomainObject(
|
||||
std::string_view accountId,
|
||||
std::string_view ledgerIndex,
|
||||
ripple::LedgerIndex seq,
|
||||
uint64_t ownerNode,
|
||||
ripple::uint256 previousTxId,
|
||||
uint32_t previousTxSeq
|
||||
)
|
||||
{
|
||||
ripple::STObject object(ripple::sfLedgerEntry);
|
||||
object.setFieldH256(ripple::sfLedgerIndex, ripple::uint256(ledgerIndex));
|
||||
object.setAccountID(ripple::sfOwner, getAccountIdWithString(accountId));
|
||||
object.setFieldU32(ripple::sfSequence, seq);
|
||||
object.setFieldArray(ripple::sfAcceptedCredentials, ripple::STArray{});
|
||||
object.setFieldU64(ripple::sfOwnerNode, ownerNode);
|
||||
object.setFieldH256(ripple::sfPreviousTxnID, previousTxId);
|
||||
object.setFieldU32(ripple::sfPreviousTxnLgrSeq, previousTxSeq);
|
||||
object.setFieldU32(ripple::sfFlags, 0);
|
||||
object.setFieldU16(ripple::sfLedgerEntryType, ripple::ltPERMISSIONED_DOMAIN);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
createOraclePriceData(
|
||||
uint64_t assetPrice,
|
||||
|
||||
@@ -453,6 +453,16 @@ createMptIssuanceObject(std::string_view accountId, std::uint32_t seq, std::stri
|
||||
[[nodiscard]] ripple::STObject
|
||||
createMpTokenObject(std::string_view accountId, ripple::uint192 issuanceID, std::uint64_t mptAmount = 1);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
createPermissionedDomainObject(
|
||||
std::string_view accountId,
|
||||
std::string_view ledgerIndex,
|
||||
ripple::LedgerIndex seq,
|
||||
uint64_t ownerNode,
|
||||
ripple::uint256 previousTxId,
|
||||
uint32_t previousTxSeq
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
createOraclePriceData(
|
||||
uint64_t assetPrice,
|
||||
|
||||
@@ -2136,7 +2136,62 @@ generateTestValuesForParametersTest()
|
||||
),
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request."
|
||||
}
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_NotObject",
|
||||
.testJson = R"json({"permissioned_domain": []})json",
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request.",
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_InvalidString",
|
||||
.testJson = R"json({"permissioned_domain": "invalid_string"})json",
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request.",
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_EmptyObject",
|
||||
.testJson = R"json({"permissioned_domain": {}})json",
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request.",
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_BadAccount",
|
||||
.testJson = R"json({"permissioned_domain": {"account": "1234", "seq": 1234}})json",
|
||||
.expectedError = "malformedAddress",
|
||||
.expectedErrorMessage = "Malformed address.",
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_MissingSeq",
|
||||
.testJson = fmt::format(
|
||||
R"json({{
|
||||
"permissioned_domain": {{ "account": "{}" }}
|
||||
}})json",
|
||||
kACCOUNT
|
||||
),
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request.",
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_SeqIsNotUint",
|
||||
.testJson = fmt::format(
|
||||
R"json({{
|
||||
"permissioned_domain": {{ "account": "{}", "seq": -1 }}
|
||||
}})json",
|
||||
kACCOUNT
|
||||
),
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request.",
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
.testName = "InvalidPermissionedDomain_BothAccountAndSeqAreInvalid",
|
||||
.testJson =
|
||||
R"json({
|
||||
"permissioned_domain": { "account": "", "seq": -1 }
|
||||
})json",
|
||||
.expectedError = "malformedRequest",
|
||||
.expectedErrorMessage = "Malformed request.",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2872,6 +2927,36 @@ generateTestValuesForNormalPathTest()
|
||||
.expectedIndex = ripple::keylet::mptoken(ripple::makeMptID(2, account1), account1).key,
|
||||
.mockedEntity = createMpTokenObject(kACCOUNT, ripple::makeMptID(2, account1))
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
.testName = "PermissionedDomainViaString",
|
||||
.testJson = fmt::format(
|
||||
R"json({{
|
||||
"binary": true,
|
||||
"permissioned_domain": "{}"
|
||||
}})json",
|
||||
kINDEX1
|
||||
),
|
||||
.expectedIndex = ripple::uint256(kINDEX1),
|
||||
.mockedEntity = createPermissionedDomainObject(kACCOUNT, kINDEX1, kRANGE_MAX, 0, ripple::uint256{0}, 0)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
.testName = "PermissionedDomainViaObject",
|
||||
.testJson = fmt::format(
|
||||
R"json({{
|
||||
"binary": true,
|
||||
"permissioned_domain": {{
|
||||
"account": "{}",
|
||||
"seq": {}
|
||||
}}
|
||||
}})json",
|
||||
kACCOUNT,
|
||||
kRANGE_MAX
|
||||
),
|
||||
.expectedIndex =
|
||||
ripple::keylet::permissionedDomain(ripple::parseBase58<ripple::AccountID>(kACCOUNT).value(), kRANGE_MAX)
|
||||
.key,
|
||||
.mockedEntity = createPermissionedDomainObject(kACCOUNT, kINDEX1, kRANGE_MAX, 0, ripple::uint256{0}, 0)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2900,15 +2985,14 @@ TEST_P(RPCLedgerEntryNormalPathTest, NormalPath)
|
||||
auto const req = json::parse(testBundle.testJson);
|
||||
auto const output = handler.process(req, Context{yield});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(output.result.value().at("ledger_hash").as_string(), kLEDGER_HASH);
|
||||
EXPECT_EQ(output.result.value().at("ledger_index").as_uint64(), kRANGE_MAX);
|
||||
auto const& outputJson = output.result.value();
|
||||
EXPECT_EQ(outputJson.at("ledger_hash").as_string(), kLEDGER_HASH);
|
||||
EXPECT_EQ(outputJson.at("ledger_index").as_uint64(), kRANGE_MAX);
|
||||
EXPECT_EQ(
|
||||
output.result.value().at("node_binary").as_string(),
|
||||
ripple::strHex(testBundle.mockedEntity.getSerializer().peekData())
|
||||
outputJson.at("node_binary").as_string(), ripple::strHex(testBundle.mockedEntity.getSerializer().peekData())
|
||||
);
|
||||
EXPECT_EQ(
|
||||
ripple::uint256(boost::json::value_to<std::string>(output.result.value().at("index")).data()),
|
||||
testBundle.expectedIndex
|
||||
ripple::uint256(boost::json::value_to<std::string>(outputJson.at("index")).data()), testBundle.expectedIndex
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ TEST(LedgerUtilsTests, LedgerObjectTypeList)
|
||||
JS(did),
|
||||
JS(mpt_issuance),
|
||||
JS(mptoken),
|
||||
JS(permissioned_domain),
|
||||
JS(oracle),
|
||||
JS(credential),
|
||||
JS(nunl)
|
||||
@@ -88,7 +89,8 @@ TEST(LedgerUtilsTests, AccountOwnedTypeList)
|
||||
JS(oracle),
|
||||
JS(credential),
|
||||
JS(mpt_issuance),
|
||||
JS(mptoken)
|
||||
JS(mptoken),
|
||||
JS(permissioned_domain),
|
||||
};
|
||||
|
||||
static_assert(std::size(kCORRECT_TYPES) == kACCOUNT_OWNED.size());
|
||||
@@ -123,7 +125,8 @@ TEST(LedgerUtilsTests, DeletionBlockerTypes)
|
||||
ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
|
||||
ripple::ltBRIDGE,
|
||||
ripple::ltMPTOKEN_ISSUANCE,
|
||||
ripple::ltMPTOKEN
|
||||
ripple::ltMPTOKEN,
|
||||
ripple::ltPERMISSIONED_DOMAIN
|
||||
};
|
||||
|
||||
static_assert(std::size(kDELETION_BLOCKERS) == kTESTED_TYPES.size());
|
||||
|
||||
Reference in New Issue
Block a user