Quel genesis une nouvelle version du client doit-il incorporer?

Pour synchroniser Duniter sur un réseau donné, il faut avoir le même genesis. Il y a plusieurs manière d’y arriver :

  • avoir le genesis intégré au binaire
  • remplacer le genesis en utilisant un fichier hors du binaire (raw specs par exemple)

Le genesis est l’état au bloc zéro, et le runtime est un élément de l’état. Donc si tu as pu te synchroniser sur la GDev avec un runtime intégré au binaire différent de celui du genesis, c’est probablement parce que tu avais des données restantes d’une synchronisation précédente. Il faut supprimer les données et recommencer la synchro, et elle devrait échouer. Sinon, je ne vois pas comme ça a pu arriver.

Pour répondre à la question du titre :

Il y aura un intérêt à intégrer le genesis de la g1 puisque le but sera de ne jamais la redémarrer, mais on ne peut pas promettre de stabilité pour la gdev donc mieux vaut obtenir son genesis à part, quitte à le rendre disponible à une URL fixe genre duniter.org/latest-gdev.json. Pour la gtest je ne sais pas.

1 Like

Effectivement, on peut tolérer dans un premier temps d’imposer aux forgerons d’avoir les raw chainspecs à côté de leur binaire Duniter. L’intérêt de les inclure dans le binaire est de simplifier encore plus l’installation d’un noeud, et ça peut être fait quelques semaines après le démarrage, quand on a une liste de bootnodes en voie de stabilisation.

Pour mémoire :

/// A configuration of a chain. Can be used to build a genesis block.
pub struct ChainSpec<G, E = NoExtension> {
	client_spec: ClientSpec<E>,
	genesis: GenesisSource<G>,
}
/// A configuration of a client. Does not include runtime storage initialization.
struct ClientSpec<E> {
	name: String,
	id: String,
	chain_type: ChainType,
	boot_nodes: Vec<MultiaddrWithPeerId>,
	telemetry_endpoints: Option<TelemetryEndpoints>,
	protocol_id: Option<String>,
	/// Arbitrary string. Nodes will only synchronize with other nodes that have the same value
	/// in their `fork_id`. This can be used in order to segregate nodes in cases when multiple
	/// chains have the same genesis hash.
	fork_id: Option<String>,
	properties: Option<Properties>,
	extensions: E,
	/// Mapping from `block_number` to `wasm_code`.
	///
	/// The given `wasm_code` will be used to substitute the on-chain wasm code starting with the
	/// given block number until the `spec_version` on chain changes.
	code_substitutes: BTreeMap<String, Bytes>,
}
enum GenesisSource<G> {
	File(PathBuf),
	Binary(Cow<'static, [u8]>),
	Factory(Arc<dyn Fn() -> G + Send + Sync>),
	Storage(Storage),
}

Vous me mettez le doute, je vous en laisse le bénéfice :slight_smile:

Mais je ne vois pas vraiment pourquoi il serait nécessaire d’avoir la Chain Spec pour se synchroniser sur une chaîne, il suffit de la Client Spec où figurent les adresses des nœuds sur lesquels se synchroniser. C’est d’ailleurs comme ça que fait Duniter v1, et la présence d’un Runtime n’y change rien.

edit : ah bah si, ça y est ! le block#0 ne contient pas le Genesis, donc il faut forcément le fournir. OK.

Théoriquement ce n’est pas nécessaire puisqu’on pourrait obtenir le genesis via l’un des noeuds auxquels on se connecte, mais il y a une sécurité dans substrate qui vérifie que l’on se connecte bien au réseau attendu → substrate ne prévoit pas de transférer le genesis, juste de comparer le hash.
Un des avantages est que l’on risque moins de se trouver avec une version du client incompatible avec le runtime.

Oui mais je suppose que ça ne fait pas partie du protocole de synchro, et qu’il n’y a peut-être même pas d’API pour le faire ?

On devrait pouvoir créer un call RPC qui donne le genesis, et une commande qui prend en paramètre le hash du genesis et appelle le call RPC et vérifie le hash.

1 Like