Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • nodes/rust/duniter-v2s
  • llaq/lc-core-substrate
  • pini-gh/duniter-v2s
  • vincentux/duniter-v2s
  • mildred/duniter-v2s
  • d0p1/duniter-v2s
  • bgallois/duniter-v2s
  • Nicolas80/duniter-v2s
8 results
Show changes
Commits on Source (8)
Showing
with 360 additions and 322 deletions
......@@ -5,6 +5,7 @@ stages:
- build
- tests
- deploy
- deploy_readme
workflow:
rules:
......@@ -272,3 +273,21 @@ deploy_docker_release_tag:
- docker push "duniter/duniter-v2s:latest"
dependencies:
- build_release
readme_docker_release_tag:
stage: deploy_readme
rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never
image:
name: chko/docker-pushrm
entrypoint: ["/bin/sh", "-c", "/docker-pushrm"]
variables:
DOCKER_USER: "duniterteam"
DOCKER_PASS: "$DUNITERTEAM_PASSWD"
PUSHRM_SHORT: "Duniter v2 based on Substrate framework"
PUSHRM_TARGET: "docker.io/duniter/duniter-v2s"
PUSHRM_DEBUG: 1
PUSHRM_FILE: "$CI_PROJECT_DIR/docker/README.md"
script: "/bin/true"
......@@ -17,6 +17,7 @@
- [Test](#test)
- [Contribute](#contribute)
- [Structure](#project-structure)
- [docker](./docker/) docker-related documentation
- [docs](./docs/)
- [api](./docs/api/)
- [manual](./docs/api/manual.md)
......@@ -34,7 +35,7 @@
- [user](./docs/user/)
- [autocompletion](./docs/user/autocompletion.md)
- [build-for-arm](./docs/user/build-for-arm.md)
- [rpc](./docs/user/rpc.md) deploy a permanent ǦDev mirror node
- [mirror](./docs/user/mirror.md) deploy a permanent ǦDev mirror node
- [smith](./docs/user/smith.md) deploy a permanent ǦDev validator node
- [end2end-tests](./end2end-tests/) automated end to end tests written with cucumber
- [live-tests](./live-tests/) sanity checks to test the storage of a live chain
......
......@@ -4,13 +4,13 @@ Duniter is the software that supports the [Ğ1 libre-currency blockchain](https:
[Duniter v2s](https://git.duniter.org/nodes/rust/duniter-v2s) is a complete rewrite of Duniter based on the Substrate / Polkadot framework. **This is alpha state work in progress.**
# Minimal docker-compose file for an RPC (non validator) node
## Minimal docker-compose file for an mirror node
```
version: "3.5"
services:
duniter-rpc:
duniter-mirror:
image: duniter/duniter-v2s:latest
restart: unless-stopped
ports:
......@@ -23,16 +23,16 @@ services:
# p2p
- 30333:30333
volumes:
- data-rpc:/var/lib/duniter/
- data-mirror:/var/lib/duniter/
environment:
- DUNITER_CHAIN_NAME=gdev
- DUNITER_NODE_NAME=<my-node-name>
volumes:
data-rpc:
data-mirror:
```
# Minimal docker-compose file for a validator node
## Minimal docker-compose file for a validator node
```
version: "3.5"
......@@ -57,25 +57,42 @@ volumes:
data-validator:
```
# Environment variables
## Environment variables
| Name | Description | Default |
| ---- | ----------- | ------- |
| `DUNITER_NODE_NAME` | The node name. This name will appear on the Substrate telemetry server when telemetry is enabled. | Random name |
| `DUNITER_CHAIN_NAME` | The currency to process. "gdev" uses the embeded chainspec. A path allows to use a local json raw chainspec. | `dev` (development mode) |
| `DUNITER_PUBLIC_ADDR` | The libp2p public address base. See [libp2p documentation](https://docs.libp2p.io/concepts/fundamentals/addressing/). This variable is useful when the node is behind a reverse-proxy with its ports not directly exposed.<br>Note: the `p2p/<peer_id>` part of the address shouldn't be set in this variable. It is automatically added by Duniter. | duniter-v2s guesses one from the node's IPv4 address. |
| `DUNITER_PUBLIC_ADDR` | The libp2p public address base. See [libp2p documentation](https://docs.libp2p.io/concepts/fundamentals/addressing/). This variable is useful when the node is behind a reverse proxy with its ports not directly exposed.<br>Note: the `p2p/<peer_id>` part of the address shouldn't be set in this variable. It is automatically added by Duniter. | duniter-v2s guesses one from the node's IPv4 address. |
| `DUNITER_LISTEN_ADDR` | The libp2p listen address. See [libp2p documentation](https://docs.libp2p.io/concepts/fundamentals/addressing/). This variable is useful when running a validator node behind a reverse proxy, to force the P2P end point in websocket mode with:<br> `DUNITER_LISTEN_ADDR=/ip4/0.0.0.0/tcp/30333/ws` | Non validator node: `/ip4/0.0.0.0/tcp/30333/ws`<br>Validator node: `/ip4/0.0.0.0/tcp/30333` |
| `DUNITER_RPC_CORS` | Value of the polkadot `--rpc-cors` option. | `all` |
| `DUNITER_VALIDATOR` | Boolean (`true` / `false`) to run the node in validator mode. Configure the polkadot options `--validator --rpc-methods Unsafe`. | `false` |
| `DUNITER_DISABLE_PROMETHEUS` | Boolean to disable the Prometheus endpoint on port 9615. | `false` |
| `DUNITER_DISABLE_TELEMETRY` | Boolean to disable connecting to the Substrate tememetry server. | `false` |
| `DUNITER_DISABLE_TELEMETRY` | Boolean to disable connecting to the Substrate telemetry server. | `false` |
| `DUNITER_PRUNING_PROFILE` | * `default`<br> * `archive`: keep all blocks and state blocks<br> * `light`: keep only last 256 state blocks and last 14400 blocks (one day duration) | `default` |
# Other duniter options
## Other Duniter options
You can pass any other option to duniter using the `command` docker-compose element:
You can pass any other option to Duniter using the `command` docker-compose element:
```
command:
# workaround for substrate issue #12073
# https://github.com/paritytech/substrate/issues/12073
- "--wasm-execution=interpreted-i-know-what-i-do"
```
## Start Duniter
Once you are happy with your `docker-compose.yml` file, run in the same folder:
```bash
docker compose up -d
```
## Running duniter subcommands or custom set of options
To run duniter from the command line without the default configuration detailed in the "Environment variables" section use `--` as the first argument. For example:
```
$ docker run --rm duniter/duniter-v2s:latest -- key generate
$ docker run --rm duniter/duniter-v2s:latest -- --chain gdev ...
```
# This is a docker template for running a gdev mirror
version: "3.5"
services:
duniter-rpc:
image: duniter/duniter-v2s:latest
restart: unless-stopped
ports:
# telemetry
- 127.0.0.1:9615:9615
# rpc
- 127.0.0.1:9933:9933
# rpc-ws
- 127.0.0.1:9944:9944
# p2p
- 30333:30333
volumes:
- ./node.key:/etc/duniter/node.key
- duniter-rpc-data:/var/lib/duniter/
environment:
- DUNITER_CHAIN_NAME=gdev
# SERVER_DOMAIN should be replaced by a domain name that point on your server
- DUNITER_PUBLIC_ADDR=/dns/${SERVER_DOMAIN?SERVER_DOMAIN should be set}/tcp/30333/ws
volumes:
duniter-rpc-data:
version: "3.5"
services:
duniter-rpc:
image: duniter/duniter-v2s:latest
restart: unless-stopped
ports:
# telemetry
- 127.0.0.1:9615:9615
# rpc
- 127.0.0.1:9933:9933
# rpc-ws
- 127.0.0.1:9944:9944
# p2p
- 30333:30333
volumes:
- ./node.key:/etc/duniter/validator-node.key
- duniter-rpc-data:/var/lib/duniter/
environment:
- DUNITER_CHAIN_NAME=gdev
# RPC_SERVER_DOMAIN should be replaced by a domain name that point on your server
- DUNITER_PUBLIC_ADDR=/dns/${RPC_SERVER_DOMAIN?RPC_SERVER_DOMAIN should be set}/tcp/30333/ws
duniter-validator:
image: duniter/duniter-v2s:latest
restart: unless-stopped
ports:
# telemetry
- 127.0.0.1:9616:9615
# rpc
- 127.0.0.1:9934:9933
# rpc-ws
- 127.0.0.1:9945:9944
# p2p
- 30334:30333
volumes:
- ./node.key:/etc/duniter/validator-node.key
- duniter-validator-data:/var/lib/duniter/
environment:
- DUNITER_CHAIN_NAME=gdev
# VALIDATOR_SERVER_DOMAIN should be replaced by a domain name that point on your server
- DUNITER_PUBLIC_ADDR=/dns/${VALIDATOR_SERVER_DOMAIN?VALIDATOR_SERVER_DOMAIN should be set}/tcp/30333
- DUNITER_VALIDATOR=true
command:
- "--pruning=14400"
# this template is used in /scripts/create-live-network.sh script
version: "3.5"
services:
......
#!/bin/bash
# Custom startup if a first argument is present and is equal to '--'
# then we just run duniter with the provided arguments (but the '--')
# without applying all the automated configuration below
if [ "$1" = -- ]; then
shift
exec duniter "$@"
fi
# Normal startup
function boolean () {
echo "$1" | sed -E 's/^(true|yes|1)$/true/i'
}
......@@ -55,6 +64,21 @@ if [ "$DUNITER_DISABLE_TELEMETRY" = true ]; then
set -- "$@" --no-telemetry
fi
DUNITER_PRUNING_PROFILE="${DUNITER_PRUNING_PROFILE:-default}"
case "$DUNITER_PRUNING_PROFILE" in
default)
;;
archive)
set -- "$@" --state-pruning archive --blocks-pruning archive
;;
light)
set -- "$@" --blocks-pruning 14400
;;
*)
echo "ERROR: ignoring unknown DUNITER_PRUNING_PROFILE value '$DUNITER_PRUNING_PROFILE'" >&2
;;
esac
DUNITER_CHAIN_NAME="${DUNITER_CHAIN_NAME:-dev}"
case "$DUNITER_CHAIN_NAME" in
dev)
......
......@@ -21,6 +21,16 @@ Only use `identity` pallet. The `membership` calls are disabled.
1. Any account that already has membership and respects the identity creation period can create an identity for another account, using `identity.createIdentity`.
1. The account has to confirm its identity with a name, using `identity.confirmIdentity`. The name must be ASCII alphanumeric, punctuation or space characters: ``/^[-!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~a-zA-Z0-9 ]{3,64}$/`` (additionally, trailing spaces and double spaces are forbidden, as a phishing countermeasure). If the name is already used, the call will fail.
## Change key
A member can request a key change via the `identity.change_onwner_key` call. It needs the following SCALE encoded (see SCALE encoding section below) payload:
* The new owner key payload prefix (rust definition: `b"icok"`)
* the genesis block hash. (rust type `[u8; 32]` (`H256`))
* The identity index (rust type `u64`)
* The old key (rust type `u64`)
This payload must be signed with the new key.
## Revoke an identity
Revoking an identity makes it lose its membership, hence UD creation and governance rights. Other data such as balance will remain.
......@@ -29,9 +39,19 @@ This feature is useful in case the user has lost their private key since the rev
### Generate the revocation payload
1. Scale-encode the revocation payload, that is the concatenation of the 32-bits public key and the genesis block hash.
2. Store this payload and its signature.
The revocation needs this SCALE encoded (see SCALE encoding section below) payload:
* The revocation payload prefix (rust definition: `b"revo"`)
* The identity index (rust type `u64`)
* the genesis block hash. (rust type `[u8; 32]` (`H256`))
This payload must be signed with the corresponding revocation key.
### Effectively revoke the identity
1. From any origin that can pay the fee, use `identity.revokeIdentity` with the revocation payload.
## SCALE encoding
SCALE codec documentation: https://docs.substrate.io/reference/scale-codec/.
At the end of this documentation you'll find links to SCALE codec implementation for other languages.
......@@ -25,7 +25,7 @@ There are **68** user calls from **21** pallets.
when: T::BlockNumber
maybe_periodic: Option<schedule::Period<T::BlockNumber>>
priority: schedule::Priority
call: Box<CallOrHashOf<T>>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -50,11 +50,11 @@ Cancel an anonymously scheduled task.
<details><summary><code>schedule_named(id, when, maybe_periodic, priority, call)</code></summary>
```rust
id: Vec<u8>
id: TaskName
when: T::BlockNumber
maybe_periodic: Option<schedule::Period<T::BlockNumber>>
priority: schedule::Priority
call: Box<CallOrHashOf<T>>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -66,7 +66,7 @@ Schedule a named task.
<details><summary><code>cancel_named(id)</code></summary>
```rust
id: Vec<u8>
id: TaskName
```
</details>
......@@ -81,7 +81,7 @@ Cancel a named scheduled task.
after: T::BlockNumber
maybe_periodic: Option<schedule::Period<T::BlockNumber>>
priority: schedule::Priority
call: Box<CallOrHashOf<T>>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -94,11 +94,11 @@ Anonymously schedule a task after a delay.
<details><summary><code>schedule_named_after(id, after, maybe_periodic, priority, call)</code></summary>
```rust
id: Vec<u8>
id: TaskName
after: T::BlockNumber
maybe_periodic: Option<schedule::Period<T::BlockNumber>>
priority: schedule::Priority
call: Box<CallOrHashOf<T>>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -131,7 +131,7 @@ be reported.
<details><summary><code>transfer(dest, value)</code></summary>
```rust
dest: <T::Lookup as StaticLookup>::Source
dest: AccountIdLookupOf<T>
value: T::Balance
```
</details>
......@@ -151,7 +151,7 @@ The dispatch origin for this call must be `Signed` by the transactor.
<details><summary><code>transfer_keep_alive(dest, value)</code></summary>
```rust
dest: <T::Lookup as StaticLookup>::Source
dest: AccountIdLookupOf<T>
value: T::Balance
```
</details>
......@@ -169,7 +169,7 @@ origin account.
<details><summary><code>transfer_all(dest, keep_alive)</code></summary>
```rust
dest: <T::Lookup as StaticLookup>::Source
dest: AccountIdLookupOf<T>
keep_alive: bool
```
</details>
......@@ -265,7 +265,7 @@ and the remaining amount to another account.
</details>
ask to leave the set of validators two sessions after
#### go_online - 1
......@@ -276,7 +276,7 @@ and the remaining amount to another account.
</details>
ask to join the set of validators two sessions after
#### set_session_keys - 2
......@@ -288,7 +288,7 @@ keys: T::KeysWrapper
</details>
declare new session keys to replace current ones
### Grandpa - 15
......@@ -356,6 +356,11 @@ hash: T::Hash
Clear an unrequested preimage from the runtime storage.
If `len` is provided, then it will be a much cheaper operation.
- `hash`: The hash of the preimage to be removed from the store.
- `len`: The length of the preimage of `hash`.
#### request_preimage - 2
<details><summary><code>request_preimage(hash)</code></summary>
......@@ -443,7 +448,39 @@ Transaction fees will be waived if the member is voting on any particular propos
for the first time and the call is successful. Subsequent vote changes will charge a
fee.
#### close - 4
#### close_old_weight - 4
<details><summary><code>close_old_weight(proposal_hash, index, proposal_weight_bound, length_bound)</code></summary>
```rust
proposal_hash: T::Hash
index: ProposalIndex
proposal_weight_bound: OldWeight
length_bound: u32
```
</details>
Close a vote that is either approved, disapproved or whose voting period has ended.
May be called by any signed account in order to finish voting and close the proposal.
If called before the end of the voting period it will only close the vote if it is
has enough votes to be approved or disapproved.
If called after the end of the voting period abstentions are counted as rejections
unless there is a prime member set and the prime member cast an approval.
If the close operation completes successfully with disapproval, the transaction fee will
be waived. Otherwise execution of the approved operation will be charged to the caller.
+ `proposal_weight_bound`: The maximum amount of weight consumed by executing the closed
proposal.
+ `length_bound`: The upper bound for the length of the proposal in storage. Checked via
`storage::read` so it is `size_of::<u32>() == 4` larger than the pure length.
#### close - 6
<details><summary><code>close(proposal_hash, index, proposal_weight_bound, length_bound)</code></summary>
......@@ -514,19 +551,6 @@ value: BalanceOf<T>
Transfer some liquid free balance to another account, in milliUD.
#### force_set_first_eligible_ud - 3
<details><summary><code>force_set_first_eligible_ud(who, first_eligible_ud)</code></summary>
```rust
who: T::AccountId
first_eligible_ud: FirstEligibleUd
```
</details>
### Identity - 41
#### create_identity - 0
......@@ -571,7 +595,7 @@ idty_index: T::IdtyIndex
</details>
validate the owned identity (must meet the main wot requirements)
#### change_owner_key - 3
......@@ -624,22 +648,10 @@ inc: bool
</details>
change sufficient ref count for given key
### Membership - 42
#### request_membership - 1
<details><summary><code>request_membership(metadata)</code></summary>
```rust
metadata: T::MetaData
```
</details>
#### renew_membership - 3
<details><summary><code>renew_membership(maybe_idty_id)</code></summary>
......@@ -650,7 +662,7 @@ maybe_idty_id: Option<T::IdtyId>
</details>
extend the validity period of an active membership
### Cert - 43
......@@ -683,7 +695,21 @@ metadata: T::MetaData
</details>
submit a membership request (must have a declared identity)
(only available for sub wot, automatic for main wot)
#### claim_membership - 2
<details><summary><code>claim_membership(maybe_idty_id)</code></summary>
```rust
maybe_idty_id: Option<T::IdtyId>
```
</details>
claim that the previously requested membership fullfills the requirements
(only available for sub wot, automatic for main wot)
#### renew_membership - 3
......@@ -695,7 +721,7 @@ maybe_idty_id: Option<T::IdtyId>
</details>
extend the validity period of an active membership
#### revoke_membership - 4
......@@ -707,7 +733,8 @@ maybe_idty_id: Option<T::IdtyId>
</details>
revoke an active membership
(only available for sub wot, automatic for main wot)
### SmithsCert - 53
......@@ -801,7 +828,7 @@ The dispatch origin for this call must be _Signed_.
```rust
other_signatories: Vec<T::AccountId>
call: Box<<T as Config>::Call>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -819,14 +846,13 @@ Result is equivalent to the dispatched result.
#### as_multi - 1
<details><summary><code>as_multi(threshold, other_signatories, maybe_timepoint, call, store_call, max_weight)</code></summary>
<details><summary><code>as_multi(threshold, other_signatories, maybe_timepoint, call, max_weight)</code></summary>
```rust
threshold: u16
other_signatories: Vec<T::AccountId>
maybe_timepoint: Option<Timepoint<T::BlockNumber>>
call: OpaqueCall<T>
store_call: bool
call: Box<<T as Config>::RuntimeCall>
max_weight: Weight
```
</details>
......@@ -941,9 +967,9 @@ Request a randomness
<details><summary><code>proxy(real, force_proxy_type, call)</code></summary>
```rust
real: T::AccountId
real: AccountIdLookupOf<T>
force_proxy_type: Option<T::ProxyType>
call: Box<<T as Config>::Call>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -960,13 +986,12 @@ Parameters:
- `force_proxy_type`: Specify the exact proxy type to be used and checked for this call.
- `call`: The call to be made by the `real` account.
#### add_proxy - 1
<details><summary><code>add_proxy(delegate, proxy_type, delay)</code></summary>
```rust
delegate: T::AccountId
delegate: AccountIdLookupOf<T>
proxy_type: T::ProxyType
delay: T::BlockNumber
```
......@@ -983,13 +1008,12 @@ Parameters:
- `delay`: The announcement period required of the initial proxy. Will generally be
zero.
#### remove_proxy - 2
<details><summary><code>remove_proxy(delegate, proxy_type, delay)</code></summary>
```rust
delegate: T::AccountId
delegate: AccountIdLookupOf<T>
proxy_type: T::ProxyType
delay: T::BlockNumber
```
......@@ -1004,7 +1028,6 @@ Parameters:
- `proxy`: The account that the `caller` would like to remove as a proxy.
- `proxy_type`: The permissions currently enabled for the removed proxy account.
#### remove_proxies - 3
<details><summary><code>remove_proxies()</code></summary>
......@@ -1018,13 +1041,12 @@ Unregister all proxy accounts for the sender.
The dispatch origin for this call must be _Signed_.
WARNING: This may be called on accounts created by `anonymous`, however if done, then
WARNING: This may be called on accounts created by `pure`, however if done, then
the unreserved fees will be inaccessible. **All access to this account will be lost.**
#### create_pure - 4
#### anonymous - 4
<details><summary><code>anonymous(proxy_type, delay, index)</code></summary>
<details><summary><code>create_pure(proxy_type, delay, index)</code></summary>
```rust
proxy_type: T::ProxyType
......@@ -1053,13 +1075,12 @@ same sender, with the same parameters.
Fails if there are insufficient funds to pay for deposit.
#### kill_pure - 5
#### kill_anonymous - 5
<details><summary><code>kill_anonymous(spawner, proxy_type, index, height, ext_index)</code></summary>
<details><summary><code>kill_pure(spawner, proxy_type, index, height, ext_index)</code></summary>
```rust
spawner: T::AccountId
spawner: AccountIdLookupOf<T>
proxy_type: T::ProxyType
index: u16
height: T::BlockNumber
......@@ -1068,30 +1089,29 @@ ext_index: u32
</details>
Removes a previously spawned anonymous proxy.
Removes a previously spawned pure proxy.
WARNING: **All access to this account will be lost.** Any funds held in it will be
inaccessible.
Requires a `Signed` origin, and the sender account must have been created by a call to
`anonymous` with corresponding parameters.
- `spawner`: The account that originally called `anonymous` to create this account.
- `index`: The disambiguation index originally passed to `anonymous`. Probably `0`.
- `proxy_type`: The proxy type originally passed to `anonymous`.
- `height`: The height of the chain when the call to `anonymous` was processed.
- `ext_index`: The extrinsic index in which the call to `anonymous` was processed.
`pure` with corresponding parameters.
Fails with `NoPermission` in case the caller is not a previously created anonymous
account whose `anonymous` call has corresponding parameters.
- `spawner`: The account that originally called `pure` to create this account.
- `index`: The disambiguation index originally passed to `pure`. Probably `0`.
- `proxy_type`: The proxy type originally passed to `pure`.
- `height`: The height of the chain when the call to `pure` was processed.
- `ext_index`: The extrinsic index in which the call to `pure` was processed.
Fails with `NoPermission` in case the caller is not a previously created pure
account whose `pure` call has corresponding parameters.
#### announce - 6
<details><summary><code>announce(real, call_hash)</code></summary>
```rust
real: T::AccountId
real: AccountIdLookupOf<T>
call_hash: CallHashOf<T>
```
</details>
......@@ -1113,13 +1133,12 @@ Parameters:
- `real`: The account that the proxy will make a call on behalf of.
- `call_hash`: The hash of the call to be made by the `real` account.
#### remove_announcement - 7
<details><summary><code>remove_announcement(real, call_hash)</code></summary>
```rust
real: T::AccountId
real: AccountIdLookupOf<T>
call_hash: CallHashOf<T>
```
</details>
......@@ -1136,13 +1155,12 @@ Parameters:
- `real`: The account that the proxy will make a call on behalf of.
- `call_hash`: The hash of the call to be made by the `real` account.
#### reject_announcement - 8
<details><summary><code>reject_announcement(delegate, call_hash)</code></summary>
```rust
delegate: T::AccountId
delegate: AccountIdLookupOf<T>
call_hash: CallHashOf<T>
```
</details>
......@@ -1159,16 +1177,15 @@ Parameters:
- `delegate`: The account that previously announced the call.
- `call_hash`: The hash of the call to be made.
#### proxy_announced - 9
<details><summary><code>proxy_announced(delegate, real, force_proxy_type, call)</code></summary>
```rust
delegate: T::AccountId
real: T::AccountId
delegate: AccountIdLookupOf<T>
real: AccountIdLookupOf<T>
force_proxy_type: Option<T::ProxyType>
call: Box<<T as Config>::Call>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -1185,7 +1202,6 @@ Parameters:
- `force_proxy_type`: Specify the exact proxy type to be used and checked for this call.
- `call`: The call to be made by the `real` account.
### Utility - 64
#### batch - 0
......@@ -1193,7 +1209,7 @@ Parameters:
<details><summary><code>batch(calls)</code></summary>
```rust
calls: Vec<<T as Config>::Call>
calls: Vec<<T as Config>::RuntimeCall>
```
</details>
......@@ -1215,7 +1231,7 @@ bypassing `frame_system::Config::BaseCallFilter`).
```rust
index: u16
call: Box<<T as Config>::Call>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -1239,7 +1255,7 @@ The dispatch origin for this call must be _Signed_.
<details><summary><code>batch_all(calls)</code></summary>
```rust
calls: Vec<<T as Config>::Call>
calls: Vec<<T as Config>::RuntimeCall>
```
</details>
......@@ -1261,7 +1277,7 @@ bypassing `frame_system::Config::BaseCallFilter`).
<details><summary><code>force_batch(calls)</code></summary>
```rust
calls: Vec<<T as Config>::Call>
calls: Vec<<T as Config>::RuntimeCall>
```
</details>
......@@ -1286,7 +1302,7 @@ bypassing `frame_system::Config::BaseCallFilter`).
```rust
value: BalanceOf<T, I>
beneficiary: <T::Lookup as StaticLookup>::Source
beneficiary: AccountIdLookupOf<T>
```
</details>
......@@ -1302,7 +1318,7 @@ proposal is awarded.
```rust
amount: BalanceOf<T, I>
beneficiary: <T::Lookup as StaticLookup>::Source
beneficiary: AccountIdLookupOf<T>
```
</details>
......@@ -1455,7 +1471,7 @@ not been enacted yet.
<details><summary><code>set_balance(who, new_free, new_reserved)</code></summary>
```rust
who: <T::Lookup as StaticLookup>::Source
who: AccountIdLookupOf<T>
new_free: T::Balance
new_reserved: T::Balance
```
......@@ -1476,8 +1492,8 @@ The dispatch origin for this call is `root`.
<details><summary><code>force_transfer(source, dest, value)</code></summary>
```rust
source: <T::Lookup as StaticLookup>::Source
dest: <T::Lookup as StaticLookup>::Source
source: AccountIdLookupOf<T>
dest: AccountIdLookupOf<T>
value: T::Balance
```
</details>
......@@ -1491,7 +1507,7 @@ specified.
<details><summary><code>force_unreserve(who, amount)</code></summary>
```rust
who: <T::Lookup as StaticLookup>::Source
who: AccountIdLookupOf<T>
amount: T::Balance
```
</details>
......@@ -1513,7 +1529,7 @@ member_id: T::MemberId
</details>
remove an identity from the set of authorities
### Grandpa - 15
......@@ -1607,7 +1623,7 @@ idty_name: Option<IdtyName>
</details>
remove an identity from storage
#### prune_item_identities_names - 6
......@@ -1619,7 +1635,7 @@ names: Vec<IdtyName>
</details>
remove identity names from storage
### Membership - 42
......@@ -1634,7 +1650,7 @@ metadata: T::MetaData
</details>
request membership without checks
### Cert - 43
......@@ -1650,7 +1666,7 @@ verify_rules: bool
</details>
add a certification without checks (only root)
#### del_cert - 2
......@@ -1663,7 +1679,7 @@ receiver: T::IdtyIndex
</details>
remove a certification (only root)
#### remove_all_certs_received_by - 3
......@@ -1675,7 +1691,7 @@ idty_index: T::IdtyIndex
</details>
remove all certifications received by an identity (only root)
### SmithsMembership - 52
......@@ -1690,7 +1706,7 @@ metadata: T::MetaData
</details>
request membership without checks
### SmithsCert - 53
......@@ -1706,7 +1722,7 @@ verify_rules: bool
</details>
add a certification without checks (only root)
#### del_cert - 2
......@@ -1719,7 +1735,7 @@ receiver: T::IdtyIndex
</details>
remove a certification (only root)
#### remove_all_certs_received_by - 3
......@@ -1731,7 +1747,7 @@ idty_index: T::IdtyIndex
</details>
remove all certifications received by an identity (only root)
### Utility - 64
......@@ -1741,7 +1757,7 @@ idty_index: T::IdtyIndex
```rust
as_origin: Box<T::PalletsOrigin>
call: Box<<T as Config>::Call>
call: Box<<T as Config>::RuntimeCall>
```
</details>
......@@ -1758,7 +1774,7 @@ The dispatch origin for this call must be _Root_.
## Disabled calls
There are **7** disabled calls from **4** pallets.
There are **7** disabled calls from **3** pallets.
### System - 0
......@@ -1828,21 +1844,22 @@ usually means being a stash account).
### Membership - 42
#### claim_membership - 2
#### request_membership - 1
<details><summary><code>claim_membership(maybe_idty_id)</code></summary>
<details><summary><code>request_membership(metadata)</code></summary>
```rust
maybe_idty_id: Option<T::IdtyId>
metadata: T::MetaData
```
</details>
submit a membership request (must have a declared identity)
(only available for sub wot, automatic for main wot)
#### claim_membership - 2
#### revoke_membership - 4
<details><summary><code>revoke_membership(maybe_idty_id)</code></summary>
<details><summary><code>claim_membership(maybe_idty_id)</code></summary>
```rust
maybe_idty_id: Option<T::IdtyId>
......@@ -1850,13 +1867,12 @@ maybe_idty_id: Option<T::IdtyId>
</details>
claim that the previously requested membership fullfills the requirements
(only available for sub wot, automatic for main wot)
#### revoke_membership - 4
### SmithsMembership - 52
#### claim_membership - 2
<details><summary><code>claim_membership(maybe_idty_id)</code></summary>
<details><summary><code>revoke_membership(maybe_idty_id)</code></summary>
```rust
maybe_idty_id: Option<T::IdtyId>
......@@ -1864,5 +1880,6 @@ maybe_idty_id: Option<T::IdtyId>
</details>
revoke an active membership
(only available for sub wot, automatic for main wot)
......@@ -21,7 +21,7 @@ docker image that you have chosen.
Generate a random secret phrase:
```bash
$ docker run --rm -it --entrypoint duniter duniter/duniter-v2s:TAG key generate
$ docker run --rm duniter/duniter-v2s:TAG -- key generate
Secret phrase: noble stay fury mean poverty delay stadium organ evil east vague can
Secret seed: 0xb39c31fb10c5080721738880c2ea45412cb3df33df022bf8d9a51483b3a9b7a6
Public key (hex): 0x90a0c2866034db9d05f8193a95fe5af8d5e12ab295a501c17c95cdbeaf226d62
......@@ -35,7 +35,7 @@ Keep this secret phrase **carefully**, it will be used **several** times later.
Then, generate the session keys:
```bash
$ docker run --rm -it --entrypoint duniter duniter/duniter-v2s:TAG key generate-session-keys --chain CURRENCY_local --suri "<your secret phrase>"
$ docker run --rm duniter/duniter-v2s:TAG -- key generate-session-keys --chain CURRENCY_local --suri "<your secret phrase>"
Session Keys: 0x87189d723e1b2826c243bc433c718ac26ba60526932216a09102a254d54462b890a0c2866034db9d05f8193a95fe5af8d5e12ab295a501c17c95cdbeaf226d6290a0c2866034db9d05f8193a95fe5af8d5e12ab295a501c17c95cdbeaf226d6290a0c2866034db9d05f8193a95fe5af8d5e12ab295a501c17c95cdbeaf226d62
```
......@@ -46,7 +46,7 @@ An example of genesis configuration file: `resources/gdev.json`
## 5. Generate raw spec
```docker
docker run -v $HOME/dev/duniter-v2s/resources:/var/lib/duniter/resources -e DUNITER_GENESIS_CONFIG=/var/lib/duniter/resources/gdev.json --rm -it --entrypoint duniter duniter/duniter-v2s:TAG build-spec -lerror --chain=gdev-gl --raw > name-raw.json
docker run -v $HOME/dev/duniter-v2s/resources:/var/lib/duniter/resources -e DUNITER_GENESIS_CONFIG=/var/lib/duniter/resources/gdev.json --rm duniter/duniter-v2s:TAG -- build-spec -lerror --chain=gdev-gl --raw > name-raw.json
```
```bash
......
# How to deploy a permanent rpc node on ĞDev network
## Publish a node
### Duniter part
See [docker documentation](../../docker/README.md) to install, configure, and start a node.
### Reverse proxy part
See [nginx reverse proxy](./nginx_reverse_proxy.md).
To go further, read [How to become a (black)smith](./smith.md)
## Upgrade your node with minimal interruption
1. Modify docker image tag on your compose file
2. Run `docker compose pull`, this will pull the new image.
3. Run `docker compose up -d --remove-orphans`, this will recreate the container
4. Verify that your node restarted well `docker compose logs duniter-rpc`
5. Remove the old image `docker rmi duniter/duniter-v2s:OLD_TAG`
# How to deploy a permanent rpc node on ĞDev network
## Publish a node
### Duniter part
- Add this docker-compose template on your server:
[docker/compose/gdev-rpc.docker-compose.yml](https://git.duniter.org/nodes/rust/duniter-v2s/-/blob/master/docker/compose/gdev-mirror.docker-compose.yml)
- Rename the file : `mv gdev-mirror.docker-compose.yml docker-compose.yml`
- In the same folder, create a `.env` file that defime environment variables `SERVER_DOMAIN`:
```bash
SERVER_DOMAIN=YOUR_DOMAIN
```
- Do `docker compose up -d` to start your node
### Reverse-proxy part (with Nginx)
# Nginx reverse proxy example
In `/etc/nginx/sites-enabled/gdev.YOUR_DOMAIN` put (you can probably do simpler):
......@@ -66,13 +50,3 @@ and replace `YOUR_DOMAIN` by your domain each time.
- `service nginx reload`
Your node is now online as a rpc node. It's fully capable for wallet use.
To go further, read [How to become a (black)smith](./smith.md)
## Upgrade your node with minimal interruption
1. Modify docker image tag on your compose file
2. Run `docker compose pull`, this will pull the new image.
3. Run `docker compose up -d --remove-orphans`, this will recreate the container
4. Verify that your node restarted well `docker compose logs duniter-rpc`
5. Remove the old image `docker images rmi duniter/duniter-v2s:OLD_TAG`
......@@ -4,67 +4,11 @@
### Duniter part
- Add this docker-compose on your server :
[docker/compose/gdev-validator.docker-compose.yml](https://git.duniter.org/nodes/rust/duniter-v2s/-/blob/master/docker/compose/gdev-validator.docker-compose.yml)
- Create a `.env` file that define environment variable `SERVER_DOMAIN`:
See [docker documentation](../../docker/README.md) to install, configure, and start a node. For a smith node, you want to set `DUNITER_VALIDATOR` to `true`.
```bash
SERVER_DOMAIN=YOUR_DOMAIN
```
### Reverse proxy part
- `docker compose up -d` to start your node
### Reverse-proxy part (with Nginx)
In `/etc/nginx/sites-enabled/gdev.YOUR_DOMAIN` put (you can probably do simpler):
```nginx
server {
server_name gdev.YOUR_DOMAIN.fr;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/nginx/ssl/YOUR_DOMAIN.cert;
ssl_certificate_key /etc/nginx/ssl/YOUR_DOMAIN.key;
root /nowhere;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_read_timeout 90;
location /http {
proxy_pass http://localhost:9933;
proxy_http_version 1.1;
}
location /ws {
proxy_pass http://localhost:9944;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_read_timeout 1200s;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}
```
and replace `YOUR_DOMAIN` by your domain each time.
- [generate your ssl certificates](https://github.com/acmesh-official/acme.sh) with let's encrypt
if you don't already have a wildcard certificate.
- `service nginx reload`
Your node is now online as a rpc node. It's fully capable for wallet use.
See [nginx reverse proxy](./nginx_reverse_proxy.md).
## Join the Smith WoT
......@@ -84,9 +28,9 @@ When you have at least 3 certifications, your'in!
- Generate and publish your session keys
1. create an ssh bridge from your desktop/laptop to your server : `ssh -L 9945:localhost:9945 SSH_USER@YOUR_SERVER`
2. In your browser go to [polkadotjs : ws://localhost:9945](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2Flocalhost%3A9945#/explorer)
3. In the UI : developer > appel RPC > author > rotateKey() and run
4. copy the result in clipboard
5. In the UI : developer > extrinsics > YOUR_SMITH_ACCOUNT > authorityMembers > setSessionKeys(keys) then copy your session keys and run the query.
3. In the UI : developer > appel RPC > author > rotateKey() and copy the result in clipboard
4. In the UI : developer > extrinsics > YOUR_SMITH_ACCOUNT > authorityMembers > setSessionKeys(keys) then paste your session keys and run the query.
5. In the UI : developer > extrinsics > YOUR_SMITH_ACCOUNT > authorityMembers > claimMembership(keys)
6. **wait 48h to verify you keep sync**
- Join
- In the UI : developer > extrinsics > YOUR_SMITH_ACCOUNT > authorityMembers > goOnline()
......@@ -99,4 +43,4 @@ If you're not able to monitor, reboot, act on your node, goOffline() to avoid pe
2. Run `docker compose pull`, this will pull the new image.
3. Run `docker compose up -d --remove-orphans`, this will recreate the container
4. Verify that your node restarted well `docker compose logs duniter-validator`
5. Remove the old image `docker images rmi duniter/duniter-v2s:OLD_TAG`
5. Remove the old image `docker rmi duniter/duniter-v2s:OLD_TAG`
......@@ -28,7 +28,7 @@ pub async fn set_balance(client: &Client, who: AccountKeyring, amount: u64) -> R
.create_signed(
&gdev::tx()
.sudo()
.sudo(gdev::runtime_types::gdev_runtime::Call::Balances(
.sudo(gdev::runtime_types::gdev_runtime::RuntimeCall::Balances(
pallet_balances::pallet::Call::set_balance {
who: MultiAddress::Id(who.to_account_id()),
new_free: amount,
......
......@@ -187,30 +187,7 @@ pub fn run() -> sc_cli::Result<()> {
match &cli.subcommand {
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
if cmd.shared_params.dev {
match config.chain_spec.runtime_type() {
#[cfg(feature = "g1")]
RuntimeType::G1 => cmd.run(
Box::new(chain_spec::g1::development_chain_spec()?),
config.network,
),
#[cfg(feature = "gtest")]
RuntimeType::GTest => cmd.run(
Box::new(chain_spec::gtest::development_chain_spec()?),
config.network,
),
#[cfg(feature = "gdev")]
RuntimeType::GDev => cmd.run(
Box::new(chain_spec::gdev::development_chain_spec()?),
config.network,
),
_ => panic!("unknown runtime"),
}
} else {
cmd.run(config.chain_spec, config.network)
}
})
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
}
Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd)?;
......
# Duniter pallets
Duniter uses some [parity pallets](https://github.com/duniter/substrate/tree/master/frame) available in our substrate fork, and some defined here. Each pallet has its own readme, but here is a summary:
## Business processes pallets
These pallets are at the core of Duniter/Ğ1 currency
- **`authority-members`** Duniter authorities are not selected with staking but through a smith web of trust.
- **`certification`** Certifications are the "edges" of Duniter's dynamic directed graph. They mean the acceptation of a Licence.
- **`duniter-account`** Duniter customized the `AccountData` defined in the `Balances` pallet to introduce a `RandomId`.
- **`duniter-wot`** Merges identities, membership, certifications and distance pallets to implement Duniter Web of Trust.
- **`duniter-distance`** Offchain worker used to compute distance criterion.
- **`identity`** Identities are the "nodes" of Duniter's dynamic directed graph. They are one-to-one mapping to human being.
- **`membership`** Membership defines the state of identities. They can be member or not of the different WoTs.
- **`universal-dividend`** UD is at the basis of Ğ1 "libre currency". It is both a kind of "basic income" and a measure unit.
## Functional pallets
- **`duniter-test-parameters`** Test parameters only used in ĞDev to allow tweaking parameters more easily.
- **`oneshot-account`** Oneshot accounts are light accounts only used once for anonimity or convenience use case.
- **`provide-randomness`** Lets blockchain users ask for a verifiable random number.
- **`upgrade-origin`** Allows some origins to dispatch a call as root.
\ No newline at end of file
# Duniter authority members pallet
In a permissioned network, we have to define the set of authorities, and among these authorities, the ones validators in the next session. That's what authority members pallet does. In practice:
- it manages a `Members` set with some custom rules
- it implements the `SessionManager` trait from the session frame pallet
## Entering the set of authorities
To become part of Duniter authorities, one has to complete these steps:
1. become member of the main web of trust
1. request membership to the smith sub wot
1. get enough certs to get smith membership
1. claim membership to the set of authorities
Then one can "go online" and "go offline" to enter or leave two sessions after.
## Staying in the set of authorities
If a smith is offline more than `MaxOfflineSessions`, he leaves the set of authorities.
## Some vocabulary
*Smiths* are people allowed to forge blocks, but in details this is:
- **smith** status required to become an authority
- **authority** status required to become validator
- **validator** status required to add blocks
\ No newline at end of file
......@@ -128,37 +128,45 @@ pub mod pallet {
// STORAGE //
/// maps member id to account id
#[pallet::storage]
#[pallet::getter(fn account_id_of)]
pub type AccountIdOf<T: Config> =
StorageMap<_, Twox64Concat, T::MemberId, T::AccountId, OptionQuery>;
/// count the number of authorities
#[pallet::storage]
#[pallet::getter(fn authorities_counter)]
pub type AuthoritiesCounter<T: Config> = StorageValue<_, u32, ValueQuery>;
/// list incoming authorities
#[pallet::storage]
#[pallet::getter(fn incoming)]
pub type IncomingAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>;
/// list online authorities
#[pallet::storage]
#[pallet::getter(fn online)]
pub type OnlineAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>;
/// list outgoing authorities
#[pallet::storage]
#[pallet::getter(fn outgoing)]
pub type OutgoingAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>;
/// maps member id to member data
#[pallet::storage]
#[pallet::getter(fn member)]
pub type Members<T: Config> =
StorageMap<_, Twox64Concat, T::MemberId, MemberData<T::AccountId>, OptionQuery>;
/// maps session index to the list of member id set to expire at this session
#[pallet::storage]
#[pallet::getter(fn members_expire_on)]
pub type MembersExpireOn<T: Config> =
StorageMap<_, Twox64Concat, SessionIndex, Vec<T::MemberId>, ValueQuery>;
/// maps session index to the list of member id forced to rotate keys before this session
#[pallet::storage]
#[pallet::getter(fn must_rotate_keys_before)]
pub type MustRotateKeysBefore<T: Config> =
......@@ -220,6 +228,7 @@ pub mod pallet {
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000_000_000)]
/// ask to leave the set of validators two sessions after
pub fn go_offline(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
// Verification phase //
let who = ensure_signed(origin)?;
......@@ -246,6 +255,7 @@ pub mod pallet {
Ok(().into())
}
#[pallet::weight(1_000_000_000)]
/// ask to join the set of validators two sessions after
pub fn go_online(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
// Verification phase //
let who = ensure_signed(origin)?;
......@@ -282,6 +292,7 @@ pub mod pallet {
}
#[pallet::weight(1_000_000_000)]
/// declare new session keys to replace current ones
pub fn set_session_keys(
origin: OriginFor<T>,
keys: T::KeysWrapper,
......@@ -314,6 +325,7 @@ pub mod pallet {
Ok(().into())
}
#[pallet::weight(1_000_000_000)]
/// remove an identity from the set of authorities
pub fn remove_member(
origin: OriginFor<T>,
member_id: T::MemberId,
......@@ -330,8 +342,12 @@ pub mod pallet {
// PUBLIC FUNCTIONS //
impl<T: Config> Pallet<T> {
/// Should be transactional
// Should be transactional (if an error occurs, storage should not be modified at all)
// Execute the annotated function in a new storage transaction.
// The return type of the annotated function must be `Result`. All changes to storage performed
// by the annotated function are discarded if it returns `Err`, or committed if `Ok`.
#[frame_support::transactional]
/// change owner key of an authority member
pub fn change_owner_key(
member_id: T::MemberId,
new_owner_key: T::AccountId,
......@@ -370,6 +386,7 @@ pub mod pallet {
// INTERNAL FUNCTIONS //
impl<T: Config> Pallet<T> {
/// perform authority member removal
fn do_remove_member(member_id: T::MemberId, owner_key: T::AccountId) -> Weight {
if Self::is_online(member_id) {
// Trigger the member deletion for next session
......@@ -398,6 +415,7 @@ pub mod pallet {
Weight::zero()
}
/// perform planned expiration of authority member for the given session
pub(super) fn expire_memberships(current_session_index: SessionIndex) {
for member_id in MembersExpireOn::<T>::take(current_session_index) {
if let Some(member_data) = Members::<T>::get(member_id) {
......@@ -414,6 +432,7 @@ pub mod pallet {
}
}
}
/// perform incoming authorities insertion
fn insert_in(member_id: T::MemberId) -> bool {
let not_already_inserted = IncomingAuthorities::<T>::mutate(|members_ids| {
if let Err(index) = members_ids.binary_search(&member_id) {
......@@ -429,6 +448,7 @@ pub mod pallet {
}
not_already_inserted
}
/// perform outgoing authority insertion
fn insert_out(member_id: T::MemberId) -> bool {
let not_already_inserted = OutgoingAuthorities::<T>::mutate(|members_ids| {
if let Err(index) = members_ids.binary_search(&member_id) {
......@@ -448,21 +468,25 @@ pub mod pallet {
}
not_already_inserted
}
/// check if member is incoming
fn is_incoming(member_id: T::MemberId) -> bool {
IncomingAuthorities::<T>::get()
.binary_search(&member_id)
.is_ok()
}
/// check if member is online
fn is_online(member_id: T::MemberId) -> bool {
OnlineAuthorities::<T>::get()
.binary_search(&member_id)
.is_ok()
}
/// check if member is outgoing
fn is_outgoing(member_id: T::MemberId) -> bool {
OutgoingAuthorities::<T>::get()
.binary_search(&member_id)
.is_ok()
}
/// perform removal from incoming authorities
fn remove_in(member_id: T::MemberId) {
AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_sub(1));
IncomingAuthorities::<T>::mutate(|members_ids| {
......@@ -471,6 +495,7 @@ pub mod pallet {
}
})
}
/// perform removal from online authorities
fn remove_online(member_id: T::MemberId) {
AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_add(1));
OnlineAuthorities::<T>::mutate(|members_ids| {
......@@ -479,6 +504,7 @@ pub mod pallet {
}
});
}
/// perform removal from outgoing authorities
fn remove_out(member_id: T::MemberId) {
OutgoingAuthorities::<T>::mutate(|members_ids| {
if let Ok(index) = members_ids.binary_search(&member_id) {
......@@ -486,6 +512,7 @@ pub mod pallet {
}
});
}
/// check that accountid is member
fn verify_ownership_and_membership(
who: &T::AccountId,
) -> Result<T::MemberId, DispatchError> {
......@@ -521,6 +548,7 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
if members_ids_to_add.is_empty() {
if members_ids_to_del.is_empty() {
// when no change to the set of autorities, return None
return None;
} else {
for member_id in &members_ids_to_del {
......@@ -540,6 +568,7 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
Self::deposit_event(Event::IncomingAuthorities(members_ids_to_add.clone()));
}
// updates the list of OnlineAuthorities and returns the list of their key
Some(
OnlineAuthorities::<T>::mutate(|members_ids| {
for member_id in members_ids_to_del {
......@@ -594,6 +623,7 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
}
}
// see substrate FullIdentification
fn add_full_identification<T: Config>(
validator_id: T::ValidatorId,
) -> Option<(T::ValidatorId, T::FullIdentification)> {
......@@ -602,6 +632,7 @@ fn add_full_identification<T: Config>(
.map(|full_ident| (validator_id, full_ident))
}
// implement SessionManager with FullIdentification
impl<T: Config> pallet_session::historical::SessionManager<T::ValidatorId, T::FullIdentification>
for Pallet<T>
{
......
......@@ -25,8 +25,11 @@ use sp_staking::SessionIndex;
#[cfg_attr(feature = "std", derive(Debug, Deserialize, Serialize))]
#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)]
pub struct MemberData<AccountId> {
/// session at which the membership expires
pub expire_on_session: SessionIndex,
/// session before which the member must have rotated keys
pub must_rotate_keys_before: SessionIndex,
/// pubkey of the member
pub owner_key: AccountId,
}
......
# Duniter certification pallet
Duniter certifications are the *edges* in the Duniter [Web of Trust](../duniter-wot/). They can have different meanings:
- in the case of the main WoT, they mean "I have met this person IRL and trust them" (see Ğ1 Licence)
- in the case of the smith sub-WoT, they mean "I trust this person to be able to run Duniter securely" (see smith Licence)
This pallet manages certifications creation, deletion...
\ No newline at end of file