duniter issueshttps://git.duniter.org/nodes/typescript/duniter/-/issues2023-06-11T10:45:07+02:00https://git.duniter.org/nodes/typescript/duniter/-/issues/1447Reverting a block will never trim LevelDBSindex.indexForTrimming2023-06-11T10:45:07+02:00Benoit LavenierReverting a block will never trim LevelDBSindex.indexForTrimmingIn [`LevelDBSindex.removeBlock()`](https://git.duniter.org/nodes/typescript/duniter/-/blob/dev/app/lib/dal/indexDAL/leveldb/LevelDBSindex.ts#L313) the function `trimWrittenOn()` is supposed to clean entries of the index `indexForTrimming...In [`LevelDBSindex.removeBlock()`](https://git.duniter.org/nodes/typescript/duniter/-/blob/dev/app/lib/dal/indexDAL/leveldb/LevelDBSindex.ts#L313) the function `trimWrittenOn()` is supposed to clean entries of the index `indexForTrimming` but instead indexForConditions is used :
```
private async trimWrittenOn(writtenOn: number, id: string) {
const k = LevelDBSindex.trimWrittenOnKey(writtenOn);
const existing = await this.getWrittenOnSourceIds(writtenOn);
const trimmed = arrayPruneAllCopy(existing, id);
if (trimmed.length) {
await this.indexForConditionsput(k, trimmed); // <= SHOULD BE indexForTrimming
} else {
await this.indexForConditions.del(k); // <= SHOULD BE indexForTrimming
}
}
```Cédric MoreauCédric Moreauhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1398Paramètre ` onlyPeers` ne fonctionne plus2023-09-19T15:32:34+02:00insoParamètre ` onlyPeers` ne fonctionne plusSuite à la synchro de mon noeud, il se retrouve isolé. Les quelques pairs qu'il a récupéré timeout. je souhaitais ne synchroniser que les pairs pour aller plus vite, mais la commande échoue :
```
g1@yunohost:/opt/scripts-for-duniter# ...Suite à la synchro de mon noeud, il se retrouve isolé. Les quelques pairs qu'il a récupéré timeout. je souhaitais ne synchroniser que les pairs pour aller plus vite, mais la commande échoue :
```
g1@yunohost:/opt/scripts-for-duniter# duniter sync duniter.acostey.fr --onlypeers --nointeractive
2020-04-05T07:14:56+02:00 - debug: Plugging file system...
2020-04-05T07:14:56+02:00 - debug: Loading conf...
2020-04-05T07:14:56+02:00 - debug: Configuration saved.
Failed to open file for reading : /opt/g1/.config/duniter/duniter_default/wotb.bin
2020-04-05T07:14:56+02:00 - debug: Opening SQLite database "/opt/g1/.config/duniter/duniter_default/duniter.db"...
2020-04-05T07:14:57+02:00 - debug: Opening SQLite database "/opt/g1/.config/duniter/duniter_default/txs.db"...
2020-04-05T07:14:57+02:00 - debug: Opening SQLite database "/opt/g1/.config/duniter/duniter_default/peers.db"...
2020-04-05T07:14:59+02:00 - debug: Upgrade database...
2020-04-05T07:15:06+02:00 - info: Block resolution: 0 potential blocks for root block...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_blockchain...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_wallet...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_bindex...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_mindex...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_iindex...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_sindex...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_cindex...
2020-04-05T07:15:06+02:00 - debug: Closing LevelDB level_dividend...
2020-04-05T07:15:06+02:00 - debug: Trying to close SQLite...
2020-04-05T07:15:06+02:00 - debug: Trying to close SQLite...
2020-04-05T07:15:06+02:00 - error: TypeError: Cannot read property 'getPeers' of undefined
at RemoteSynchronizer.syncPeers (/opt/duniter/app/modules/crawler/lib/sync/RemoteSynchronizer.js:258:39)
at Object.onDatabaseExecute (/opt/duniter/app/modules/crawler/index.js:130:41)
at Stack.processCommand (/opt/duniter/index.js:380:47)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:160:7)
```https://git.duniter.org/nodes/typescript/duniter/-/issues/1371Replacing naclb by node-sodium2019-05-07T22:08:29+02:00Cédric MoreauReplacing naclb by node-sodiumNaclb was a handmaid port dependency for fast, native C++ execution of Nacl (speed needed for PoW).
Today, it exists [node-sodium](https://github.com/paixaop/node-sodium) which seems to do this exact job and be maintained actively and b...Naclb was a handmaid port dependency for fast, native C++ execution of Nacl (speed needed for PoW).
Today, it exists [node-sodium](https://github.com/paixaop/node-sodium) which seems to do this exact job and be maintained actively and bases on stantard C++ libs.
Maybe we could replace naclb by node-sodium.Horizonhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1337lost peers after new release2019-02-02T02:29:37+01:00nikolost peers after new releasewith windows edition
currently the 1.7.10 does not have peers anymore
happen all the time when there is a new version availablewith windows edition
currently the 1.7.10 does not have peers anymore
happen all the time when there is a new version availablehttps://git.duniter.org/nodes/typescript/duniter/-/issues/1336Fork resolution may fail to recover a consumed source2019-01-30T19:40:11+01:00Cédric MoreauFork resolution may fail to recover a consumed sourceSee https://forum.duniter.org/t/g1-en-fork-bloc-refuse-car-la-transaction-utilise-des-sources-inexistantes/5677See https://forum.duniter.org/t/g1-en-fork-bloc-refuse-car-la-transaction-utilise-des-sources-inexistantes/5677https://git.duniter.org/nodes/typescript/duniter/-/issues/1334Write a test for issue #13322020-04-30T22:26:18+02:00Cédric MoreauWrite a test for issue #1332Issue #1332 is fixed, but we need a test to lock the behavior.Issue #1332 is fixed, but we need a test to lock the behavior.Horizonhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1307Api wot/lookup fail with "Cannot read property 'number' of undefined"2018-07-24T17:40:40+02:00Vincent TexierApi wot/lookup fail with "Cannot read property 'number' of undefined"https://g1-test.duniter.org/wot/lookup/vit
or
```
curl https://g1-test.duniter.org/wot/lookup/droYn565eApVvJFu18trt4qTiS8uFcVpd5TdwSUPQAT
```
return:
```
{
"ucode": 1002,
"message": "Cannot read property 'number' of undefined"
}...https://g1-test.duniter.org/wot/lookup/vit
or
```
curl https://g1-test.duniter.org/wot/lookup/droYn565eApVvJFu18trt4qTiS8uFcVpd5TdwSUPQAT
```
return:
```
{
"ucode": 1002,
"message": "Cannot read property 'number' of undefined"
}
```https://git.duniter.org/nodes/typescript/duniter/-/issues/1280sync: delete filesystem chunks that do not chains correctly2020-05-01T13:19:11+02:00Cédric Moreausync: delete filesystem chunks that do not chains correctlyhttps://forum.duniter.org/t/bug-de-synchro-sur-g1-test/4245/101?u=cgeekhttps://forum.duniter.org/t/bug-de-synchro-sur-g1-test/4245/101?u=cgeekHorizonhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1258add WS2P into wizard network command2020-10-04T18:42:39+02:00Éloïsadd WS2P into wizard network command2.0https://git.duniter.org/nodes/typescript/duniter/-/issues/1239Change the proof of work algorithm2018-12-07T14:22:42+01:00Cédric MoreauChange the proof of work algorithmAs discussed here: https://mastodon.xyz/web/statuses/99174770035035196
It seems that the current PoW chain (`SHA256(Ed25519_sign(SHA256("InnerHash:...Nonce: <nonce>")))`) is still ASIC compliant, in that an ASIC could still handle this ...As discussed here: https://mastodon.xyz/web/statuses/99174770035035196
It seems that the current PoW chain (`SHA256(Ed25519_sign(SHA256("InnerHash:...Nonce: <nonce>")))`) is still ASIC compliant, in that an ASIC could still handle this computation.
@aeris suggests to either use ARGON2 or scrypt currently, because these functions introduce a tradeoff between CPU and memory.
I'm not an expert, so I can just believe this assertion right now.
Anyway, as long as the number of ASIC powered member nodes is low compared to the number of non-ASIC powered member nodes, it won't be a big problem. But it would still be annoying, even more later if Ğ1 growth.2.0https://git.duniter.org/nodes/typescript/duniter/-/issues/979Use YAML format for document parsing2020-10-04T18:51:39+02:00Cédric MoreauUse YAML format for document parsingDuniter documents' format is so much close to YAML that it would really be better to use diretly this format, allowing us to use YAML tools that exists in our prefered language.
Note: this does not require any change in the protocol, we...Duniter documents' format is so much close to YAML that it would really be better to use diretly this format, allowing us to use YAML tools that exists in our prefered language.
Note: this does not require any change in the protocol, we can keep our current format (a.k.a. RAW) for signing documents. However, we can work with a YAML transformation for parsing documents coming from the network in RAW format:
RAW --> YAML --> JSON --> RAW
* `RAW --> YAML` would be done by us, according the the very simple algorithms given below
* `YAML --> JSON` would be done by `js-yaml` library (or equivalent on other platforms)
* `JSON --> RAW` would be done by us, because we want very specifc layout for signing documents
That's cool because we won't need text parsers anymore, we can delegate this job to YAML parser. For example, [this code would be removed from Duniter](https://github.com/duniter/duniter/tree/master/app/lib/streams/parsers) (notably the one in GenericParser.js).
I would then add this core stuff in `duniter-common` module, so anything concerning documents and their format would be available to any Node.js library which would need it.
Note how the YAML format for blocks makes it very easy to read every field:
Look:
### Duniter block format
```
Version: VERSION
Type: Block
Currency: CURRENCY
Number: BLOCK_ID
PoWMin: NUMBER_OF_ZEROS
Time: GENERATED_ON
MedianTime: MEDIAN_DATE
UniversalDividend: DIVIDEND_AMOUNT
UnitBase: UNIT_BASE
Issuer: ISSUER_KEY
IssuersFrame: ISSUERS_FRAME
IssuersFrameVar: ISSUERS_FRAME_VAR
DifferentIssuersCount: ISSUER_KEY
PreviousHash: PREVIOUS_HASH
PreviousIssuer: PREVIOUS_ISSUER_KEY
Parameters: PARAMETERS
MembersCount: WOT_MEM_COUNT
Identities:
PUBLIC_KEY:SIGNATURE:I_BLOCK_UID:USER_ID
...
Joiners:
PUBLIC_KEY:SIGNATURE:M_BLOCK_UID:I_BLOCK_UID:USER_ID
...
Actives:
PUBLIC_KEY:SIGNATURE:M_BLOCK_UID:I_BLOCK_UID:USER_ID
...
Leavers:
PUBLIC_KEY:SIGNATURE:M_BLOCK_UID:I_BLOCK_UID:USER_ID
...
Revoked:
PUBLIC_KEY:SIGNATURE
...
Excluded:
PUBLIC_KEY
...
Certifications:
PUBKEY_FROM:PUBKEY_TO:BLOCK_ID:SIGNATURE
...
Transactions:
COMPACT_TRANSACTION
...
InnerHash: BLOCK_HASH
Nonce: NONCE
BOTTOM_SIGNATURE
```
What do we lack precisely to have a valid YAML document?
* prefix each multiline field value with `- `
* prefix `BOTTOM_SIGNATURE` with `Sig: `
* change COMPACT_TRANSACTION format
Result:
```yml
Version: VERSION
Type: Block
Currency: CURRENCY
Number: BLOCK_ID
PoWMin: NUMBER_OF_ZEROS
Time: GENERATED_ON
MedianTime: MEDIAN_DATE
UniversalDividend: DIVIDEND_AMOUNT
UnitBase: UNIT_BASE
Issuer: ISSUER_KEY
IssuersFrame: ISSUERS_FRAME
IssuersFrameVar: ISSUERS_FRAME_VAR
DifferentIssuersCount: ISSUER_KEY
PreviousHash: PREVIOUS_HASH
PreviousIssuer: PREVIOUS_ISSUER_KEY
Parameters: PARAMETERS
MembersCount: WOT_MEM_COUNT
Identities:
- PUBLIC_KEY:SIGNATURE:I_BLOCK_UID:USER_ID
- ...
Joiners:
- PUBLIC_KEY:SIGNATURE:M_BLOCK_UID:I_BLOCK_UID:USER_ID
- ...
Actives:
- PUBLIC_KEY:SIGNATURE:M_BLOCK_UID:I_BLOCK_UID:USER_ID
- ...
Leavers:
- PUBLIC_KEY:SIGNATURE:M_BLOCK_UID:I_BLOCK_UID:USER_ID
- ...
Revoked:
- PUBLIC_KEY:SIGNATURE
- ...
Excluded:
- PUBLIC_KEY
- ...
Certifications:
- PUBKEY_FROM:PUBKEY_TO:BLOCK_ID:SIGNATURE
- ...
Transactions:
- Head: TX:VERSION:NB_ISSUERS:NB_INPUTS:NB_UNLOCKS:NB_OUTPUTS:HAS_COMMENT:LOCKTIME
Blockstamp: BLOCKSTAMP
Issuers:
- PUBLIC_KEY
- ...
Inputs:
- INPUT
- ...
Unlocks:
- ...
Outputs:
- OUTPUT
- ...
Comment: COMMENT
Sigs:
- SIGNATURE
- ...
- ...
InnerHash: BLOCK_HASH
Nonce: NONCE
Sig: BOTTOM_SIGNATURE
```
### Duniter identity format
Almost YAML compliant, we need to add `Sig: ` at the end:
```yml
Version: 10
Type: Identity
Currency: CURRENCY_NAME
Issuer: PUBLIC_KEY
UniqueID: USER_ID
Timestamp: BLOCK_UID
Sig: IDENTITY_SIGNATURE
```
### Duniter revocation format
Almost YAML compliant, we need to add `Sig: ` at the end:
```yml
Version: 10
Type: Certification
Currency: CURRENCY_NAME
Issuer: PUBLIC_KEY
IdtyIssuer: IDTY_ISSUER
IdtyUniqueID: USER_ID
IdtyTimestamp: BLOCK_UID
IdtySignature: IDTY_SIGNATURE
CertTimestamp: BLOCK_UID
Sig: CERTIFIER_SIGNATURE
```
### Duniter membership format
Almost YAML compliant, we need to add `Sig: ` at the end:
```yml
Version: VERSION
Type: Membership
Currency: CURRENCY_NAME
Issuer: ISSUER
Block: M_BLOCK_UID
Membership: MEMBERSHIP_TYPE
UserID: USER_ID
CertTS: BLOCK_UID
Sig: MEMBERSHIP_SIGNATURE
```
### Duniter revocation format
Almost YAML compliant, we need to add `Sig: ` at the end:
```yml
Version: 10
Type: Revocation
Currency: CURRENCY_NAME
Issuer: PUBLIC_KEY
IdtyUniqueID: USER_ID
IdtyTimestamp: BLOCK_UID
IdtySignature: IDTY_SIGNATURE
Sig: REVOCATION_SIGNATURE
```
### Duniter transaction format
Almost YAML compliant, we need to add `Sig: ` at the end + prefix every multiline field value with a `- `:
```yml
Version: VERSION
Type: Transaction
Currency: CURRENCY_NAME
Blockstamp: BLOCK_UID
Locktime: INTEGER
Issuers:
- PUBLIC_KEY
- ...
Inputs:
- INPUT
- ...
Unlocks:
- UNLOCK
- ...
Outputs:
- AMOUNT:BASE:CONDITIONS
- ...
Comment: COMMENT
Sigs:
- SIGNATURES
- ...
```2.0https://git.duniter.org/nodes/typescript/duniter/-/issues/557Debian repository2020-04-30T22:10:38+02:00Cédric MoreauDebian repository*Created by: M5oul*
- [Debian tutorial](https://wiki.debian.org/HowToSetupADebianRepository)
It would be great to move releases from GitHub to this repositories.
We could have two repositories:
- a `dektop` one.
- a `server` one.
On t...*Created by: M5oul*
- [Debian tutorial](https://wiki.debian.org/HowToSetupADebianRepository)
It would be great to move releases from GitHub to this repositories.
We could have two repositories:
- a `dektop` one.
- a `server` one.
On this two repositories we need to handle CPU arch: `x64` and `armv7l`.
We could have `stable` and `unstable` repositories. `unstable` one is for alphas and betas.
``` bash
deb http://debian.duniter.org/debian stable main
deb http://debian.duniter.org/debian unstable main
```
Horizonhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1449Unit tests : SqlLite connection not well closed2023-06-16T12:41:50+02:00Benoit LavenierUnit tests : SqlLite connection not well closedWhen trying to upgrade `mocha`, i found that DB connection are not well closed, because of write queries, that are asynchronous (see `SqliteNodeIOManager.writePromise`).
Inside `SqliteNodeIOManager.close()`, we wait the end of writing q...When trying to upgrade `mocha`, i found that DB connection are not well closed, because of write queries, that are asynchronous (see `SqliteNodeIOManager.writePromise`).
Inside `SqliteNodeIOManager.close()`, we wait the end of writing queries (add an `await this.writePromise;`1.8.7https://git.duniter.org/nodes/typescript/duniter/-/issues/1446Reverting a block that consumed a source can delete the source, in SINDEX sub...2023-06-12T12:56:27+02:00Benoit LavenierReverting a block that consumed a source can delete the source, in SINDEX sub-index (indexForConditions)This unit test failed "revert b#3-4 and re-commit block#3 should be ok"
Cause:
- In [`LevelDBSindex.removeBlock()`](https://git.duniter.org/nodes/typescript/duniter/-/blob/dev/app/lib/dal/indexDAL/leveldb/LevelDBSindex.ts#L313) (for re...This unit test failed "revert b#3-4 and re-commit block#3 should be ok"
Cause:
- In [`LevelDBSindex.removeBlock()`](https://git.duniter.org/nodes/typescript/duniter/-/blob/dev/app/lib/dal/indexDAL/leveldb/LevelDBSindex.ts#L313) (for reverting a block), we call `trimConditions()` when a consumption is undone (when the `UPDATE` record should be deleted) even if a source creation exists.
Solution:
- The correct approach would be to call `trimConditions()` only when no source creation exists anymore.Cédric MoreauCédric Moreauhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1445Synchronize on BMAS enpoint with a path (e.g. `/bma`)2023-06-06T18:02:11+02:00Benoit LavenierSynchronize on BMAS enpoint with a path (e.g. `/bma`)Yunohost Duniter package deploy BMAS on path `/bma`. Such endpoints seems to be not used by `sync` commandYunohost Duniter package deploy BMAS on path `/bma`. Such endpoints seems to be not used by `sync` commandhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1444SqliteTable: all columns indexed ?2023-06-16T12:38:35+02:00Benoit LavenierSqliteTable: all columns indexed ?En regardant de plus près les index qui existent sur les tables, je m’aperçois que **toutes les colonnes sont indexées**. Par exemple dans le cas de la table des TX, cela fait beaucoup de monde ! :)
Voici [le code responsable](https://...En regardant de plus près les index qui existent sur les tables, je m’aperçois que **toutes les colonnes sont indexées**. Par exemple dans le cas de la table des TX, cela fait beaucoup de monde ! :)
Voici [le code responsable](https://git.duniter.org/nodes/typescript/duniter/-/blob/release/1.8/app/lib/dal/indexDAL/sqlite/SqliteTable.ts#L63) à mon avis :
```typescript
generateCreateIndexes() {
return this.keys()
.map((fieldName) => {
return `CREATE INDEX IF NOT EXISTS idx_${this.name}_${fieldName} ON ${this.name} (${fieldName});\n`;
})
.join("");
}
keys(): (keyof T)[] {
return Underscore.keys(this.fields);
}
```
Il s'agit d'un vieux code. Mais cela doit ralentir de beaucoup l'écriture dans la table, non ? D'autant que tout indexés semble inutile.
Par ailleurs je vois dans le constructeur que l'on a pour chaque colonne un `SqlFieldDefinition` avec un boolean `indexed`. Le but initial était sans doute d'utiliser cette valeur pour savoir quelle colonne indexées ou pas.
Je me trompes @cgeek ? Redis moi stp, si tu te penses que ca peut-être utile que j'optimise des choses de ce côté là aussi.
La correction semble toute simple, mais globalement il faudra retester une synchro pour voir si ca change quelque chose.1.8.7https://git.duniter.org/nodes/typescript/duniter/-/issues/1442Improve BMA `/tx/history/:pubkey/pending`, `/tx/history/:pubkey/blocks/:from/...2023-06-16T12:39:10+02:00Benoit LavenierImprove BMA `/tx/history/:pubkey/pending`, `/tx/history/:pubkey/blocks/:from/:to` and `/tx/history/:pubkey/times/:from/:to`I thhink we cn optimize the response time of BMA `/tx/history/:pubkey/pending`
In Duniter `dev` branch, i can see that:
- in `transactions.ts` the pubkey's full history is laoded (including sending and received), then filtered :
```ts...I thhink we cn optimize the response time of BMA `/tx/history/:pubkey/pending`
In Duniter `dev` branch, i can see that:
- in `transactions.ts` the pubkey's full history is laoded (including sending and received), then filtered :
```ts
async getPendingForPubkey(req: any): Promise<HttpTxHistory> {
const pubkey = await ParametersService.getPubkeyP(req);
return this.getFilteredHistory(pubkey, function (res: any) {
const histo = res.history;
Underscore.extend(histo, { sent: [], received: [] });
return res;
});
}
private async getFilteredHistory(
pubkey: string,
filter: any
): Promise<HttpTxHistory> {
let history = await this.server.dal.getTransactionsHistory(pubkey);
let result = {
currency: this.conf.currency,
pubkey: pubkey,
history: {
sending: history.sending.map(dbtx2HttpTxOfHistory),
received: history.received.map(dbtx2HttpTxOfHistory),
sent: history.sent.map(dbtx2HttpTxOfHistory),
pending: history.pending.map(dbtx2HttpTxOfHistory),
},
};
return filter(result);
}
}
```
- there is not DAL function to get only pending TX, by pubkey1.8.7https://git.duniter.org/nodes/typescript/duniter/-/issues/1441BMA /node/summary : dump config's storage2023-06-16T12:38:48+02:00Benoit LavenierBMA /node/summary : dump config's storageAdd storage infos into `/node/summary`.
New `/node/sumary` response should be :
```json
{
"duniter": {
"software": "duniter",
"version": "1.8.7",
"forkWindowSize": 100,
"storage": {
"transaction": true,
"w...Add storage infos into `/node/summary`.
New `/node/sumary` response should be :
```json
{
"duniter": {
"software": "duniter",
"version": "1.8.7",
"forkWindowSize": 100,
"storage": {
"transaction": true,
"wotwizard": false
}
}
}
```1.8.7Benoit LavenierBenoit Lavenierhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1437GVA: bug with some membres or past members balances2023-03-21T00:23:50+01:00pokaGVA: bug with some membres or past members balancesThis is the related thread: https://forum.duniter.org/t/bug-balance-db-gva/9805
Some membre wallets or past members have a negative balance..
We can see it easily on this page, when order by balance (Solde Ğ1 column): https://g1-stats....This is the related thread: https://forum.duniter.org/t/bug-balance-db-gva/9805
Some membre wallets or past members have a negative balance..
We can see it easily on this page, when order by balance (Solde Ğ1 column): https://g1-stats.axiom-team.fr/data/search.htmlhttps://git.duniter.org/nodes/typescript/duniter/-/issues/1436[wiki] missing images in wiki on installation section2022-11-22T19:34:47+01:00Antonio Vanegas[wiki] missing images in wiki on installation section## Overview
Hi, I'm new, but I want try to contribute with Ğ1. Also I want improve my Rust skills or Android skills with this project, and of course try to expand this initiative. For now I found that the images on the server installati...## Overview
Hi, I'm new, but I want try to contribute with Ğ1. Also I want improve my Rust skills or Android skills with this project, and of course try to expand this initiative. For now I found that the images on the server installation guide are missing:
![screenshot20221122_192937](/uploads/b3423d57dfe5d417c6eb7b0247c45a79/screenshot20221122_192937.jpg)