DID: Decentralized identifiers (DIDs) (XLS-40): (#4636)

Implement native support for W3C DIDs.

Add a new ledger object: `DID`.

Add two new transactions:
1. `DIDSet`: create or update the `DID` object.
2. `DIDDelete`: delete the `DID` object.

This meets the requirements specified in the DID v1.0 specification
currently recommended by the W3C Credentials Community Group.

The DID format for the XRP Ledger conforms to W3C DID standards.
The objects can be created and owned by any XRPL account holder.
The transactions can be integrated by any service, wallet, or application.
This commit is contained in:
Mayukha Vadari
2023-10-18 16:01:12 -04:00
committed by GitHub
parent 41cd337506
commit b421945e71
30 changed files with 1063 additions and 7 deletions

View File

@@ -599,6 +599,7 @@ public:
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amm), 0));
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::did), 0));
// gw mints an NFT so we can find it.
uint256 const nftID{token::getNextID(env, gw, 0u, tfTransferable)};
@@ -854,6 +855,26 @@ public:
BEAST_EXPECT(
payChan[sfSettleDelay.jsonName].asUInt() == 24 * 60 * 60);
}
{
// gw creates a DID that we can look for in the ledger.
Json::Value jvDID;
jvDID[jss::TransactionType] = jss::DIDSet;
jvDID[jss::Flags] = tfUniversal;
jvDID[jss::Account] = gw.human();
jvDID[sfURI.jsonName] = strHex(std::string{"uri"});
env(jvDID);
env.close();
}
{
// Find the DID.
Json::Value const resp = acct_objs(gw, jss::did);
BEAST_EXPECT(acct_objs_is_size(resp, 1));
auto const& did = resp[jss::result][jss::account_objects][0u];
BEAST_EXPECT(did[sfAccount.jsonName] == gw.human());
BEAST_EXPECT(did[sfURI.jsonName] == strHex(std::string{"uri"}));
}
// Make gw multisigning by adding a signerList.
env(jtx::signers(gw, 6, {{alice, 7}}));
env.close();
@@ -881,7 +902,7 @@ public:
auto const& ticket = resp[jss::result][jss::account_objects][0u];
BEAST_EXPECT(ticket[sfAccount.jsonName] == gw.human());
BEAST_EXPECT(ticket[sfLedgerEntryType.jsonName] == jss::Ticket);
BEAST_EXPECT(ticket[sfTicketSequence.jsonName].asUInt() == 13);
BEAST_EXPECT(ticket[sfTicketSequence.jsonName].asUInt() == 14);
}
{
// See how "deletion_blockers_only" handles gw's directory.