Skip to content

Commit bb72504

Browse files
authored
feat: new runtime API for unique linking (#787)
Part of KILTprotocol/ticket#3650, based on top of #784. Last bit of required functionality. ## Features * Since it's not possible to batch multiple runtime API calls, I introduced a `batch_` version for our old `did` runtime API, which allows to do batching instead of firing one request per lookup * Similarly to that, I introduced a new runtime API (since it's not possible to implement the same API twice for the same runtime), which resolves an account given a name, or a name given an account. This new API also provides a batched version to resolve multiple names or addresses at once. This was one of the requirements we got from Parity to make the solution easier to integrate in the mobile app ## How to test Polkadot Apps support new runtime APIs out of the box. So just compile Peregrine or Spiritnet runtime and spin up a network with Chopsticks. Then: 1. Create a new account-controlled DID. For the Sudo key, use this call `0x401003921cbc0ffe09a865dbf4ae1d0410aa17c656881fe86666da0f97939e3701b674` 2. Claim a new dotname. For the Sudo key, use this call `0x400f921cbc0ffe09a865dbf4ae1d0410aa17c656881fe86666da0f97939e3701b674490020746573742e646f74` 3. Link the Sudo account to the DID. Use this call `0x400f921cbc0ffe09a865dbf4ae1d0410aa17c656881fe86666da0f97939e3701b6744a01` 4. Call the runtime API `uniqueLinking.addressForName("test.dot")` which should return ``` { Ok: { address: { AccountId32: 4rDeMGr3Hi4NfxRUp8qVyhvgW3BSUBLneQisGa9ASkhh2sXB } extra: 4rDeMGr3Hi4NfxRUp8qVyhvgW3BSUBLneQisGa9ASkhh2sXB } } ``` 5. Call the runtime API `uniqueLinking.nameForAddress({AccountId32: "4rDeMGr3Hi4NfxRUp8qVyhvgW3BSUBLneQisGa9ASkhh2sXB"})` which should return ``` { Ok: { name: test.dot extra: 4rDeMGr3Hi4NfxRUp8qVyhvgW3BSUBLneQisGa9ASkhh2sXB } } ```
1 parent 9ffdc32 commit bb72504

File tree

11 files changed

+345
-9
lines changed

11 files changed

+345
-9
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ kilt-runtime-api-dip-provider = { path = "runtime-api/dip-provider", defau
8787
kilt-runtime-api-public-credentials = { path = "runtime-api/public-credentials", default-features = false }
8888
kilt-runtime-api-staking = { path = "runtime-api/staking", default-features = false }
8989
pallet-asset-switch-runtime-api = { path = "runtime-api/asset-switch", default-features = false }
90+
unique-linking-runtime-api = { path = "runtime-api/unique-linking", default-features = false }
9091

9192
# Internal KILT runtimes (with default disabled)
9293
kestrel-runtime = { path = "runtimes/kestrel", default-features = false }

dip-template/runtimes/dip-provider/src/lib.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,18 @@ impl_runtime_apis! {
660660
})
661661
}
662662

663+
fn batch_query_by_web3_name(names: Vec<Vec<u8>>) -> Vec<Option<kilt_runtime_api_did::RawDidLinkedInfo<
664+
DidIdentifier,
665+
AccountId,
666+
LinkableAccountId,
667+
Balance,
668+
Hash,
669+
BlockNumber
670+
>
671+
>> {
672+
names.into_iter().map(Self::query_by_web3_name).collect()
673+
}
674+
663675
fn query_by_account(account: LinkableAccountId) -> Option<
664676
kilt_runtime_api_did::RawDidLinkedInfo<
665677
DidIdentifier,
@@ -689,6 +701,19 @@ impl_runtime_apis! {
689701
})
690702
}
691703

704+
fn batch_query_by_account(accounts: Vec<LinkableAccountId>) -> Vec<Option<
705+
kilt_runtime_api_did::RawDidLinkedInfo<
706+
DidIdentifier,
707+
AccountId,
708+
LinkableAccountId,
709+
Balance,
710+
Hash,
711+
BlockNumber
712+
>
713+
>> {
714+
accounts.into_iter().map(Self::query_by_account).collect()
715+
}
716+
692717
fn query(did: DidIdentifier) -> Option<
693718
kilt_runtime_api_did::RawDidLinkedInfo<
694719
DidIdentifier,
@@ -712,6 +737,19 @@ impl_runtime_apis! {
712737
details: details.into(),
713738
})
714739
}
740+
741+
fn batch_query(dids: Vec<DidIdentifier>) -> Vec<Option<
742+
kilt_runtime_api_did::RawDidLinkedInfo<
743+
DidIdentifier,
744+
AccountId,
745+
LinkableAccountId,
746+
Balance,
747+
Hash,
748+
BlockNumber
749+
>
750+
>> {
751+
dids.into_iter().map(Self::query).collect()
752+
}
715753
}
716754

