Aller au contenu

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 blockchain dans 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_l2 par 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


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.