Running full local network for tests (duniter + indexer)

@txels is trying to run a local network (duniter + indexer) and connect to it with gcli. I’m copying here his DM because I prefer to do support in public (we have a Support category for that) so that more people can benefit from it.

1 Like

It looks like your local network is using dev chainspecs with only a few initial accounts (Alice, Bob, Charlie…)

# local duniter with dev chainspecs
duniter --dev
# equivalent to 
duniter --chain=dev --tmp --validator --alice
# see duniter --help for more info

# local duniter with gdev chainspecs
duniter --chain=gdev --tmp --validator --alice

But your indexer is using gdev chainspecs data with an export of the Ğ1 data dating from 04/02/2024. ĞCli can check if the indexer is on the same network as duniter with gcli indexer check but not that the given genesis data are actually correct.

To customize the input files of the indexer, you can edit your .env: .env.example · main · nodes / duniter-squid · GitLab

GENESIS_FILE="gdev.json"        # "test.json"
HISTORY_FILE="history.json"     # "history_empty.json"

The gdev.json can be replaced by the output of the following command:

# build chainspecs of local network
duniter build-spec --chain=dev > dev.json

Now you have more info. But the gdev network is here for tests. Sorry I forgot to send you some ĞDevs so you can test, no you have some at address 5EYqFMrSmMJ35mpXFXwr5w5GJj1kYmmKXLWbj3uHnDE5QBBu on gdev network.

1 Like

Thanks for the tips.