717755
impl kilt_runtime_api_dip_provider::DipProvider<Block, runtime_api::DipProofRequest, CompleteMerkleProof<Hash, DidMerkleProofOf<Runtime>>, runtime_api::DipProofError> for Runtime {

runtime-api/did/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub type RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance,
6666
>;
6767

6868
sp_api::decl_runtime_apis! {
69-
#[api_version(2)]
69+
#[api_version(3)]
7070
pub trait Did<DidIdentifier, AccountId, LinkableAccountId, Balance, Key: Ord, BlockNumber: MaxEncodedLen> where
7171
DidIdentifier: Codec,
7272
AccountId: Codec,
@@ -84,6 +84,9 @@ sp_api::decl_runtime_apis! {
8484
#[changed_in(2)]
8585
fn query_by_web3_name(name: Vec<u8>) -> Option<RawDidLinkedInfo<DidIdentifier, AccountId, AccountId, Balance, Key, BlockNumber>>;
8686
fn query_by_web3_name(name: Vec<u8>) -> Option<RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance, Key, BlockNumber>>;
87+
/// Allows for batching multiple `query_by_web3_name` requests into one. For each requested name, the corresponding vector entry contains either `Some` or `None` depending on the result of each query.
88+
#[allow(clippy::type_complexity)]
89+
fn batch_query_by_web3_name(names: Vec<Vec<u8>>) -> Vec<Option<RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance, Key, BlockNumber>>>;
8790
/// Given an account address this returns:
8891
/// * the DID
8992
/// * public keys stored for the did
@@ -93,6 +96,9 @@ sp_api::decl_runtime_apis! {
9396
#[changed_in(2)]
9497
fn query_by_account(account: AccountId) -> Option<RawDidLinkedInfo<DidIdentifier, AccountId, AccountId, Balance, Key, BlockNumber>>;
9598
fn query_by_account(account: LinkableAccountId) -> Option<RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance, Key, BlockNumber>>;
99+
/// Allows for batching multiple `query_by_account` requests into one. For each requested name, the corresponding vector entry contains either `Some` or `None` depending on the result of each query.
100+
#[allow(clippy::type_complexity)]
101+
fn batch_query_by_account(accounts: Vec<LinkableAccountId>) -> Vec<Option<RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance, Key, BlockNumber>>>;
96102
/// Given a did this returns:
97103
/// * the DID
98104
/// * public keys stored for the did
@@ -102,5 +108,8 @@ sp_api::decl_runtime_apis! {
102108
#[changed_in(2)]
103109
fn query(did: DidIdentifier) -> Option<RawDidLinkedInfo<DidIdentifier, AccountId, AccountId, Balance, Key, BlockNumber>>;
104110
fn query(did: DidIdentifier) -> Option<RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance, Key, BlockNumber>>;
111+
/// Allows for batching multiple `query` requests into one. For each requested name, the corresponding vector entry contains either `Some` or `None` depending on the result of each query.
112+
#[allow(clippy::type_complexity)]
113+
fn batch_query(dids: Vec<DidIdentifier>) -> Vec<Option<RawDidLinkedInfo<DidIdentifier, AccountId, LinkableAccountId, Balance, Key, BlockNumber>>>;
105114
}
106115
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
authors = { workspace = true }
3+
description = "Runtime APIs for integrating the unique-lookup capabilities."
4+
documentation = { workspace = true }
5+
edition = { workspace = true }
6+
homepage = { workspace = true }
7+
license-file = { workspace = true }
8+
name = "unique-linking-runtime-api"
9+
readme = { workspace = true }
10+
repository = { workspace = true }
11+
version = { workspace = true }
12+
13+
[dependencies]
14+
# External dependencies
15+
parity-scale-codec = { workspace = true }
16+
scale-info = { workspace = true }
17+
18+
# Substrate dependencies
19+
sp-api = { workspace = true }
20+
sp-std = { workspace = true }
21+
22+
[features]
23+
default = ["std"]
24+
std = ["parity-scale-codec/std", "scale-info/std", "sp-api/std", "sp-std/std"]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// KILT Blockchain – https://botlabs.org
2+
// Copyright (C) 2019-2024 BOTLabs GmbH
3+
4+
// The KILT Blockchain is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// The KILT Blockchain is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
// If you feel like getting in touch with us, you can do so at [email protected]
18+
19+
#![cfg_attr(not(feature = "std"), no_std)]
20+
21+
use parity_scale_codec::{Codec, Decode, Encode};
22+
use scale_info::TypeInfo;
23+
use sp_std::vec::Vec;
24+
25+
#[derive(Encode, Decode, TypeInfo)]
26+
pub struct AddressResult<Address, Extra> {
27+
address: Address,
28+
extra: Option<Extra>,
29+
}
30+
31+
impl<Address, Extra> AddressResult<Address, Extra> {
32+
pub const fn new(address: Address, extra: Option<Extra>) -> Self {
33+
Self { address, extra }
34+
}
35+
}
36+
37+
#[derive(Encode, Decode, TypeInfo)]
38+
pub struct NameResult<Name, Extra> {
39+
name: Name,
40+
extra: Option<Extra>,
41+
}
42+
43+
impl<Name, Extra> NameResult<Name, Extra> {
44+
pub const fn new(name: Name, extra: Option<Extra>) -> Self {
45+
Self { name, extra }
46+
}
47+
}
48+
49+
sp_api::decl_runtime_apis! {
50+
pub trait UniqueLinking<Address, Name, Extra> where
51+
Address: Codec,
52+
Name: Codec,
53+
Extra: Codec,
54+
{
55+
fn address_for_name(name: Name) -> Option<AddressResult<Address, Extra>>;
56+
fn batch_address_for_name(names: Vec<Name>) -> Vec<Option<AddressResult<Address, Extra>>>;
57+
fn name_for_address(address: Address) -> Option<NameResult<Name, Extra>>;
58+
fn batch_name_for_address(addresses: Vec<Address>) -> Vec<Option<NameResult<Name, Extra>>>;
59+
}
60+
}

runtimes/kestrel/src/lib.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,18 @@ impl_runtime_apis! {
10341034
})
10351035
}
10361036

1037+
fn batch_query_by_web3_name(names: Vec<Vec<u8>>) -> Vec<Option<kilt_runtime_api_did::RawDidLinkedInfo<
1038+
DidIdentifier,
1039+
AccountId,
1040+
LinkableAccountId,
1041+
Balance,
1042+
Hash,
1043+
BlockNumber
1044+
>
1045+
>> {
1046+
names.into_iter().map(Self::query_by_web3_name).collect()
1047+
}
1048+
10371049
fn query_by_account(account: LinkableAccountId) -> Option<
10381050
kilt_runtime_api_did::RawDidLinkedInfo<
10391051
DidIdentifier,
@@ -1063,6 +1075,19 @@ impl_runtime_apis! {
10631075
})
10641076
}
10651077

1078+
fn batch_query_by_account(accounts: Vec<LinkableAccountId>) -> Vec<Option<
1079+
kilt_runtime_api_did::RawDidLinkedInfo<
1080+
DidIdentifier,
1081+
AccountId,
1082+
LinkableAccountId,
1083+
Balance,
1084+
Hash,
1085+
BlockNumber
1086+
>
1087+
>> {
1088+
accounts.into_iter().map(Self::query_by_account).collect()
1089+
}
1090+
10661091
fn query(did: DidIdentifier) -> Option<
10671092
kilt_runtime_api_did::RawDidLinkedInfo<
10681093
DidIdentifier,
@@ -1086,6 +1111,19 @@ impl_runtime_apis! {
10861111
details: details.into(),
10871112
})
10881113
}
1114+
1115+
fn batch_query(dids: Vec<DidIdentifier>) -> Vec<Option<
1116+
kilt_runtime_api_did::RawDidLinkedInfo<
1117+
DidIdentifier,
1118+
AccountId,
1119+
LinkableAccountId,
1120+
Balance,
1121+
Hash,
1122+
BlockNumber
1123+
>
1124+
>> {
1125+
dids.into_iter().map(Self::query).collect()
1126+
}
10891127
}
10901128

10911129
impl kilt_runtime_api_public_credentials::PublicCredentials<Block, Vec<u8>, Hash, public_credentials::CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<<Runtime as delegation::Config>::DelegationNodeId>>, PublicCredentialsFilter<Hash, AccountId>, PublicCredentialsApiError> for Runtime {

runtimes/peregrine/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ kilt-runtime-api-public-credentials = { workspace = true }
3333
kilt-runtime-api-staking = { workspace = true }
3434
pallet-asset-switch-runtime-api = { workspace = true }
3535
pallet-transaction-payment-rpc-runtime-api = { workspace = true }
36+
unique-linking-runtime-api = { workspace = true }
3637

3738
# KILT pallets & primitives
3839
attestation = { workspace = true }
@@ -247,6 +248,7 @@ std = [
247248
"sp-transaction-pool/std",
248249
"sp-version/std",
249250
"sp-weights/std",
251+
"unique-linking-runtime-api/std",
250252
"xcm-builder/std",
251253
"xcm-executor/std",
252254
"xcm/std",

0 commit comments

Comments
 (0)