Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement DID #967

Merged
merged 5 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
// Max number of requests to queue up before rejecting further requests.
// Defaults to 0, which disables the limit.
"max_queue_size": 500,
// If request contains header with authorization, Clio will check if it matches this value's hash
// If request contains header with authorization, Clio will check if it matches this value's sha256 hash
// If matches, the request will be considered as admin request
"admin_password": "xrp",
// If local_admin is true, Clio will consider requests come from 127.0.0.1 as admin requests
Expand Down
33 changes: 21 additions & 12 deletions src/rpc/handlers/AccountObjects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,28 @@
namespace rpc {

// found here : https://xrpl.org/ledger_entry.html#:~:text=valid%20fields%20are%3A-,index,-account_root
std::unordered_map<std::string, ripple::LedgerEntryType> const AccountObjectsHandler::TYPESMAP{
{"state", ripple::ltRIPPLE_STATE},
{"ticket", ripple::ltTICKET},
{"signer_list", ripple::ltSIGNER_LIST},
{"payment_channel", ripple::ltPAYCHAN},
{"offer", ripple::ltOFFER},
{"escrow", ripple::ltESCROW},
{"deposit_preauth", ripple::ltDEPOSIT_PREAUTH},
{"check", ripple::ltCHECK},
{"nft_page", ripple::ltNFTOKEN_PAGE},
{"nft_offer", ripple::ltNFTOKEN_OFFER},
std::unordered_map<std::string, ripple::LedgerEntryType> const AccountObjectsHandler::TYPES_MAP{
{JS(state), ripple::ltRIPPLE_STATE},
{JS(ticket), ripple::ltTICKET},
{JS(signer_list), ripple::ltSIGNER_LIST},
{JS(payment_channel), ripple::ltPAYCHAN},
{JS(offer), ripple::ltOFFER},
{JS(escrow), ripple::ltESCROW},
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
{JS(check), ripple::ltCHECK},
{JS(nft_page), ripple::ltNFTOKEN_PAGE},
{JS(nft_offer), ripple::ltNFTOKEN_OFFER},
{JS(did), ripple::ltDID},
};

std::unordered_set<std::string> const AccountObjectsHandler::TYPES_KEYS = [] {
std::unordered_set<std::string> keys;
std::transform(TYPES_MAP.begin(), TYPES_MAP.end(), std::inserter(keys, keys.begin()), [](auto const& pair) {
return pair.first;
});
return keys;
}();

AccountObjectsHandler::Result
AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const& ctx) const
{
Expand Down Expand Up @@ -153,7 +162,7 @@ tag_invoke(boost::json::value_to_tag<AccountObjectsHandler::Input>, boost::json:
}

if (jsonObject.contains(JS(type)))
input.type = AccountObjectsHandler::TYPESMAP.at(jv.at(JS(type)).as_string().c_str());
input.type = AccountObjectsHandler::TYPES_MAP.at(jv.at(JS(type)).as_string().c_str());

if (jsonObject.contains(JS(limit)))
input.limit = jv.at(JS(limit)).as_int64();
Expand Down
18 changes: 4 additions & 14 deletions src/rpc/handlers/AccountObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace rpc {
* @brief The account_objects command returns the raw ledger format for all objects owned by an account.
* The results can be filtered by the type.
* The valid types are: check, deposit_preauth, escrow, nft_offer, offer, payment_channel, signer_list, state (trust
* line), and ticket.
* line), did and ticket.
*
* For more details see: https://xrpl.org/account_objects.html
*/
Expand All @@ -42,7 +42,8 @@ class AccountObjectsHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_;

// constants
static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPESMAP;
static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPES_MAP;
static std::unordered_set<std::string> const TYPES_KEYS;

public:
static auto constexpr LIMIT_MIN = 10;
Expand Down Expand Up @@ -89,18 +90,7 @@ class AccountObjectsHandler {
modifiers::Clamp<int32_t>(LIMIT_MIN, LIMIT_MAX)},
{JS(type),
validation::Type<std::string>{},
validation::OneOf<std::string>{
"state",
"ticket",
"signer_list",
"payment_channel",
"offer",
"escrow",
"deposit_preauth",
"check",
"nft_page",
"nft_offer",
}},
validation::OneOf<std::string>(TYPES_KEYS.cbegin(), TYPES_KEYS.cend())},
{JS(marker), validation::AccountMarkerValidator},
{JS(deletion_blockers_only), validation::Type<bool>{}},
};
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/handlers/AccountTx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ std::unordered_map<std::string, ripple::TxType> const AccountTxHandler::TYPESMAP
{JSL(SignerListSet), ripple::ttSIGNER_LIST_SET},
{JSL(TicketCreate), ripple::ttTICKET_CREATE},
{JSL(TrustSet), ripple::ttTRUST_SET},
{JSL(DIDSet), ripple::ttDID_SET},
{JSL(DIDDelete), ripple::ttDID_DELETE},
};

// TODO: should be std::views::keys when clang supports it
Expand Down
1 change: 1 addition & 0 deletions src/rpc/handlers/LedgerData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace rpc {

std::unordered_map<std::string, ripple::LedgerEntryType> const LedgerDataHandler::TYPES_MAP{
{JS(account), ripple::ltACCOUNT_ROOT},
{JS(did), ripple::ltDID},
{JS(amendments), ripple::ltAMENDMENTS},
{JS(check), ripple::ltCHECK},
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
Expand Down
4 changes: 2 additions & 2 deletions src/rpc/handlers/LedgerData.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ class LedgerDataHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_;
util::Logger log_{"RPC"};

static const std::unordered_map<std::string, ripple::LedgerEntryType> TYPES_MAP;
static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPES_MAP;

static const std::unordered_set<std::string> TYPES_KEYS;
static std::unordered_set<std::string> const TYPES_KEYS;

public:
// constants
Expand Down
4 changes: 4 additions & 0 deletions src/rpc/handlers/LedgerEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
key = ripple::uint256{std::string_view(*(input.index))};
} else if (input.accountRoot) {
key = ripple::keylet::account(*ripple::parseBase58<ripple::AccountID>(*(input.accountRoot))).key;
} else if (input.did) {
key = ripple::keylet::did(*ripple::parseBase58<ripple::AccountID>(*(input.did))).key;
} else if (input.directory) {
auto const keyOrStatus = composeKeyFromDirectory(*input.directory);
if (auto const status = std::get_if<Status>(&keyOrStatus))
Expand Down Expand Up @@ -209,6 +211,8 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
// check if request for account root
else if (jsonObject.contains(JS(account_root))) {
input.accountRoot = jv.at(JS(account_root)).as_string().c_str();
} else if (jsonObject.contains(JS(did))) {
input.did = jv.at(JS(did)).as_string().c_str();
}
// no need to check if_object again, validator only allows string or object
else if (jsonObject.contains(JS(directory))) {
Expand Down
3 changes: 3 additions & 0 deletions src/rpc/handlers/LedgerEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class LedgerEntryHandler {
ripple::LedgerEntryType expectedType = ripple::ltANY;
// account id to address account root object
std::optional<std::string> accountRoot;
// account id to address did object
std::optional<std::string> did;
// TODO: extract into custom objects, remove json from Input
std::optional<boost::json::object> directory;
std::optional<boost::json::object> offer;
Expand Down Expand Up @@ -128,6 +130,7 @@ class LedgerEntryHandler {
{JS(ledger_index), validation::LedgerIndexValidator},
{JS(index), malformedRequestHexStringValidator},
{JS(account_root), validation::AccountBase58Validator},
{JS(did), validation::AccountBase58Validator},
{JS(check), malformedRequestHexStringValidator},
{JS(deposit_preauth),
validation::Type<std::string, boost::json::object>{},
Expand Down
16 changes: 16 additions & 0 deletions unittests/rpc/handlers/AccountTxTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,22 @@ static auto
generateTransactionTypeTestValues()
{
return std::vector<AccountTxTransactionBundle>{
AccountTxTransactionBundle{
"DIDSet",
R"({
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"ledger_index": "validated",
"tx_type": "DIDSet"
})",
"[]"},
AccountTxTransactionBundle{
"DIDDelete",
R"({
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"ledger_index": "validated",
"tx_type": "DIDDelete"
})",
"[]"},
AccountTxTransactionBundle{
"AccountSet",
R"({
Expand Down
19 changes: 19 additions & 0 deletions unittests/rpc/handlers/LedgerEntryTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ generateTestValuesForParametersTest()
"malformedAddress",
"Malformed address."},

ParamTestCaseBundle{
"InvalidDidFormat",
R"({
"did": "invalid"
})",
"malformedAddress",
"Malformed address."},

ParamTestCaseBundle{
"InvalidAccountRootNotString",
R"({
Expand Down Expand Up @@ -1041,6 +1049,17 @@ generateTestValuesForNormalPathTest()
),
ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key,
CreateAccountRootObject(ACCOUNT, 0, 1, 1, 1, INDEX1, 1)},
NormalPathTestBundle{
"DID",
fmt::format(
R"({{
"binary": true,
"did": "{}"
}})",
ACCOUNT
),
ripple::keylet::did(GetAccountIDWithString(ACCOUNT)).key,
CreateDidObject(ACCOUNT, "mydocument", "myURI", "mydata")},
NormalPathTestBundle{
"DirectoryViaDirRoot",
fmt::format(
Expand Down
19 changes: 19 additions & 0 deletions unittests/util/TestObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ CreatePaymentTransactionMetaObject(
return metaObj;
}

ripple::STObject
CreateDidObject(std::string_view accountId, std::string_view didDoc, std::string_view uri, std::string_view data)
{
ripple::STObject did(ripple::sfLedgerEntry);
did.setAccountID(ripple::sfAccount, GetAccountIDWithString(accountId));
did.setFieldU16(ripple::sfLedgerEntryType, ripple::ltDID);
did.setFieldU32(ripple::sfFlags, 0);
did.setFieldU64(ripple::sfOwnerNode, 0);
did.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
did.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
ripple::Slice const sliceDoc(didDoc.data(), didDoc.size());
did.setFieldVL(ripple::sfDIDDocument, sliceDoc);
ripple::Slice const sliceUri(uri.data(), uri.size());
did.setFieldVL(ripple::sfURI, sliceUri);
ripple::Slice const sliceData(data.data(), data.size());
did.setFieldVL(ripple::sfData, sliceData);
return did;
}

ripple::STObject
CreateAccountRootObject(
std::string_view accountId,
Expand Down
3 changes: 3 additions & 0 deletions unittests/util/TestObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,6 @@ CreateAMMObject(
std::string_view asset2Currency,
std::string_view asset2Issuer
);

[[nodiscard]] ripple::STObject
CreateDidObject(std::string_view accountId, std::string_view didDoc, std::string_view uri, std::string_view data);