I have generated the local chainspec file with duniter build-spec --chain=dev > dev.json however the json schema of my resulting file doesn’t seem to match, and the indexer fails to run.


  "genesis": {
    "runtimeAndCode": {
      "runtime": {
        "system": {},
        "account": {
          "accounts": {

Newly generated local.json:

  "genesis": {
    "runtimeGenesis": {
      "code": "...",
      "patch": {
        "account": {
          "accounts": {
1 Like

I could manage to make this work by editing genesis.ts in the indexer to match the new schema, and manually editing the resulting local.json file to add expiry blocks on certifications (they were all null) like this:

          "certsByReceiver": {
            "1": {
              "2": 1555325,  # arbitrary, based on a value in gdev.json
              "3": 1555325,
              "4": 1555325

…but doesn’t seem like the correct way to do this, just a temporary hack to get me up and running.

Seems like a different version of Duniter. Are you on master after !229 was merged?

With this in place, things at least are consistent

$ cargo run -- identity get -i 1
Identity index: 1
Username:       Alice
Address:        5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
Status:         Member
Certifications: issued ["Bob", "Charlie", "Dave"], received ["Bob", "Charlie", "Dave"]
Smith status:   Smith
Smith certs:    issued 2, received 2

Seems like a different version of Duniter. Are you on master after !229 was merged?

I think so, yes

Now when I create an account with gcli, it gets indexed… in principle:

[processor] 19:32:42 INFO  sqd:processor:mapping 136 System.NewAccount
[processor] 19:32:42 INFO  sqd:processor:mapping 136 Identity.IdtyCreated
[processor] 19:32:42 INFO  sqd:processor:mapping 136 Account.AccountLinked
[processor] 19:32:42 INFO  sqd:processor:mapping 136 Certification.CertAdded
[processor] 19:32:42 INFO  sqd:processor:mapping Added account 5DHcUhgWBTiu8fvQfYsXxMHrFLyWeYPhPHyGG2HZceg9Naah
squid=# select * from account;
                        id                        |   linked_identity_id    
 5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy | 
 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty | 
 5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y | 
 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY | 
 5DHcUhgWBTiu8fvQfYsXxMHrFLyWeYPhPHyGG2HZceg9Naah | 0000000136-a5631-000003

I see in the indexer history that the old format was

 "genesis": {
    "runtime": {
      "system": {
        "code": "

and the new is

"genesis": {
    "runtimeAndCode": {
      "runtime": {
        "system": {},

So I’m curious how you get

which I do not have in my history. Maybe an other update that happened later and that was not used. Try to use a binary from the branch runtime-800 before !236 was merged.

Yes, that’s normal. Because in Duniter v2 the identity is created before being named, the indexer uses a default name corresponding to the event id of the identity creation (here it is). Now you can confirm the identity to give it a name.

$ cargo run -- --address 5DHcUhgWBTiu8fvQfYsXxMHrFLyWeYPhPHyGG2HZceg9Naah identity confirm txels
Subxt(Rpc(ClientError(Call(ErrorObject { code: ServerError(1010), message: "Invalid Transaction", data: Some(RawValue("Inability to pay some fees (e.g. account balance too low)")) }))))

…I think you had some instructions for this whole process I misplaced.

I tried also

$ cargo run -q -- account transfer 1000 5DHcUhgWBTiu8fvQfYsXxMHrFLyWeYPhPHyGG2HZceg9Naah        
transaction submitted to the network, waiting 6 seconds...
transfered 10 ĞD (5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY → 5DHcUhgWBTiu8fvQfYsXxMHrFLyWeYPhPHyGG2HZceg9Naah)

$ cargo run -- --address 5DHcUhgWBTiu8fvQfYsXxMHrFLyWeYPhPHyGG2HZceg9Naah identity confirm txels
Subxt(Rpc(ClientError(Call(ErrorObject { code: ServerError(1010), message: "Invalid Transaction", data: Some(RawValue("Inability to pay some fees (e.g. account balance too low)")) }))))

no luck

I can confirm that. You were too up to date!! The genesis format changed and the indexer is not ready for that yet because it is still using an “old” version of the chainspecs generated with the duniter version in the runtime-800 branch.

The address arg is a pubkey, but to perfom actions = calls, you need the privkey which is derived from the mnemonic you provided. To know the address corresponding to a mnemonic and the balance of the account on the network you are connecting to, you can do gcli account balance. I like to use a mnemonic in clear in my config file to avoid pasting it every time (with gcli config). And soon we will have proper keyring management (see #17). Bear in mind that squid and gcli are highly experimental and it is normal that you meet their limits ^^
Btw this is a hard but good way to learn their deep behavior.

I can push my local changes to the indexer as an MR. It will be incomplete but a starting point:

Feel free anyone to take that through, I guess it requires a careful rollout, and re-generating the data files that are now obsolete.


So… I got as far as having an identity certified by all four original bootstrap members… however I am not a member. Am I missing an additional call?

$ gcli identity show
Identity index: 5
Username:       txels
Address:        5HKgju4S9BcqC2Yh7ex1FTVbhapdEUJzy3fYuy6f1vnbXoL7
Status:         Unvalidated
Certifications: issued [], received ["Charlie", "Dave", "Bob", "Alice"]

I did request a distance calculation and ran the distance oracle…

$ gcli -S predefined -s Alice identity request-distance-evaluation-for 5
transaction submitted to the network, waiting 6 seconds...
evaluation requested EvaluationRequested { idty_index: 5, who: AccountId32([212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]) }

Waited a little. On Duniter I ran:

$ ./target/debug/distance-oracle
INFO [distance_oracle] Evaluating distance for session 13
INFO [distance_oracle] Distance for idty 5: 4/4 = 100%

On the indexer DB:

squid=# select * from identity where name='txels';
-[ RECORD 1 ]--+-------------------------------------------------
id             | 0000000036-72065-000003
index          | 5
name           | txels
status         | Unvalidated
created_on     | 36
last_change_on | 48
smith_status   | 
is_member      | f
expire_on      | 88
account_id     | 5HKgju4S9BcqC2Yh7ex1FTVbhapdEUJzy3fYuy6f1vnbXoL7
created_in_id  | 0000000036-72065-000003

…no idea what step I am missing. Is it because for some reason the number of certifications required is hardcoded to 5 rather than match the size of the membership?

Look in the distance pool if your oracle published a result. But you are going quite deep here, distance oracle implementation is still fresh and we did not experiment a lot on it locally. Even on gdev we currently do not have a working distance oracle (due to the docker entrypoint problem, see Oracle de distance dans un docker and Docker distance entrypoint is outdated (#199) · Issues · nodes / rust / Duniter v2S · GitLab).

The oracle is writing a result file in the duniter chain directory. Then the file is used to publish results in an inherent next time the validator adds a block. You are trying to debug one of the most experimental part of the software in an untested environment. It is normal if it seems difficult.

When nothing happens duniter side, indexer can not have the info! If you want to debug duniter, connect to it with polkadotjs app.

To shortcut distance oracle, you can use the sudo call to force valid evaluation. For this kind of custom operation, it’s convenient to use polkadotjs app.

I see a file has been created by the oracle under /tmp/duniter/chains/gdev/distance/14
I don’t see any event in the blockchain that looks like the result has been read and published. So maybe duniter is not reading from the same location…? I can’t find the configuration for that.

duniter --help | grep base-dir
distance-oracle --help | grep result-dir

Even when it’s written in the good location, have in mind that it takes two sessions (2h) for the result to be taken into account. I repeat it, the distance oracle is one of the most sophisticated part and not the easiest to understand. It was designed by elois and tuxmain. You can read about it on the forum under the tag distance. The doc entrypoint is here: distance-oracle · master · nodes / rust / Duniter v2S · GitLab but it is quite superficial at the moment.