PD-52 - Setup connexion Ethereum L2 (Polygon/Arbitrum)¶
1. Objectif¶
Definir le contrat fonctionnel, securite et operabilite de la capacite de connexion Ethereum L2 pour ProbatioVault afin de:
- etablir une connectivite fiable vers Polygon et Arbitrum,
- permettre la signature et l'emission de transactions de testnet via une cle de custody conforme,
- garantir la resilence provider (failover),
- exposer des observables de sante et de couts (latence RPC, gas, solde),
- preparer la base technique des stories PD-53, PD-55, PD-56 et PD-57.
Elements non directement testables et donc hors perimetre contractuel:
- perception utilisateur de la "confiance" induite par la blockchain,
- interpretation juridique definitive de la valeur probatoire selon juridiction.
2. Perimetre / Hors perimetre¶
Inclus¶
- Connectivite RPC vers Polygon et Arbitrum en environnement test.
- Verification de connectivite par appels blockchain standards.
- Gestion d'un wallet de service avec signature Ethereum verifiable.
- Prise en charge contractuelle des 3 scenarios de compatibilite secp256k1 (S1, S2, S3).
- Estimation de gas pour une transaction type d'ancrage.
- Emission et confirmation de transaction de test sur testnets cibles.
- Mecanisme de failover entre provider RPC primaire et secondaire.
- Exposition d'indicateurs minimaux: latence RPC, gas price, solde wallet, statut provider actif.
Exclu¶
- Deploiement et gestion de smart contract (PD-53).
- Worker d'ancrage periodique et orchestration de lots (PD-55).
- Generation de preuve Merkle individuelle (PD-56).
- Verification composite TSA + blockchain (PD-57).
- Fallback Tezos (PD-58).
- Transactions mainnet en dehors d'une campagne d'acceptation explicitement autorisee.
- Gestion de concurrence multi-instance sur le wallet (architecture multi-worker releve de PD-55).
3. Definitions¶
- L2: reseau de couche 2 compatible EVM.
- RPC Provider: endpoint d'acces JSON-RPC a un reseau blockchain.
- Failover RPC: bascule automatique du provider primaire vers un secondaire.
- Wallet de service: identite blockchain utilitaire de ProbatioVault pour signatures et transactions.
- Custody mode: mode de gestion de cle Ethereum parmi S1/S2/S3.
- S1: cle secp256k1 signee directement par CloudHSM via PKCS#11.
- S2: cle secp256k1 signee via AWS KMS (
ECC_SECG_P256K1) ou Vault Transit. - S3: approche hybride avec materiel derive depuis HSM et secret secp256k1 stocke chiffre dans Vault. La preuve de chiffrement au repos est verifiable via l'API Vault
sys/seal-status(sealed=false implique encryption at rest active) et les audit logs Vault. - Transaction type d'ancrage: transaction
eth_sendTransactionvers l'adresse du sender (self-send) avecvalue=0etdata=keccak256("ProbatioVault:anchor:test:" || timestamp_unix). Ce payload minimal est representatif de l'ecriture d'un engagement sans smart contract. - Confirmation: transaction incluse en bloc et observee avec le nombre de confirmations requis.
- Finalite operationnelle: etat "valide" interne atteint apres seuil de confirmations contractuel.
- Seuil de confirmations: nombre de blocs apres inclusion necessaires pour declarer la finalite. Valeurs par defaut: Polygon testnet (Amoy) = 5 confirmations (~10 secondes), Arbitrum testnet (Sepolia) = 1 confirmation (soft-finality suffisante sur L2 optimistic).
- Timeout de detection RPC: duree maximale d'attente de reponse d'un provider avant de le considerer en echec. Valeur par defaut: 2 secondes.
- Retries avant failover: nombre de tentatives sur le provider primaire avant bascule. Valeur par defaut: 1 retry (soit 2 tentatives totales).
- Format de signature Ethereum: toutes les signatures produites par le wallet de service DOIVENT etre conformes a EIP-191 (personal_sign avec prefixe
\x19Ethereum Signed Message:\n).
4. Invariants (non negociables)¶
| ID | Regle | Justification |
|---|---|---|
| INV-52-01 | Les reseaux cibles obligatoires de PD-52 sont Polygon et Arbitrum. | Alignement epic PD-187. |
| INV-52-02 | Toute operation blockchain de PD-52 est executee sur testnet uniquement (chain IDs: Polygon Amoy=80002, Arbitrum Sepolia=421614). | Maitrise du risque financier et operationnel. |
| INV-52-03 | La cle privee ne doit jamais etre presente en clair dans code, variables d'environnement, logs, traces applicatives ou historique git. | Exigence securite critique. |
| INV-52-04 | Un et un seul custody mode (S1, S2 ou S3) doit etre selectionne explicitement avant emission de transaction. Si plusieurs modes sont configures simultanement, le systeme refuse de demarrer avec erreur CUSTODY_MODE_AMBIGUOUS. | Eliminer l'ambiguite face au risque secp256k1. |
| INV-52-05 | Si le custody mode selectionne est indisponible, l'emission de transaction est refusee avec erreur explicite. | Eviter signatures degradantes/non conformes. |
| INV-52-06 | Le mecanisme RPC doit supporter un provider primaire et au moins un provider secondaire par reseau. | Continuite de service. |
| INV-52-07 | En cas d'indisponibilite provider primaire, la bascule vers secondaire doit etre automatique et transparente pour l'appelant applicatif. Le temps total de bascule (detection + retry + switch) ne doit pas depasser 5 secondes. | Robustesse contractuelle. |
| INV-52-08 | Les donnees emises on-chain dans PD-52 sont limitees a des hash et metadonnees techniques non identifiantes. Le systeme DOIT rejeter toute tentative d'emission de payload contenant des donnees non conformes (validation entrante obligatoire). | Confidentialite et conformite. |
| INV-52-09 | Une transaction n'est pas consideree finalisee tant que le seuil de confirmations n'est pas atteint (Polygon=5, Arbitrum=1). | Protection contre reorg. |
| INV-52-10 | Les metriques de sante minimales (latence RPC, gas price, solde wallet, provider actif) doivent etre exposables a la demande via un endpoint HTTP /health/blockchain retournant un objet JSON. | Exploitabilite operationnelle. |
| INV-52-11 | Toute erreur d'appel RPC ou de signature doit produire un code d'erreur deterministic et journalisable sans fuite de secret. | Diagnostic fiable et securise. |
| INV-52-12 | Les tests contractuels de PD-52 doivent etre executes en CI avant acceptation. | Learning PD-7, refus automatique sinon. |
| INV-52-13 | Le seuil de confirmations par reseau est configurable par variable d'environnement, avec les valeurs par defaut specifiees en §3. | Adaptabilite operationnelle. |
5. Flux nominaux¶
FN-52-01 - Verification de connectivite multi-reseaux¶
- Le systeme cible Polygon testnet puis Arbitrum testnet.
- Pour chaque reseau, il execute 10 appels consecutifs
eth_blockNumber. - Chaque appel retourne un numero de bloc valide.
Resultat attendu: succes de 10/10 appels sur chaque reseau.
FN-52-02 - Selection et validation du custody mode¶
- Le systeme lit le mode de custody configure (S1, S2 ou S3).
- Si plusieurs modes sont configures, il refuse de demarrer avec
CUSTODY_MODE_AMBIGUOUS. - Il execute un test de capacite de signature secp256k1 pour ce mode.
- Il publie l'etat "mode valide" ou "mode invalide".
Resultat attendu: un mode unique valide est declare avant tout envoi de transaction.
FN-52-03 - Signature de reference du wallet¶
- Le systeme soumet un message canonique de test au wallet de service.
- Le wallet retourne une signature Ethereum conforme EIP-191.
- La signature est verifiee comme correspondante a l'adresse attendue via
ecrecover.
Resultat attendu: signature verifiable sans acces au secret prive.
FN-52-04 - Estimation de gas transaction type¶
- Le systeme construit une transaction type d'ancrage (self-send avec hash en data).
- Il calcule une estimation de gas via
eth_estimateGas. - Il conserve l'estimation pour comparaison avec le gas reel apres execution.
Resultat attendu: estimation disponible et comparables aux mesures reelles.
FN-52-05 - Emission et confirmation transaction testnet¶
- Le systeme emet une transaction de test sur un reseau cible.
- Il suit le hash de transaction jusqu'a inclusion.
- Il attend le seuil de confirmations contractuel (Polygon=5, Arbitrum=1).
- Il marque la transaction finalisee.
Resultat attendu: transaction confirmee dans le delai contractuel.
FN-52-06 - Failover provider¶
- Le provider primaire devient indisponible pendant un appel.
- Le systeme detecte l'echec apres timeout (2s) + 1 retry.
- Il bascule sur le secondaire.
- L'appel applicatif est servi par le provider secondaire.
Resultat attendu: bascule en moins de 5 secondes sans intervention manuelle.
FN-52-07 - Exposition des observables operationnels¶
- Un appel HTTP GET
/health/blockchainest execute. - Le systeme retourne un objet JSON avec les metriques minimales contractuelles.
- Les metriques sont horodatees et coherentes avec l'etat runtime.
Resultat attendu: metriques exploitables pour supervision et alerting.
5bis. Diagrammes¶
SD-52-01 - Etats d'une transaction blockchain¶
Cycle de vie d'une transaction depuis son emission jusqu'a sa finalite ou son abandon. Ref: INV-52-09 (seuil de confirmations), ERR-52-08 (reorg), INV-52-02 (testnet only).
stateDiagram-v2
[*] --> PENDING : emit tx (FN-52-05)
PENDING --> INCLUDED : tx incluse en bloc
INCLUDED --> CONFIRMED : confirmations < seuil
CONFIRMED --> FINALIZED : seuil atteint\n(Polygon=5, Arbitrum=1)\n[INV-52-09]
FINALIZED --> [*]
INCLUDED --> REORG : reorg detectee\n[ERR-52-08]
CONFIRMED --> REORG : reorg detectee\n[ERR-52-08]
REORG --> INCLUDED : tx reapparait\nen nouveau bloc
REORG --> ABANDONED : tx absente\napres 60s timeout\n[ERR-52-08]
ABANDONED --> [*]
PENDING --> REJECTED : gas ceiling\n[ERR-52-07]\nou payload invalide\n[ERR-52-14]\nou mainnet\n[ERR-52-13]
REJECTED --> [*] SD-52-02 - Etats du provider RPC (failover)¶
Bascule automatique entre provider primaire et secondaire. Ref: INV-52-06, INV-52-07 (bascule < 5s), ERR-52-01, ERR-52-02.
stateDiagram-v2
[*] --> PRIMARY_ACTIVE : demarrage
PRIMARY_ACTIVE --> PRIMARY_FAILED : timeout 2s\n+ 1 retry echoue\n[INV-52-07]
PRIMARY_FAILED --> SECONDARY_ACTIVE : bascule auto\n< 5s total\n[ERR-52-01]
SECONDARY_ACTIVE --> PRIMARY_ACTIVE : health check\nprimaire retabli
SECONDARY_ACTIVE --> ALL_UNAVAILABLE : secondaire\negalement en echec\n[ERR-52-02]
ALL_UNAVAILABLE --> PRIMARY_ACTIVE : provider retabli SQ-52-01 - Emission et confirmation de transaction (FN-52-05)¶
Flux multi-service couvrant la signature, l'emission et le suivi de confirmation. Ref: INV-52-03 (pas de secret en clair), INV-52-04 (custody mode unique), INV-52-09 (seuil confirmations).
sequenceDiagram
participant App as Appelant applicatif
participant BC as BlockchainService
participant Custody as CustodyProvider<br/>(S1/S2/S3)
participant RPC as RPC Provider<br/>(primaire/secondaire)
App->>BC: emitAnchorTx(hash)
BC->>BC: validatePayload(hash) [INV-52-08]
BC->>BC: checkChainId == testnet [INV-52-02]
BC->>Custody: signTransaction(txData) [INV-52-04]
Custody-->>BC: signedTx (secret jamais expose [INV-52-03])
BC->>RPC: eth_sendRawTransaction(signedTx)
RPC-->>BC: txHash
BC-->>App: txHash + status=PENDING
loop Suivi confirmations
BC->>RPC: eth_getTransactionReceipt(txHash)
RPC-->>BC: receipt (blockNumber, confirmations)
end
alt Seuil atteint [INV-52-09]
BC-->>App: status=FINALIZED
else Reorg detectee [ERR-52-08]
BC-->>App: status=REORG
end SQ-52-02 - Failover RPC (FN-52-06)¶
Bascule transparente vers le provider secondaire en cas d'indisponibilite. Ref: INV-52-06, INV-52-07 (< 5s), ERR-52-01.
sequenceDiagram
participant App as Appelant applicatif
participant BC as BlockchainService
participant P1 as Provider primaire
participant P2 as Provider secondaire
App->>BC: appel RPC
BC->>P1: requete JSON-RPC
P1--xBC: timeout 2s [INV-52-07]
BC->>P1: retry (1 tentative)
P1--xBC: echec [ERR-52-01]
BC->>P2: bascule auto + requete JSON-RPC
P2-->>BC: reponse OK
BC-->>App: reponse (< 5s total) [INV-52-07] SQ-52-03 - Selection et validation du custody mode (FN-52-02)¶
Validation au demarrage que le mode de custody est unique et operationnel. Ref: INV-52-04 (mode unique), INV-52-05 (mode indisponible), ERR-52-03/10/11.
sequenceDiagram
participant Srv as Service (startup)
participant Cfg as Configuration
participant HSM as CloudHSM (S1)
participant KMS as AWS KMS / Vault (S2)
participant VLT as Vault Transit (S3)
Srv->>Cfg: lire custody_mode
alt Aucun mode configure
Cfg-->>Srv: CUSTODY_MODE_MISSING [ERR-52-03]
Srv->>Srv: ABORT demarrage
else Plusieurs modes configures
Cfg-->>Srv: CUSTODY_MODE_AMBIGUOUS [ERR-52-10]
Srv->>Srv: ABORT demarrage [INV-52-04]
else Mode inconnu
Cfg-->>Srv: CUSTODY_MODE_UNKNOWN [ERR-52-11]
Srv->>Srv: ABORT demarrage
else Mode S1
Srv->>HSM: test signature secp256k1
HSM-->>Srv: signature OK / KO [INV-52-05]
else Mode S2
Srv->>KMS: test signature secp256k1
KMS-->>Srv: signature OK / KO [INV-52-05]
else Mode S3
Srv->>VLT: test signature + seal-status
VLT-->>Srv: signature OK + sealed=false [INV-52-05]
end 6. Cas d'erreur¶
| ID | Cas d'erreur | Code erreur | Reponse attendue |
|---|---|---|---|
| ERR-52-01 | Echec RPC sur provider primaire | RPC_PRIMARY_FAILED | Bascule automatique vers secondaire, erreur non bloquante si secondaire disponible. |
| ERR-52-02 | Echec RPC sur tous les providers d'un reseau | RPC_UNAVAILABLE | Retour d'erreur bloquante explicite, appel marque en echec. |
| ERR-52-03 | Custody mode non defini | CUSTODY_MODE_MISSING | Aucune signature tentee, demarrage refuse. |
| ERR-52-04 | Custody mode defini mais capacite secp256k1 invalide | CUSTODY_MODE_INVALID | Emission transaction interdite. |
| ERR-52-05 | Signature non verifiable pour l'adresse configuree | SIGNATURE_VERIFICATION_FAILED | Mode marque non conforme. |
| ERR-52-06 | Solde wallet insuffisant pour gas estime | INSUFFICIENT_FUNDS | Transaction non emise. |
| ERR-52-07 | Depassement du plafond gas configurable | GAS_PRICE_CEILING_EXCEEDED | Transaction rejetee (politique stricte). Pas de mise en queue — l'appelant doit reessayer ulterieurement. |
| ERR-52-08 | Transaction incluse puis reorg avant finalite | TRANSACTION_REORG | Etat transaction repasse a non finalisee, suivi continue jusqu'a nouvelle finalite. Si la transaction ne reapparait pas dans un nouveau bloc apres 60 secondes, elle est marquee TRANSACTION_ABANDONED. |
| ERR-52-09 | Fuite potentielle de secret detectee dans logs de test | SECRET_LEAK_DETECTED | Echec immediate de la campagne d'acceptation, non-conformite securite. |
| ERR-52-10 | Plusieurs custody modes configures simultanement | CUSTODY_MODE_AMBIGUOUS | Refus de demarrage du service. |
| ERR-52-11 | Custody mode inconnu (ni S1, ni S2, ni S3) | CUSTODY_MODE_UNKNOWN | Refus de demarrage du service. |
| ERR-52-12 | Endpoint RPC mal configure (URL invalide) | RPC_INVALID_ENDPOINT | Refus de demarrage du service. |
| ERR-52-13 | Tentative d'emission sur mainnet | MAINNET_FORBIDDEN | Transaction bloquee, alerte securite emise. |
| ERR-52-14 | Payload de transaction non conforme (donnees non-hash) | PAYLOAD_VALIDATION_FAILED | Transaction rejetee avant emission. |
7. Criteres d'acceptation (testables)¶
| ID | Critere | Observable |
|---|---|---|
| CA-52-01 | Connectivite Polygon testnet validee. | 10 appels consecutifs eth_blockNumber reussis sur Polygon. |
| CA-52-02 | Connectivite Arbitrum testnet validee. | 10 appels consecutifs eth_blockNumber reussis sur Arbitrum. |
| CA-52-03 | Un custody mode unique S1/S2/S3 est explicitement selectionne et valide. | Journal de selection unique + resultat test de capacite secp256k1 positif. |
| CA-52-04 | Signature wallet de reference verifiable. | Signature EIP-191 recuperee et verification reussie contre l'adresse attendue via ecrecover. |
| CA-52-05 | Estimation gas exploitable. | Ecart relatif entre gas estime et gas consomme < 25% sur transaction type. |
| CA-52-06 | Transaction testnet confirmee dans le delai cible. | Temps emission -> confirmation <= 30 secondes sur environnement de test de reference. |
| CA-52-07 | Failover RPC respecte le SLA de bascule. | Bascule primaire->secondaire observee en < 5 secondes (timeout 2s + 1 retry + switch), appel applicatif servi. |
| CA-52-08 | Metriques minimales exposees. | Presence de latence RPC, gas price, solde wallet et provider actif sur endpoint JSON /health/blockchain. |
| CA-52-09 | Absence de secret prive en clair. | Audit logs/config/code/historique git sans cle privee brute ni materiel secret exploitable. |
| CA-52-10 | Donnees on-chain limitees a hash/non-identifiant. | Inspection des payloads transaction: aucun champ contenant donnees personnelles ou metadonnees identifiantes. |
| CA-52-11 | Gestion reorg conforme a la finalite. | Cas de test reorg: transaction non finalisee tant que seuil confirmations non atteint (Polygon=5, Arbitrum=1). |
| CA-52-12 | Campagne de tests contractuels executee en CI. | Pipeline CI vert incluant tests unitaires + integration; couverture unitaire >= 80%. |
| CA-52-13 | Validation de payload entrante operationnelle. | Tentative d'emission de donnees non conformes rejetee avec PAYLOAD_VALIDATION_FAILED. |
8. Scenarios de test (Given / When / Then)¶
TC-52-01 - Connectivite Polygon (CA-52-01, INV-52-01)¶
Given un endpoint RPC Polygon testnet valide When 10 appels consecutifs eth_blockNumber sont executes Then les 10 appels retournent un numero de bloc valide.
TC-52-02 - Connectivite Arbitrum (CA-52-02, INV-52-01)¶
Given un endpoint RPC Arbitrum testnet valide When 10 appels consecutifs eth_blockNumber sont executes Then les 10 appels retournent un numero de bloc valide.
TC-52-03 - Validation scenario S1 (CA-52-03, INV-52-04)¶
Given le mode S1 configure When un test de signature secp256k1 est lance via CloudHSM/PKCS#11 Then le mode est marque valide uniquement si la signature est verifiable.
TC-52-04 - Validation scenario S2 (CA-52-03, INV-52-04)¶
Given le mode S2 configure When un test de signature secp256k1 est lance via KMS ou Vault Transit Then le mode est marque valide uniquement si la signature est verifiable.
TC-52-05 - Validation scenario S3 (CA-52-03, INV-52-04)¶
Given le mode S3 configure When un test de signature secp256k1 est lance sur le materiel chiffre derive Then le mode est marque valide uniquement si la signature est verifiable et le secret reste chiffre au repos (verifiable via Vault sys/seal-status).
TC-52-06 - Signature wallet verifiable (CA-52-04, INV-52-03)¶
Given un message canonique de test et une adresse wallet attendue When le wallet signe le message en format EIP-191 Then la verification cryptographique via ecrecover retrouve l'adresse attendue.
TC-52-07 - Estimation gas (CA-52-05)¶
Given une transaction type d'ancrage (self-send avec hash) When le systeme estime le gas puis execute la transaction Then l'ecart relatif entre estimation et gas reel est inferieur a 25%.
TC-52-08 - Confirmation transaction (CA-52-06, INV-52-09)¶
Given une transaction test emise sur testnet When le suivi de transaction est actif Then la transaction est confirmee en <= 30 secondes et finalisee apres seuil de confirmations (Polygon=5, Arbitrum=1).
TC-52-09 - Failover automatique (CA-52-07, INV-52-07)¶
Given un provider primaire indisponible et un secondaire operationnel When un appel RPC est execute Then la bascule vers secondaire est realisee en moins de 5 secondes (timeout 2s + 1 retry + switch).
TC-52-10 - Observabilite minimale (CA-52-08, INV-52-10)¶
Given le service en execution When l'endpoint /health/blockchain est consulte Then latence RPC, gas price, solde wallet et provider actif sont presents et horodates en JSON.
TC-52-11 - Confidentialite secrets (CA-52-09, INV-52-03)¶
Given une campagne de tests complete When les logs, traces, configurations et historique git sont audites Then aucun secret prive en clair n'est detectable.
TC-52-12 - Donnees on-chain minimales (CA-52-10, INV-52-08)¶
Given une transaction type observee When son payload est inspecte Then seuls des hash et metadonnees techniques non identifiantes sont presents.
9. Hypotheses explicites¶
| ID | Hypothese | Impact si faux |
|---|---|---|
| H-52-01 | Les endpoints RPC testnet Polygon et Arbitrum sont disponibles pendant les campagnes de test. | Impossibilite de demontrer CA-52-01/02 de maniere fiable. |
| H-52-02 | Un mecanisme d'obtention de fonds testnet est operationnel pour le wallet de service. | CA-52-06 et CA-52-07 deviennent non executables. |
| H-52-03 | Le mode de custody choisi dispose des droits IAM/Vault/HSM necessaires en environnement de test. | Echec de signature, blocage sur CA-52-03/04. |
| H-52-04 | Le seuil de confirmations est definissable par configuration deploiement. | CA-52-11 ne peut pas etre valide de facon uniforme. |
| H-52-05 | La CI dispose d'un environnement d'integration testnet stable et rejouable. | CA-52-12 peut etre partiellement non demonstrable. |
| H-52-06 | Les outils d'audit de logs sont capables de detecter les motifs de fuite de secret attendus. | CA-52-09 risque de faux negatif. |
| H-52-07 | Le custody mode initial pour l'acceptation v1 est S2 (AWS KMS). | Simplification de l'integration ; S1 (HSM) reserve pour production. |
10. Points resolus¶
Les points suivants ont ete clarifies dans cette version de la specification :
- Seuil de confirmations : Polygon=5, Arbitrum=1 (defini en §3 et INV-52-09).
- Transaction type d'ancrage : self-send avec
data=keccak256("ProbatioVault:anchor:test:" || timestamp)(defini en §3). - Politique GAS_PRICE_CEILING_EXCEEDED : rejet strict, pas de mise en queue (defini en ERR-52-07).
- Custody mode initial : S2 (AWS KMS) recommande pour v1 (defini en H-52-07).
- Preuve S3 chiffre au repos : via Vault
sys/seal-statuset audit logs (defini en §3). - Endpoint observabilite :
/health/blockchainretournant JSON (defini en INV-52-10). - Seuil solde critique : 0.01 ETH equivalent (a definir en configuration, hors scope spec).
- Independance verification : utilisation de Vault externe + audit logs (conforme PD-37).
- Timeout de detection : 2 secondes, 1 retry avant failover (defini en §3 et FN-52-06).
- Format de signature : EIP-191 obligatoire (defini en §3 et FN-52-03).
- Catalogue codes d'erreur : 14 codes definis en §6.
- Validation payload entrante : obligatoire via INV-52-08 et ERR-52-14.
References¶
- Epic : PD-187 - BLOCKCHAIN
- JIRA : PD-52
- Repos concernes : ProbatioVault-backend, ProbatioVault-infra
- Documents associes : PD-52-besoin.md, learnings PD-36/PD-7/PD-37
- Correction Gate 3 v1 : 2026-02-12 (resolution de 12 ecarts)