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

feat: basic DIP structure #489

Merged
merged 71 commits into from
Apr 4, 2023
Merged

feat: basic DIP structure #489

merged 71 commits into from
Apr 4, 2023

Conversation

ntn-x2
Copy link
Member

@ntn-x2 ntn-x2 commented Mar 15, 2023

Fixes https://github.com/KILTprotocol/ticket/issues/2550.

This PR will merge the changes into the aa/dip branch, which will be the base branch for all the future DIP improvements until we reach a version that we can merge into develop and deploy on some testnets in the Peregrine runtime.

Base structure for DIP

This PR contains the following components:

  • A pallet to send identity information to one or more destinations (DIP sender)
  • A pallet to receive such identity information from a source (DIP receiver)
  • A support crate that contains common (versioned) types, in future also traits and auxiliary functions, if needed
  • A template project consisting of 1. a template runtime for the dip-sender, with its node counterpart, 2. a template runtime for the dip-receiver, with its node counterpart, 3. an example XCM integration test using XCM emulator (not simulator) which connects the two template runtimes with a local Rococo relay chain.

Design

The current version assumes that anyone on the sender chain can dispatch identity information on some target chain (with which there exists an open HRMP channel). Ultimately, all the fees for dispatching the message and process it on the receiver side will be paid by the extrinsic submitter on the target chain. Right now, the submitter only pays for the extrinsic dispatch on the source chain, and the chain itself uses its own balance (liked to its sovereign account) on the target chain to pay for the Transact execution. The Transact operation that interacts with the dip-receiver pallet on the target chain has an OriginKind::Native, so that there is no way for any user on the source chain to dispatch such messages.

Right now, the basic structure and the templates use defaults for everything, from proof generation to proof verification. One step at the time, all these defaults will be replaced with the actual features. Nevertheless, for two chains that have the same concept of Identifier and AccountId, it is already possible to demo the complete e2e flow. For the sake of our demonstration, the flow would go as follow, assuming that both the source and target chains are registered as parachain on the same relaychain:

  1. The source chain requests to open an HRMP channel with the target chain
  2. The target chain accepts the request and the channel is open
  3. The target chain issues some funds (enough to cover the demo use case) to the sender chain's sovereign account
  4. A user on the source chain creates a DID with a single authentication key
  5. The same user (but could be anyone else), calls the extrinsic on the dip-sender pallet to send the merkle root of the DID to the target chain, paying for the dispatch fee
  6. The source chain sends the information to the target chain
  7. The user calls the dispatch_as extrinsic of the dip-receiver pallet which is deployed on the target chain, providing a merkle proof of their DID document + details on the source chain. For now this check always returns true.
  8. Inside, the dispatch_as has a nested call which is dispatched with the new DipOrigin, which pallets can now use if they expect extrinsics to be DID-authorized.

What's coming

