PD-245 — Format de preuve multi-chain¶
Epic : BLOCKCHAIN (PD-187) Sprint : 8 Priorité : High Prérequis obligatoire avant : PD-58 (Tezos fallback) Amendment de : PD-39 (TSA RFC 3161)
1. Contexte et motivation¶
1.1 Incohérence identifiée (INC-1)¶
Le document de spécifications techniques (doc 42) définit la preuve individuelle comme :
Merkle path + merkleroot + txid + jeton TSA + signature
PD-39 implémente ce format. Cependant, en contexte multi-chain (Ethereum L2 comme blockchain primaire, Tezos comme fallback envisagé dans PD-58), le champ txid seul est ambigu :
- Un hash de transaction Ethereum L2 (
0x...) et un hash d'opération Tezos (o...en base58) ont des formats différents en Tezos — mais ce n'est pas garanti pour toutes les chaînes futures. - Un auditeur, un tribunal, ou un système de vérification automatisé ne doit pas dépendre d'une heuristique de format pour déterminer la blockchain cible.
- La blockchain utilisée doit être un champ explicite, normé et obligatoire.
1.2 Ce qui existe déjà¶
Doc 42 définit pour le stockage interne :
anchorageauditlog : merkleroot, txid, **chaîne**, signature
Le champ chaîne existe en base de données. Cette story l'étend au format de preuve livrable, qui est ce que reçoit l'utilisateur final, un auditeur ou un juge.
2. Objectif¶
Amender le format de preuve individuelle ProbatioVault pour y inclure un champ blockchain explicite et obligatoire. Mettre à jour la spécification PD-39 et le document d'architecture doc 42 en conséquence. Constituer le prérequis formel à l'implémentation de PD-58.
3. Périmètre¶
3.1 Inclus¶
- Définition formelle du champ
blockchaindans le format de preuve individuelle - Amendment du module TSA (PD-39) : ajout du champ dans la structure
InclusionProof - Amendment du module ancrage (PD-52) : exposition de
blockchain: 'ethereum_l2'dans la preuve produite - Mise à jour de doc 42 : modèle multi-chain avec Ethereum L2 primaire et Tezos fallback
- Tests de vérification de preuve : validation du champ
blockchain, rejet si absent - Rétrocompatibilité : preuves historiques sans champ →
ethereum_l2par défaut
3.2 Exclus¶
- Implémentation de PD-58 (Tezos fallback) — story distincte, dépendante de PD-245
- Migration des preuves historiques stockées
- Changement du protocole TSA RFC 3161
- Ajout d'autres blockchains non prévues
4. Spécification du format de preuve amendé¶
4.1 Format actuel (PD-39, section 10.4)¶
// RFC 9162 InclusionProofDataV2 — format actuel
interface InclusionProof {
log_id: string; // Identifiant batch
tree_size: number; // Taille arbre Merkle
leaf_index: number; // Position feuille
inclusion_path: string[]; // Chemin audit (hash siblings)
leaf_hash: string; // Hash feuille (SHA-256)
root_hash: string; // Merkle root (horodaté)
// TST RFC 3161 joint séparément
}
4.2 Format amendé (PD-245)¶
// RFC 9162 InclusionProofDataV2 — format amendé PD-245
type BlockchainIdentifier = 'ethereum_l2' | 'tezos';
interface InclusionProof {
log_id: string;
tree_size: number;
leaf_index: number;
inclusion_path: string[];
leaf_hash: string;
root_hash: string;
blockchain: BlockchainIdentifier; // NOUVEAU — obligatoire
// TST RFC 3161 joint séparément
}
4.3 Valeurs autorisées du champ blockchain¶
| Valeur | Blockchain | Statut |
|---|---|---|
ethereum_l2 | Ethereum L2 (primaire) | ✅ Actif — toutes les preuves actuelles |
tezos | Tezos (fallback) | 🔒 Réservé — disponible après implémentation PD-58 |
4.4 Règle de rétrocompatibilité¶
Les preuves émises avant PD-245 (sans champ blockchain) sont interprétées comme ethereum_l2 par convention. Le vérificateur applique cette règle silencieusement. Aucune migration de données n'est requise.
4.5 Gestion des cas limites¶
| Cas | Comportement | Justification |
|---|---|---|
blockchain absent | Rétrocompat → ethereum_l2 | Preuves historiques |
blockchain: null | Erreur INVALID_BLOCKCHAIN_IDENTIFIER | Champ présent mais invalide |
blockchain: "" | Erreur INVALID_BLOCKCHAIN_IDENTIFIER | String vide non autorisée |
blockchain: "ETHEREUM_L2" | Erreur INVALID_BLOCKCHAIN_IDENTIFIER | Case-sensitive, lowercase requis |
blockchain: 123 (number) | Erreur INVALID_BLOCKCHAIN_IDENTIFIER | Type non-string non autorisé |
blockchain: true (boolean) | Erreur INVALID_BLOCKCHAIN_IDENTIFIER | Type non-string non autorisé |
4.6 Mécanisme d'activation des blockchains¶
// src/modules/tsa/constants/blockchain.constants.ts
export type BlockchainIdentifier = 'ethereum_l2' | 'tezos';
/**
* Blockchains actuellement actives pour l'ancrage.
* IMPORTANT: tezos sera ajouté ici UNIQUEMENT après PD-58 DONE et validé.
* Cette liste est la source de vérité pour INV-245-05.
*/
export const ACTIVE_BLOCKCHAINS: readonly BlockchainIdentifier[] = [
'ethereum_l2',
// 'tezos' — décommenté après PD-58 DONE
] as const;
/**
* Vérifie si une blockchain est active pour l'ancrage.
*/
export function isBlockchainActive(blockchain: BlockchainIdentifier): boolean {
return ACTIVE_BLOCKCHAINS.includes(blockchain);
}
4.7 Diagrammes¶
4.7.1 Diagramme d'états — Cycle de vie d'une blockchain dans le système¶
Le champ blockchain suit un cycle d'activation gouverné par ACTIVE_BLOCKCHAINS (INV-245-05). Une blockchain passe par trois états : définie dans le type, activée en production, puis potentiellement désactivée.
stateDiagram-v2
[*] --> Definie : Ajout dans BlockchainIdentifier
Definie --> Active : Déploiement story (ex: PD-58)\nisBlockchainActive() = true
Active --> Definie : Retrait de ACTIVE_BLOCKCHAINS\nisBlockchainActive() = false
Active --> Active : Preuves émises avec ce blockchain id\n[INV-245-01, INV-245-04]
state Definie {
[*] --> Reconnue
Reconnue : Valeur acceptée par l'enum
Reconnue : Rejetée à l'ancrage (PROOF_002)
Reconnue : [INV-245-02, INV-245-05]
}
state Active {
[*] --> Production
Production : Ancrage autorisé
Production : Preuves émises [INV-245-01]
Production : Vérification acceptée [INV-245-02]
}
note right of Definie
État actuel de 'tezos' :
défini dans le type mais
non activé (PROOF_002)
end note
note right of Active
État actuel de 'ethereum_l2' :
seule blockchain active
end note 4.7.2 Diagramme de séquence — Émission et vérification d'une preuve multi-chain¶
Ce diagramme montre le flux nominal d'émission d'une preuve (à gauche) et le flux de vérification avec rétrocompatibilité (à droite), impliquant le module TSA (PD-39), le service d'ancrage (PD-52) et le vérificateur.
sequenceDiagram
autonumber
participant Client
participant TSA as TSA Module<br/>(PD-39)
participant Anchor as Anchor Service<br/>(PD-52 Ethereum L2)
participant Verifier as Proof Verifier
rect rgb(230, 245, 230)
note over Client, Anchor: Émission de preuve [INV-245-01, INV-245-04]
Client->>TSA: Demande preuve individuelle
TSA->>Anchor: Récupère ancrage (merkle root + txid)
Anchor-->>TSA: { merkleRoot, txid, blockchain: 'ethereum_l2' }
TSA->>TSA: Construit InclusionProof<br/>+ injecte blockchain [INV-245-01]
TSA-->>Client: InclusionProof { ..., blockchain: 'ethereum_l2' }
end
rect rgb(230, 235, 250)
note over Client, Verifier: Vérification — preuve post-PD-245 [INV-245-02]
Client->>Verifier: Vérifie preuve (blockchain: 'ethereum_l2')
Verifier->>Verifier: blockchain ∈ BlockchainIdentifier ? [INV-245-02]
Verifier->>Verifier: isBlockchainActive(blockchain) ? [INV-245-05]
Verifier-->>Client: ✓ Preuve valide
end
rect rgb(250, 245, 230)
note over Client, Verifier: Vérification — preuve historique (rétrocompat) [INV-245-03]
Client->>Verifier: Vérifie preuve (pas de champ blockchain)
Verifier->>Verifier: blockchain absent → 'ethereum_l2' [INV-245-03]
Verifier->>Verifier: isBlockchainActive('ethereum_l2') ? [INV-245-05]
Verifier-->>Client: ✓ Preuve valide (rétrocompat)
end
rect rgb(250, 230, 230)
note over Client, Verifier: Vérification — rejet [INV-245-06, INV-245-05]
Client->>Verifier: Vérifie preuve (blockchain: 'bitcoin')
Verifier->>Verifier: 'bitcoin' ∉ BlockchainIdentifier
Verifier-->>Client: ✗ PROOF_001 INVALID_BLOCKCHAIN_IDENTIFIER [INV-245-06]
Client->>Verifier: Vérifie preuve (blockchain: 'tezos')
Verifier->>Verifier: 'tezos' ∈ BlockchainIdentifier ✓
Verifier->>Verifier: isBlockchainActive('tezos') = false
Verifier-->>Client: ✗ PROOF_002 BLOCKCHAIN_NOT_ACTIVE [INV-245-05]
end 5. Codes d'erreur¶
| Code | Constante | HTTP | Description |
|---|---|---|---|
PROOF_001 | INVALID_BLOCKCHAIN_IDENTIFIER | 400 | Valeur blockchain non reconnue ou invalide |
PROOF_002 | BLOCKCHAIN_NOT_ACTIVE | 400 | Blockchain reconnue mais pas encore activée (ex: tezos avant PD-58) |
5.1 Format de réponse d'erreur¶
{
"statusCode": 400,
"error": "Bad Request",
"message": "Invalid blockchain identifier: bitcoin",
"code": "PROOF_001",
"details": {
"field": "blockchain",
"value": "bitcoin",
"allowed": ["ethereum_l2", "tezos"]
}
}
6. Invariants¶
| ID | Règle |
|---|---|
| INV-245-01 | Toute preuve individuelle émise après PD-245 DOIT contenir un champ blockchain non nul |
| INV-245-02 | La valeur blockchain DOIT appartenir à l'enum BlockchainIdentifier (ethereum_l2 ou tezos) |
| INV-245-03 | Le vérificateur DOIT traiter l'absence de champ blockchain comme ethereum_l2 (rétrocompat) |
| INV-245-04 | Le module TSA (PD-39) DOIT inclure blockchain dans tout token de preuve produit post-PD-245 |
| INV-245-05 | La valeur tezos NE PEUT être utilisée que si isBlockchainActive('tezos') retourne true (cf. section 4.6) |
| INV-245-06 | Les valeurs null, "", casse incorrecte, ou types non-string DOIVENT être rejetées avec erreur PROOF_001 |
7. Critères d'acceptation¶
| ID | Critère | Testable | INV couvert |
|---|---|---|---|
| CA-245-01 | Une preuve émise par le module TSA contient le champ blockchain: 'ethereum_l2' | Oui (unit) | INV-245-01, INV-245-04 |
| CA-245-02 | Le vérificateur accepte une preuve avec blockchain: 'ethereum_l2' | Oui (unit) | INV-245-02 |
| CA-245-03 | Le vérificateur rejette une preuve avec blockchain: 'bitcoin' (code PROOF_001) | Oui (unit) | INV-245-02, INV-245-06 |
| CA-245-04 | Le vérificateur accepte une preuve sans champ blockchain (rétrocompat → ethereum_l2) | Oui (unit) | INV-245-03 |
| CA-245-05 | Le vérificateur rejette blockchain: 'tezos' tant que isBlockchainActive('tezos') = false (code PROOF_002) | Oui (unit) | INV-245-05 |
| CA-245-06 | Le vérificateur rejette blockchain: null avec code PROOF_001 | Oui (unit) | INV-245-06 |
| CA-245-07 | Le vérificateur rejette blockchain: "" avec code PROOF_001 | Oui (unit) | INV-245-06 |
| CA-245-08 | L'interface InclusionProof expose le champ blockchain obligatoire | Oui (type check) | INV-245-01 |
| CA-245-09 | Le vérificateur accepte blockchain: 'tezos' si isBlockchainActive('tezos') = true | Oui (unit) | INV-245-05 |
8. Matrice de traçabilité¶
| INV | CA | Scénario de test |
|---|---|---|
| INV-245-01 | CA-245-01, CA-245-08 | Scénario 1 |
| INV-245-02 | CA-245-02, CA-245-03 | Scénario 1, Scénario 3 |
| INV-245-03 | CA-245-04 | Scénario 2 |
| INV-245-04 | CA-245-01 | Scénario 1 |
| INV-245-05 | CA-245-05, CA-245-09 | Scénario 4 |
| INV-245-06 | CA-245-03, CA-245-06, CA-245-07 | Scénario 3, 5, 6, 7 |
9. Scénarios de test¶
Scénario 1 — Preuve Ethereum L2 valide (CA-245-01, CA-245-02)¶
Given un document ancré sur Ethereum L2 When la preuve individuelle est générée Then le champ blockchain: 'ethereum_l2' est présent et la preuve est acceptée
Scénario 2 — Preuve sans champ blockchain (CA-245-04)¶
Given une preuve historique sans champ blockchain When la vérification est exécutée Then la convention ethereum_l2 est appliquée et la preuve est acceptée
Scénario 3 — Valeur blockchain invalide (CA-245-03)¶
Given une preuve avec blockchain: 'bitcoin' When la vérification est exécutée Then la preuve est rejetée avec erreur PROOF_001 (INVALID_BLOCKCHAIN_IDENTIFIER)
Scénario 4 — Valeur tezos avant activation (CA-245-05)¶
Given isBlockchainActive('tezos') retourne false And une preuve avec blockchain: 'tezos' When la vérification est exécutée Then la preuve est rejetée avec erreur PROOF_002 (BLOCKCHAIN_NOT_ACTIVE)
Scénario 5 — Valeur null (CA-245-06)¶
Given une preuve avec blockchain: null When la vérification est exécutée Then la preuve est rejetée avec erreur PROOF_001 (INVALID_BLOCKCHAIN_IDENTIFIER)
Scénario 6 — Valeur vide (CA-245-07)¶
Given une preuve avec blockchain: "" When la vérification est exécutée Then la preuve est rejetée avec erreur PROOF_001 (INVALID_BLOCKCHAIN_IDENTIFIER)
Scénario 7 — Casse incorrecte (CA-245-03)¶
Given une preuve avec blockchain: "ETHEREUM_L2" (majuscules) When la vérification est exécutée Then la preuve est rejetée avec erreur PROOF_001 (case-sensitive)
10. Fichiers impactés¶
| Fichier | Type de modification |
|---|---|
src/modules/tsa/interfaces/inclusion-proof.interface.ts | Ajout champ blockchain: BlockchainIdentifier |
src/modules/tsa/services/proof.service.ts | Injection blockchain: 'ethereum_l2' à la création |
src/modules/tsa/services/proof-verifier.service.ts | Validation champ + rétrocompat + codes erreur |
src/modules/tsa/constants/blockchain.constants.ts | Enum BlockchainIdentifier + ACTIVE_BLOCKCHAINS (nouveau) |
src/modules/tsa/errors/proof.errors.ts | Constantes PROOF_001, PROOF_002 (nouveau) |
src/modules/blockchain/ethereum/anchor.service.ts | Exposer blockchain: 'ethereum_l2' |
11. Dépendances¶
| Story | Direction | Nature |
|---|---|---|
| PD-39 | ← backward | Module TSA à amender — DONE, amendment requis |
| PD-52 | ← backward | Ancrage Ethereum L2 — doit exposer blockchain: 'ethereum_l2' |
| PD-58 | → forward | Tezos fallback — bloqué jusqu'à PD-245 DONE |
12. Références¶
- PD-39 — Intégration TSA RFC 3161 (section 13, GAP-39-01)
- PD-52 — Ethereum L2 Setup
- Doc 42 — Spécifications Techniques v2.1 (sections "Preuve individuelle" et "Ancrage blockchain")
13. Clarifications contractuelles¶
| Question | Réponse | Justification |
|---|---|---|
| Comment savoir si tezos est activé ? | Vérifier ACTIVE_BLOCKCHAINS.includes('tezos') | Source de vérité unique (cf. section 4.6) |
| Qui active tezos ? | Déploiement PD-58 modifie blockchain.constants.ts | Pas de runtime toggle, déploiement requis |
| Preuves existantes migrées ? | Non, rétrocompat transparente | Absence de champ = ethereum_l2 |
| Casse sensible ? | Oui, lowercase uniquement | Cohérence avec standards blockchain |
Fin de la spécification PD-245.