I created tickets for each of the next steps, under the DIP milestone. The tickets will take care of:

  • Adding benchmarks and weights
  • Introducing proper error handling
  • Introducing proper DID signature verificaiton on the target template chain (right now it's just a default behaviour)
  • Introducing proper merkle proof generation (I tested that it works, but removed those pieces from this PR for the ease of understanding)
  • Introducing proper merkle proof verification (same as above)
  • Adding an emergency brake in the sender pallet to stop dispatching messages to a specific destination, e.g., if the sender sovereign account on the destination chain does not have any more or if the Transact encoding would fail
  • Adding support for metadata beyond the simple DID details, e.g., proof expiration time, etc.
  • Replacing user-provided weights and assets with per-chain configurations stored in the sender pallet
  • More comments (I can work on this first if the code as it is it's too hard to follow)
  • Adding support for version negotiation. There is a basic concept of versioning right now, but it can and should be expanded and improved.
  • More unit and integration tests.

Probably more tickets will come out of this work, and will be tracked separately in the same or in future milestones.

How to test

A basic integration test of the two template runtimes is present in the dip-templates-xcm-tests crate, inside the dip-template/runtimes/xcm-tests. It can be run as usual with cargo test -p dip-templates-xcm-tests.

Comment on lines +131 to +132
let _ = T::ProofVerifier::verify_proof_against_digest(proof, proof_digest)
.map_err(|_| Error::<T>::InvalidProof)?;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the call as part of the proof verification. Shouldn't the proof or something check to make sure that the call is not someone front running and actually requested by the DID owner?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, yes, that's in the making! This is the skeleton PR. There's no logic yet in here, but there will be a trait implemented for the RuntimeCall type which dictates which calls require the Dip origin, and if so, which key relationship must be used in the signature.
We already use it in our blockchain to define which calls require a DID origin and which don't ->

impl did::DeriveDidCallAuthorizationVerificationKeyRelationship for RuntimeCall {
.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also DID signature verification is not yet in there, but it would work similarly to what we have on our chain in the submit_did_call extrinsic:

pub fn submit_did_call(
.

So the receiver chain would keep track of the last used nonce, so that it's not possible to replay actions nor front-run anything if one action is dependent on another (i.e., the first nonce has to be 1 less than the next one).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Cool! Thanks!

Copy link
Contributor

@weichweich weichweich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work.

My thoughts on this:

  • there are a few unrelated changes, would be great to move them to a separate PR
  • I don't understand the ReceiverParachainDipReceiverCalls and ReceiverParachainCalls
  • I feel like Receiver and Sender are not the best wordings here?
    • Isn't Provider and relying-party what openID uses? I feel like this would describe it better? In the end sending and receiving is only done to read the storage. If we use another strategy to access the parachains storage, this wouldn't be sending/receiving anymore
  • Is this future proof for new technology?
    • The consensus in the community seems to be, that storage proofs should be used to read another chains storage. Here we use XCM. We should at least make sure we can switch later to the other mechanism?

dip-template/runtimes/dip-sender/src/dip.rs Show resolved Hide resolved
dip-template/runtimes/dip-sender/src/dip.rs Show resolved Hide resolved
nodes/parachain/Cargo.toml Outdated Show resolved Hide resolved
pallets/pallet-dip-receiver/src/lib.rs Show resolved Hide resolved
pallets/pallet-dip-receiver/src/origin.rs Outdated Show resolved Hide resolved
}

// Always returns success.
pub struct SuccessfulProofVerifier<ProofDigest, LeafKey, LeafValue>(PhantomData<(ProofDigest, LeafKey, LeafValue)>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably only be used in tests and benchmarks?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in the shell template runtime, inside this PR. It could also be used in some mock environment. How would you suggest to change or feature-gate this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in some pallets with have a mock feature for that

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in the actual runtime template, so we can't use any features. It will be deprecated with the new merkle proof PR, but here it's used here: https://github.com/KILTprotocol/kilt-node/pull/489/files#diff-6c40e72378ea467c86621567df431cc2dabb74d5b76ef2a25fa43a16cf568e00R32

@ntn-x2
Copy link
Member Author

ntn-x2 commented Mar 27, 2023

Isn't Provider and relying-party what openID uses? I feel like this would describe it better? In the end sending and receiving is only done to read the storage. If we use another strategy to access the parachains storage, this wouldn't be sending/receiving anymore

Gotcha. I will rename them everywhere. In order to avoid merge hell, I made a ticket and will tackle this in the future. But your is a valid point, as other people have had the same confusion.

Is this future proof for new technology?

As mentioned elsewhere, versioning is not completely baked in here, and will be part of a different ticket, most likely after the other big feature milestone have been reached, e.g., call-based verification and actual DID signature verification. But we already have a ticket for versioning, where we can discuss how future-proof the implementation will be, at that point.

@ntn-x2 ntn-x2 removed ✨ new feature feature: new feature ⛓ KILT node labels Mar 28, 2023
@ntn-x2 ntn-x2 merged commit 98de546 into aa/dip Apr 4, 2023
@ntn-x2 ntn-x2 deleted the aa/dip-take-2 branch April 4, 2023 14:48
ntn-x2 added a commit that referenced this pull request Apr 6, 2023
Fixes KILTprotocol/ticket#2550.

**This PR will merge the changes into the `aa/dip` branch, which will be
the base branch for all the future DIP improvements until we reach a
version that we can merge into `develop` and deploy on some testnets in
the Peregrine runtime.**

## Base structure for DIP

This PR contains the following components:

* A pallet to send identity information to one or more destinations (DIP
sender)
* A pallet to receive such identity information from a source (DIP
receiver)
* A support crate that contains common (versioned) types, in future also
traits and auxiliary functions, if needed
* A template project consisting of 1. a template runtime for the
dip-sender, with its node counterpart, 2. a template runtime for the
dip-receiver, with its node counterpart, 3. an example XCM integration
test using [XCM emulator](https://github.com/shaunxw/xcm-simulator) (not
simulator) which connects the two template runtimes with a local Rococo
relay chain.

### Design

The current version assumes that anyone on the sender chain can dispatch
identity information on some target chain (with which there exists an
open HRMP channel). Ultimately, all the fees for dispatching the message
and process it on the receiver side will be paid by the extrinsic
submitter on the target chain. Right now, the submitter only pays for
the extrinsic dispatch on the source chain, and the chain itself uses
its own balance (liked to its sovereign account) on the target chain to
pay for the `Transact` execution. The `Transact` operation that
interacts with the `dip-receiver` pallet on the target chain has an
`OriginKind::Native`, so that there is no way for any user on the source
chain to dispatch such messages.

Right now, the basic structure and the templates use defaults for
everything, from proof generation to proof verification. One step at the
time, all these defaults will be replaced with the actual features.
Nevertheless, for two chains that have the same concept of `Identifier`
and `AccountId`, it is already possible to demo the complete e2e flow.
For the sake of our demonstration, the flow would go as follow,
**assuming that both the source and target chains are registered as
parachain on the same relaychain**:

1. The source chain requests to open an HRMP channel with the target
chain
2. The target chain accepts the request and the channel is open
3. The target chain issues some funds (enough to cover the demo use
case) to the sender chain's sovereign account
4. A user on the source chain creates a DID with a single authentication
key
5. The same user (but could be anyone else), calls the extrinsic on the
`dip-sender` pallet to send the merkle root of the DID to the target
chain, paying for the dispatch fee
6. The source chain sends the information to the target chain
7. The user calls the `dispatch_as` extrinsic of the `dip-receiver`
pallet which is deployed on the target chain, providing a merkle proof
of their DID document + details on the source chain. For now this check
always returns true.
8. Inside, the `dispatch_as` has a nested call which is dispatched with
the new `DipOrigin`, which pallets can now use if they expect extrinsics
to be DID-authorized.

## What's coming

I created tickets for each of the next steps, under the DIP milestone.
The tickets will take care of:

* Adding benchmarks and weights
* Introducing proper error handling
* Introducing proper DID signature verificaiton on the target template
chain (right now it's just a default behaviour)
* Introducing proper merkle proof generation (I tested that it works,
but removed those pieces from this PR for the ease of understanding)
* Introducing proper merkle proof verification (same as above)
* Adding an emergency brake in the sender pallet to stop dispatching
messages to a specific destination, e.g., if the sender sovereign
account on the destination chain does not have any more or if the
`Transact` encoding would fail
* Adding support for metadata beyond the simple DID details, e.g., proof
expiration time, etc.
* Replacing user-provided weights and assets with per-chain
configurations stored in the sender pallet
* More comments (I can work on this first if the code as it is it's too
hard to follow)
* Adding support for version negotiation. There is a basic concept of
versioning right now, but it can and should be expanded and improved.
* More unit and integration tests.

Probably more tickets will come out of this work, and will be tracked
separately in the same or in future milestones.

## How to test

A basic integration test of the two template runtimes is present in the
`dip-templates-xcm-tests` crate, inside the
`dip-template/runtimes/xcm-tests`. It can be run as usual with `cargo
test -p dip-templates-xcm-tests`.
ntn-x2 added a commit that referenced this pull request Apr 6, 2023
Fixes KILTprotocol/ticket#2557 and fixes
KILTprotocol/ticket#2556.

This PR builds on top of the shell PR, and adds support for Merkle proof
for DID documents.

## Merkle proof structure

A DID merkle proof is, at the core, an order set of (key, value) pairs,
on which proof-of-inclusion and proof-of-non-inclusion can be performed.
This PR generates and validates merkle proofs where leaves are of two
types:

- a DID key reference leave, whose key is the tuple (key ID, key
relationship) and the value is an empty tuple
- a DID key details leave, whose key is the key ID and the value is the
key details

For each key reference leaf with a given key ID, the proof also has to
contain a key details leaf whose key is the key ID. Multiple reference
leaves can reference the same key details leaf, optimising the storage
size.

## New runtime APIs

There is a new runtime API which the DIP sender would expose, and that
allows anyone to generate a merkle proof for a given DID identifier and
set of key IDs. The result contains the merkle root (which must match
what other chains have stored in their `pallet-dip-receiver` map), and a
merkle proof, which includes blinded values and a set of key reference
and key details leaves for the keys identified by the provided key IDs.

## How to test

The setup flow is similar to that of
#489.
Specifically:

- Set up the local Rococo network onboarding the sender and receiver
chains with para IDs 2_000 and 2_001 respectively
- Open an HRMP channel from sender 2_000 to receiver 2_001
- Create a DID on the sender chain, e.g., using the
[kilt-did-utilities](https://github.com/KILTprotocol/kilt-did-utilities)
tool
![Screenshot 2023-03-27 at 10 00
48](https://user-images.githubusercontent.com/6704504/227900994-41f0f355-84bd-4b8a-a2a8-3a9c74447e59.png)
- Push the identity of the DID to the receiver chain via the
`pallet-dip-sender` extrinsic
![Screenshot 2023-03-27 at 10 01
13](https://user-images.githubusercontent.com/6704504/227901150-7e8c9c9d-8aac-4739-8ad3-fad4ba6ff5f8.png)
- Call the runtime API to generate a proof for the created DID with some
keys revealed
![Screenshot 2023-03-27 at 10 01
40](https://user-images.githubusercontent.com/6704504/227901309-94b4dbc9-ca83-4541-820d-d1bec6adc6f0.png)
- Use the generated proof to dispatch an extrinsic on the receiving
chain

### How to use the runtime API with polkadot apps

There is currently no support for the new runtime API in the public
polkadot apps instance. To use the runtime APIs from UI, please use [our
fork from the aa/dip-sender-template
branch](https://github.com/KILTprotocol/polkadot-apps/tree/aa/dip-sender-template),
by running `yarn && yarn build && yarn start`, then connecting to the
sender node WS socket.
For runtime augmentation within a Node script, please use our [SDK repo
from the aa/dip-merkle-proof
branch](https://github.com/KILTprotocol/sdk-js/tree/aa/dip-merkle-proof).
ntn-x2 added a commit that referenced this pull request Apr 17, 2023
Fixes KILTprotocol/ticket#2550.

**This PR will merge the changes into the `aa/dip` branch, which will be
the base branch for all the future DIP improvements until we reach a
version that we can merge into `develop` and deploy on some testnets in
the Peregrine runtime.**

## Base structure for DIP

This PR contains the following components:

* A pallet to send identity information to one or more destinations (DIP
sender)
* A pallet to receive such identity information from a source (DIP
receiver)
* A support crate that contains common (versioned) types, in future also
traits and auxiliary functions, if needed
* A template project consisting of 1. a template runtime for the
dip-sender, with its node counterpart, 2. a template runtime for the
dip-receiver, with its node counterpart, 3. an example XCM integration
test using [XCM emulator](https://github.com/shaunxw/xcm-simulator) (not
simulator) which connects the two template runtimes with a local Rococo
relay chain.

### Design

The current version assumes that anyone on the sender chain can dispatch
identity information on some target chain (with which there exists an
open HRMP channel). Ultimately, all the fees for dispatching the message
and process it on the receiver side will be paid by the extrinsic
submitter on the target chain. Right now, the submitter only pays for
the extrinsic dispatch on the source chain, and the chain itself uses
its own balance (liked to its sovereign account) on the target chain to
pay for the `Transact` execution. The `Transact` operation that
interacts with the `dip-receiver` pallet on the target chain has an
`OriginKind::Native`, so that there is no way for any user on the source
chain to dispatch such messages.

Right now, the basic structure and the templates use defaults for
everything, from proof generation to proof verification. One step at the
time, all these defaults will be replaced with the actual features.
Nevertheless, for two chains that have the same concept of `Identifier`
and `AccountId`, it is already possible to demo the complete e2e flow.
For the sake of our demonstration, the flow would go as follow,
**assuming that both the source and target chains are registered as
parachain on the same relaychain**:

1. The source chain requests to open an HRMP channel with the target
chain
2. The target chain accepts the request and the channel is open
3. The target chain issues some funds (enough to cover the demo use
case) to the sender chain's sovereign account
4. A user on the source chain creates a DID with a single authentication
key
5. The same user (but could be anyone else), calls the extrinsic on the
`dip-sender` pallet to send the merkle root of the DID to the target
chain, paying for the dispatch fee
6. The source chain sends the information to the target chain
7. The user calls the `dispatch_as` extrinsic of the `dip-receiver`
pallet which is deployed on the target chain, providing a merkle proof
of their DID document + details on the source chain. For now this check
always returns true.
8. Inside, the `dispatch_as` has a nested call which is dispatched with
the new `DipOrigin`, which pallets can now use if they expect extrinsics
to be DID-authorized.

## What's coming

I created tickets for each of the next steps, under the DIP milestone.
The tickets will take care of:

* Adding benchmarks and weights
* Introducing proper error handling
* Introducing proper DID signature verificaiton on the target template
chain (right now it's just a default behaviour)
* Introducing proper merkle proof generation (I tested that it works,
but removed those pieces from this PR for the ease of understanding)
* Introducing proper merkle proof verification (same as above)
* Adding an emergency brake in the sender pallet to stop dispatching
messages to a specific destination, e.g., if the sender sovereign
account on the destination chain does not have any more or if the
`Transact` encoding would fail
* Adding support for metadata beyond the simple DID details, e.g., proof
expiration time, etc.
* Replacing user-provided weights and assets with per-chain
configurations stored in the sender pallet
* More comments (I can work on this first if the code as it is it's too
hard to follow)
* Adding support for version negotiation. There is a basic concept of
versioning right now, but it can and should be expanded and improved.
* More unit and integration tests.

Probably more tickets will come out of this work, and will be tracked
separately in the same or in future milestones.

## How to test

A basic integration test of the two template runtimes is present in the
`dip-templates-xcm-tests` crate, inside the
`dip-template/runtimes/xcm-tests`. It can be run as usual with `cargo
test -p dip-templates-xcm-tests`.
ntn-x2 added a commit that referenced this pull request Apr 17, 2023
Fixes KILTprotocol/ticket#2557 and fixes
KILTprotocol/ticket#2556.

This PR builds on top of the shell PR, and adds support for Merkle proof
for DID documents.

## Merkle proof structure

A DID merkle proof is, at the core, an order set of (key, value) pairs,
on which proof-of-inclusion and proof-of-non-inclusion can be performed.
This PR generates and validates merkle proofs where leaves are of two
types:

- a DID key reference leave, whose key is the tuple (key ID, key
relationship) and the value is an empty tuple
- a DID key details leave, whose key is the key ID and the value is the
key details

For each key reference leaf with a given key ID, the proof also has to
contain a key details leaf whose key is the key ID. Multiple reference
leaves can reference the same key details leaf, optimising the storage
size.

## New runtime APIs

There is a new runtime API which the DIP sender would expose, and that
allows anyone to generate a merkle proof for a given DID identifier and
set of key IDs. The result contains the merkle root (which must match
what other chains have stored in their `pallet-dip-receiver` map), and a
merkle proof, which includes blinded values and a set of key reference
and key details leaves for the keys identified by the provided key IDs.

## How to test

The setup flow is similar to that of
#489.
Specifically:

- Set up the local Rococo network onboarding the sender and receiver
chains with para IDs 2_000 and 2_001 respectively
- Open an HRMP channel from sender 2_000 to receiver 2_001
- Create a DID on the sender chain, e.g., using the
[kilt-did-utilities](https://github.com/KILTprotocol/kilt-did-utilities)
tool
![Screenshot 2023-03-27 at 10 00
48](https://user-images.githubusercontent.com/6704504/227900994-41f0f355-84bd-4b8a-a2a8-3a9c74447e59.png)
- Push the identity of the DID to the receiver chain via the
`pallet-dip-sender` extrinsic
![Screenshot 2023-03-27 at 10 01
13](https://user-images.githubusercontent.com/6704504/227901150-7e8c9c9d-8aac-4739-8ad3-fad4ba6ff5f8.png)
- Call the runtime API to generate a proof for the created DID with some
keys revealed
![Screenshot 2023-03-27 at 10 01
40](https://user-images.githubusercontent.com/6704504/227901309-94b4dbc9-ca83-4541-820d-d1bec6adc6f0.png)
- Use the generated proof to dispatch an extrinsic on the receiving
chain

### How to use the runtime API with polkadot apps

There is currently no support for the new runtime API in the public
polkadot apps instance. To use the runtime APIs from UI, please use [our
fork from the aa/dip-sender-template
branch](https://github.com/KILTprotocol/polkadot-apps/tree/aa/dip-sender-template),
by running `yarn && yarn build && yarn start`, then connecting to the
sender node WS socket.
For runtime augmentation within a Node script, please use our [SDK repo
from the aa/dip-merkle-proof
branch](https://github.com/KILTprotocol/sdk-js/tree/aa/dip-merkle-proof).
ntn-x2 added a commit that referenced this pull request Apr 19, 2023
Fixes KILTprotocol/ticket#2550.

**This PR will merge the changes into the `aa/dip` branch, which will be
the base branch for all the future DIP improvements until we reach a
version that we can merge into `develop` and deploy on some testnets in
the Peregrine runtime.**

## Base structure for DIP

This PR contains the following components:

* A pallet to send identity information to one or more destinations (DIP
sender)
* A pallet to receive such identity information from a source (DIP
receiver)
* A support crate that contains common (versioned) types, in future also
traits and auxiliary functions, if needed
* A template project consisting of 1. a template runtime for the
dip-sender, with its node counterpart, 2. a template runtime for the
dip-receiver, with its node counterpart, 3. an example XCM integration
test using [XCM emulator](https://github.com/shaunxw/xcm-simulator) (not
simulator) which connects the two template runtimes with a local Rococo
relay chain.

### Design

The current version assumes that anyone on the sender chain can dispatch
identity information on some target chain (with which there exists an
open HRMP channel). Ultimately, all the fees for dispatching the message
and process it on the receiver side will be paid by the extrinsic
submitter on the target chain. Right now, the submitter only pays for
the extrinsic dispatch on the source chain, and the chain itself uses
its own balance (liked to its sovereign account) on the target chain to
pay for the `Transact` execution. The `Transact` operation that
interacts with the `dip-receiver` pallet on the target chain has an
`OriginKind::Native`, so that there is no way for any user on the source
chain to dispatch such messages.

Right now, the basic structure and the templates use defaults for
everything, from proof generation to proof verification. One step at the
time, all these defaults will be replaced with the actual features.
Nevertheless, for two chains that have the same concept of `Identifier`
and `AccountId`, it is already possible to demo the complete e2e flow.
For the sake of our demonstration, the flow would go as follow,
**assuming that both the source and target chains are registered as
parachain on the same relaychain**:

1. The source chain requests to open an HRMP channel with the target
chain
2. The target chain accepts the request and the channel is open
3. The target chain issues some funds (enough to cover the demo use
case) to the sender chain's sovereign account
4. A user on the source chain creates a DID with a single authentication
key
5. The same user (but could be anyone else), calls the extrinsic on the
`dip-sender` pallet to send the merkle root of the DID to the target
chain, paying for the dispatch fee
6. The source chain sends the information to the target chain
7. The user calls the `dispatch_as` extrinsic of the `dip-receiver`
pallet which is deployed on the target chain, providing a merkle proof
of their DID document + details on the source chain. For now this check
always returns true.
8. Inside, the `dispatch_as` has a nested call which is dispatched with
the new `DipOrigin`, which pallets can now use if they expect extrinsics
to be DID-authorized.

## What's coming

I created tickets for each of the next steps, under the DIP milestone.
The tickets will take care of:

* Adding benchmarks and weights
* Introducing proper error handling
* Introducing proper DID signature verificaiton on the target template
chain (right now it's just a default behaviour)
* Introducing proper merkle proof generation (I tested that it works,
but removed those pieces from this PR for the ease of understanding)
* Introducing proper merkle proof verification (same as above)
* Adding an emergency brake in the sender pallet to stop dispatching
messages to a specific destination, e.g., if the sender sovereign
account on the destination chain does not have any more or if the
`Transact` encoding would fail
* Adding support for metadata beyond the simple DID details, e.g., proof
expiration time, etc.
* Replacing user-provided weights and assets with per-chain
configurations stored in the sender pallet
* More comments (I can work on this first if the code as it is it's too
hard to follow)
* Adding support for version negotiation. There is a basic concept of
versioning right now, but it can and should be expanded and improved.
* More unit and integration tests.

Probably more tickets will come out of this work, and will be tracked
separately in the same or in future milestones.

## How to test

A basic integration test of the two template runtimes is present in the
`dip-templates-xcm-tests` crate, inside the
`dip-template/runtimes/xcm-tests`. It can be run as usual with `cargo
test -p dip-templates-xcm-tests`.
ntn-x2 added a commit that referenced this pull request Apr 19, 2023
Fixes KILTprotocol/ticket#2557 and fixes
KILTprotocol/ticket#2556.

This PR builds on top of the shell PR, and adds support for Merkle proof
for DID documents.

## Merkle proof structure

A DID merkle proof is, at the core, an order set of (key, value) pairs,
on which proof-of-inclusion and proof-of-non-inclusion can be performed.
This PR generates and validates merkle proofs where leaves are of two
types:

- a DID key reference leave, whose key is the tuple (key ID, key
relationship) and the value is an empty tuple
- a DID key details leave, whose key is the key ID and the value is the
key details

For each key reference leaf with a given key ID, the proof also has to
contain a key details leaf whose key is the key ID. Multiple reference
leaves can reference the same key details leaf, optimising the storage
size.

## New runtime APIs

There is a new runtime API which the DIP sender would expose, and that
allows anyone to generate a merkle proof for a given DID identifier and
set of key IDs. The result contains the merkle root (which must match
what other chains have stored in their `pallet-dip-receiver` map), and a
merkle proof, which includes blinded values and a set of key reference
and key details leaves for the keys identified by the provided key IDs.

## How to test

The setup flow is similar to that of
#489.
Specifically:

- Set up the local Rococo network onboarding the sender and receiver
chains with para IDs 2_000 and 2_001 respectively
- Open an HRMP channel from sender 2_000 to receiver 2_001
- Create a DID on the sender chain, e.g., using the
[kilt-did-utilities](https://github.com/KILTprotocol/kilt-did-utilities)
tool
![Screenshot 2023-03-27 at 10 00
48](https://user-images.githubusercontent.com/6704504/227900994-41f0f355-84bd-4b8a-a2a8-3a9c74447e59.png)
- Push the identity of the DID to the receiver chain via the
`pallet-dip-sender` extrinsic
![Screenshot 2023-03-27 at 10 01
13](https://user-images.githubusercontent.com/6704504/227901150-7e8c9c9d-8aac-4739-8ad3-fad4ba6ff5f8.png)
- Call the runtime API to generate a proof for the created DID with some
keys revealed
![Screenshot 2023-03-27 at 10 01
40](https://user-images.githubusercontent.com/6704504/227901309-94b4dbc9-ca83-4541-820d-d1bec6adc6f0.png)
- Use the generated proof to dispatch an extrinsic on the receiving
chain

### How to use the runtime API with polkadot apps

There is currently no support for the new runtime API in the public
polkadot apps instance. To use the runtime APIs from UI, please use [our
fork from the aa/dip-sender-template
branch](https://github.com/KILTprotocol/polkadot-apps/tree/aa/dip-sender-template),
by running `yarn && yarn build && yarn start`, then connecting to the
sender node WS socket.
For runtime augmentation within a Node script, please use our [SDK repo
from the aa/dip-merkle-proof
branch](https://github.com/KILTprotocol/sdk-js/tree/aa/dip-merkle-proof).
@ntn-x2 ntn-x2 mentioned this pull request Apr 20, 2023
30 tasks
ntn-x2 added a commit that referenced this pull request May 22, 2023
Fixes KILTprotocol/ticket#2550.

**This PR will merge the changes into the `aa/dip` branch, which will be
the base branch for all the future DIP improvements until we reach a
version that we can merge into `develop` and deploy on some testnets in
the Peregrine runtime.**

## Base structure for DIP

This PR contains the following components:

* A pallet to send identity information to one or more destinations (DIP
sender)
* A pallet to receive such identity information from a source (DIP
receiver)
* A support crate that contains common (versioned) types, in future also
traits and auxiliary functions, if needed
* A template project consisting of 1. a template runtime for the
dip-sender, with its node counterpart, 2. a template runtime for the
dip-receiver, with its node counterpart, 3. an example XCM integration
test using [XCM emulator](https://github.com/shaunxw/xcm-simulator) (not
simulator) which connects the two template runtimes with a local Rococo
relay chain.

### Design

The current version assumes that anyone on the sender chain can dispatch
identity information on some target chain (with which there exists an
open HRMP channel). Ultimately, all the fees for dispatching the message
and process it on the receiver side will be paid by the extrinsic
submitter on the target chain. Right now, the submitter only pays for
the extrinsic dispatch on the source chain, and the chain itself uses
its own balance (liked to its sovereign account) on the target chain to
pay for the `Transact` execution. The `Transact` operation that
interacts with the `dip-receiver` pallet on the target chain has an
`OriginKind::Native`, so that there is no way for any user on the source
chain to dispatch such messages.

Right now, the basic structure and the templates use defaults for
everything, from proof generation to proof verification. One step at the
time, all these defaults will be replaced with the actual features.
Nevertheless, for two chains that have the same concept of `Identifier`
and `AccountId`, it is already possible to demo the complete e2e flow.
For the sake of our demonstration, the flow would go as follow,
**assuming that both the source and target chains are registered as
parachain on the same relaychain**:

1. The source chain requests to open an HRMP channel with the target
chain
2. The target chain accepts the request and the channel is open
3. The target chain issues some funds (enough to cover the demo use
case) to the sender chain's sovereign account
4. A user on the source chain creates a DID with a single authentication
key
5. The same user (but could be anyone else), calls the extrinsic on the
`dip-sender` pallet to send the merkle root of the DID to the target
chain, paying for the dispatch fee
6. The source chain sends the information to the target chain
7. The user calls the `dispatch_as` extrinsic of the `dip-receiver`
pallet which is deployed on the target chain, providing a merkle proof
of their DID document + details on the source chain. For now this check
always returns true.
8. Inside, the `dispatch_as` has a nested call which is dispatched with
the new `DipOrigin`, which pallets can now use if they expect extrinsics
to be DID-authorized.

## What's coming

I created tickets for each of the next steps, under the DIP milestone.
The tickets will take care of:

* Adding benchmarks and weights
* Introducing proper error handling
* Introducing proper DID signature verificaiton on the target template
chain (right now it's just a default behaviour)
* Introducing proper merkle proof generation (I tested that it works,
but removed those pieces from this PR for the ease of understanding)
* Introducing proper merkle proof verification (same as above)
* Adding an emergency brake in the sender pallet to stop dispatching
messages to a specific destination, e.g., if the sender sovereign
account on the destination chain does not have any more or if the
`Transact` encoding would fail
* Adding support for metadata beyond the simple DID details, e.g., proof
expiration time, etc.
* Replacing user-provided weights and assets with per-chain
configurations stored in the sender pallet
* More comments (I can work on this first if the code as it is it's too
hard to follow)
* Adding support for version negotiation. There is a basic concept of
versioning right now, but it can and should be expanded and improved.
* More unit and integration tests.

Probably more tickets will come out of this work, and will be tracked
separately in the same or in future milestones.

## How to test

A basic integration test of the two template runtimes is present in the
`dip-templates-xcm-tests` crate, inside the
`dip-template/runtimes/xcm-tests`. It can be run as usual with `cargo
test -p dip-templates-xcm-tests`.
ntn-x2 added a commit that referenced this pull request May 22, 2023
Fixes KILTprotocol/ticket#2557 and fixes
KILTprotocol/ticket#2556.

This PR builds on top of the shell PR, and adds support for Merkle proof
for DID documents.

## Merkle proof structure

A DID merkle proof is, at the core, an order set of (key, value) pairs,
on which proof-of-inclusion and proof-of-non-inclusion can be performed.
This PR generates and validates merkle proofs where leaves are of two
types:

- a DID key reference leave, whose key is the tuple (key ID, key
relationship) and the value is an empty tuple
- a DID key details leave, whose key is the key ID and the value is the
key details

For each key reference leaf with a given key ID, the proof also has to
contain a key details leaf whose key is the key ID. Multiple reference
leaves can reference the same key details leaf, optimising the storage
size.

## New runtime APIs

There is a new runtime API which the DIP sender would expose, and that
allows anyone to generate a merkle proof for a given DID identifier and
set of key IDs. The result contains the merkle root (which must match
what other chains have stored in their `pallet-dip-receiver` map), and a
merkle proof, which includes blinded values and a set of key reference
and key details leaves for the keys identified by the provided key IDs.

## How to test

The setup flow is similar to that of
#489.
Specifically:

- Set up the local Rococo network onboarding the sender and receiver
chains with para IDs 2_000 and 2_001 respectively
- Open an HRMP channel from sender 2_000 to receiver 2_001
- Create a DID on the sender chain, e.g., using the
[kilt-did-utilities](https://github.com/KILTprotocol/kilt-did-utilities)
tool
![Screenshot 2023-03-27 at 10 00
48](https://user-images.githubusercontent.com/6704504/227900994-41f0f355-84bd-4b8a-a2a8-3a9c74447e59.png)
- Push the identity of the DID to the receiver chain via the
`pallet-dip-sender` extrinsic
![Screenshot 2023-03-27 at 10 01
13](https://user-images.githubusercontent.com/6704504/227901150-7e8c9c9d-8aac-4739-8ad3-fad4ba6ff5f8.png)
- Call the runtime API to generate a proof for the created DID with some
keys revealed
![Screenshot 2023-03-27 at 10 01
40](https://user-images.githubusercontent.com/6704504/227901309-94b4dbc9-ca83-4541-820d-d1bec6adc6f0.png)
- Use the generated proof to dispatch an extrinsic on the receiving
chain

### How to use the runtime API with polkadot apps

There is currently no support for the new runtime API in the public
polkadot apps instance. To use the runtime APIs from UI, please use [our
fork from the aa/dip-sender-template
branch](https://github.com/KILTprotocol/polkadot-apps/tree/aa/dip-sender-template),
by running `yarn && yarn build && yarn start`, then connecting to the
sender node WS socket.
For runtime augmentation within a Node script, please use our [SDK repo
from the aa/dip-merkle-proof
branch](https://github.com/KILTprotocol/sdk-js/tree/aa/dip-merkle-proof).
ntn-x2 added a commit that referenced this pull request Dec 14, 2023
Feature branch for everything DIP. It will collect other PRs until we
are happy with the features, and will add the DIP to some of our
runtimes and merge this into `develop`.

## WIP Checklist for the open tasks for v1

- [x] Basic structure ->
#489
- [x] Merkleization of DID Documents ->
#492
- [x] `RuntimeCall` verification logic ->
#502
- [x] DID signature verification ->
#516
- [x] Add support for linked accounts and web3name ->
#525
- [x] Configurable origin for `commit_identity` ->
#526
- [x] Proper fee management ->
#528
- [x] Update to Polkadot 0.9.43 ->
c18a6ce
- [x] Replace XCM with state proofs ->
#543
- [x] Add support for relaychain consumer ->
#553 (part of
#543)
- [x] Proper error handling ->
#572
- [x] Add support for versioning ->
#573
- [x] Take deposits for identity commitments ->
#574
- [x] Expose common definitions usable by consumers ->
#577
- [x] Change ensure_signed! to configurable origin also for the
`dispatch_as` function ->
#577
- [x] Proper benchmarking and weights ->
#585
- [x] Comments and docs ->
#584
- [x] Revert Dockerfile changes in
#587
- [x] [OPTIONAL] Add support for Zombienet ->
#587
- [x] [OPTIONAL] Add chain spec loading from file for template runtimes
-> #587
- [x] Big, final review ->
#494 (review)
- [x] Improvements n.1 PR ->
#591
- [x] Improvements n.2 PR ->
#592
- [x] Add to Peregrine runtime ->
#594
- [ ] Deploy on Peregrine
- [ ] Unit tests
- [ ] Add to Spiritnet runtime
- [ ] Deploy on Spiritnet
- [ ] [OPTIONAL] Move DIP-related stuff into its own repo

---------

Co-authored-by: Adel Golghalyani <[email protected]>
Co-authored-by: Chris Chinchilla <[email protected]>
Co-authored-by: Albrecht <[email protected]>
webguru9178 pushed a commit to webguru9178/kilt-node that referenced this pull request Jan 8, 2024
Feature branch for everything DIP. It will collect other PRs until we
are happy with the features, and will add the DIP to some of our
runtimes and merge this into `develop`.

## WIP Checklist for the open tasks for v1

- [x] Basic structure ->
KILTprotocol/kilt-node#489
- [x] Merkleization of DID Documents ->
KILTprotocol/kilt-node#492
- [x] `RuntimeCall` verification logic ->
KILTprotocol/kilt-node#502
- [x] DID signature verification ->
KILTprotocol/kilt-node#516
- [x] Add support for linked accounts and web3name ->
KILTprotocol/kilt-node#525
- [x] Configurable origin for `commit_identity` ->
KILTprotocol/kilt-node#526
- [x] Proper fee management ->
KILTprotocol/kilt-node#528
- [x] Update to Polkadot 0.9.43 ->
KILTprotocol/kilt-node@c18a6ce
- [x] Replace XCM with state proofs ->
KILTprotocol/kilt-node#543
- [x] Add support for relaychain consumer ->
KILTprotocol/kilt-node#553 (part of
KILTprotocol/kilt-node#543)
- [x] Proper error handling ->
KILTprotocol/kilt-node#572
- [x] Add support for versioning ->
KILTprotocol/kilt-node#573
- [x] Take deposits for identity commitments ->
KILTprotocol/kilt-node#574
- [x] Expose common definitions usable by consumers ->
KILTprotocol/kilt-node#577
- [x] Change ensure_signed! to configurable origin also for the
`dispatch_as` function ->
KILTprotocol/kilt-node#577
- [x] Proper benchmarking and weights ->
KILTprotocol/kilt-node#585
- [x] Comments and docs ->
KILTprotocol/kilt-node#584
- [x] Revert Dockerfile changes in
KILTprotocol/kilt-node#587
- [x] [OPTIONAL] Add support for Zombienet ->
KILTprotocol/kilt-node#587
- [x] [OPTIONAL] Add chain spec loading from file for template runtimes
-> KILTprotocol/kilt-node#587
- [x] Big, final review ->
KILTprotocol/kilt-node#494 (review)
- [x] Improvements n.1 PR ->
KILTprotocol/kilt-node#591
- [x] Improvements n.2 PR ->
KILTprotocol/kilt-node#592
- [x] Add to Peregrine runtime ->
KILTprotocol/kilt-node#594
- [ ] Deploy on Peregrine
- [ ] Unit tests
- [ ] Add to Spiritnet runtime
- [ ] Deploy on Spiritnet
- [ ] [OPTIONAL] Move DIP-related stuff into its own repo

---------

Co-authored-by: Adel Golghalyani <[email protected]>
Co-authored-by: Chris Chinchilla <[email protected]>
Co-authored-by: Albrecht <[email protected]>
Ad96el added a commit that referenced this pull request Feb 7, 2024
Feature branch for everything DIP. It will collect other PRs until we
are happy with the features, and will add the DIP to some of our
runtimes and merge this into `develop`.

## WIP Checklist for the open tasks for v1

- [x] Basic structure ->
#489
- [x] Merkleization of DID Documents ->
#492
- [x] `RuntimeCall` verification logic ->
#502
- [x] DID signature verification ->
#516
- [x] Add support for linked accounts and web3name ->
#525
- [x] Configurable origin for `commit_identity` ->
#526
- [x] Proper fee management ->
#528
- [x] Update to Polkadot 0.9.43 ->
c18a6ce
- [x] Replace XCM with state proofs ->
#543
- [x] Add support for relaychain consumer ->
#553 (part of
#543)
- [x] Proper error handling ->
#572
- [x] Add support for versioning ->
#573
- [x] Take deposits for identity commitments ->
#574
- [x] Expose common definitions usable by consumers ->
#577
- [x] Change ensure_signed! to configurable origin also for the
`dispatch_as` function ->
#577
- [x] Proper benchmarking and weights ->
#585
- [x] Comments and docs ->
#584
- [x] Revert Dockerfile changes in
#587
- [x] [OPTIONAL] Add support for Zombienet ->
#587
- [x] [OPTIONAL] Add chain spec loading from file for template runtimes
-> #587
- [x] Big, final review ->
#494 (review)
- [x] Improvements n.1 PR ->
#591
- [x] Improvements n.2 PR ->
#592
- [x] Add to Peregrine runtime ->
#594
- [ ] Deploy on Peregrine
- [ ] Unit tests
- [ ] Add to Spiritnet runtime
- [ ] Deploy on Spiritnet
- [ ] [OPTIONAL] Move DIP-related stuff into its own repo

---------

Co-authored-by: Adel Golghalyani <[email protected]>
Co-authored-by: Chris Chinchilla <[email protected]>
Co-authored-by: Albrecht <[email protected]>
Ad96el added a commit that referenced this pull request Apr 2, 2024
Feature branch for everything DIP. It will collect other PRs until we
are happy with the features, and will add the DIP to some of our
runtimes and merge this into `develop`.

## WIP Checklist for the open tasks for v1

- [x] Basic structure ->
#489
- [x] Merkleization of DID Documents ->
#492
- [x] `RuntimeCall` verification logic ->
#502
- [x] DID signature verification ->
#516
- [x] Add support for linked accounts and web3name ->
#525
- [x] Configurable origin for `commit_identity` ->
#526
- [x] Proper fee management ->
#528
- [x] Update to Polkadot 0.9.43 ->
c18a6ce
- [x] Replace XCM with state proofs ->
#543
- [x] Add support for relaychain consumer ->
#553 (part of
#543)
- [x] Proper error handling ->
#572
- [x] Add support for versioning ->
#573
- [x] Take deposits for identity commitments ->
#574
- [x] Expose common definitions usable by consumers ->
#577
- [x] Change ensure_signed! to configurable origin also for the
`dispatch_as` function ->
#577
- [x] Proper benchmarking and weights ->
#585
- [x] Comments and docs ->
#584
- [x] Revert Dockerfile changes in
#587
- [x] [OPTIONAL] Add support for Zombienet ->
#587
- [x] [OPTIONAL] Add chain spec loading from file for template runtimes
-> #587
- [x] Big, final review ->
#494 (review)
- [x] Improvements n.1 PR ->
#591
- [x] Improvements n.2 PR ->
#592
- [x] Add to Peregrine runtime ->
#594
- [ ] Deploy on Peregrine
- [ ] Unit tests
- [ ] Add to Spiritnet runtime
- [ ] Deploy on Spiritnet
- [ ] [OPTIONAL] Move DIP-related stuff into its own repo

---------

Co-authored-by: Adel Golghalyani <[email protected]>
Co-authored-by: Chris Chinchilla <[email protected]>
Co-authored-by: Albrecht <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants