Traduzione italiana di " Engineering dive into Cardano’s Dynamic P2P design"
Traduzione italiana a cura di Lordwotton di RIOT Stake Pools. Se apprezzi queste traduzioni, per favore valuta di supportare il mio lavoro delegando i tuoi ada a RIOT entra nel nostro gruppo Telegram
Scoprite il viaggio attraverso le sfide, le soluzioni e i trionfi che hanno portato alla creazione di un sistema di rete robusto e scalabile.
Questo post è stato pubblicato originariamente sul blog di ingegneria.
Mentre l’ecosistema Cardano continua a crescere ed evolversi, i suoi collaboratori si impegnano a perfezionare e ottimizzare continuamente l’infrastruttura di rete di Cardano. Il rilascio del Dynamic peer-to-peer (P2P) networking, fornito con il nodo v.1.35.6, è stato uno sforzo collaborativo del team di networking di IOG, Well-Typed, PNSol e della Cardano Foundation e rappresenta un prodotto altamente performante e una pietra miliare significativa nel viaggio di Cardano verso la creazione di una piattaforma blockchain completamente decentralizzata e sicura.
Dato che Cardano funziona come un sistema stocastico in tempo reale, le sue prestazioni e la sua sicurezza sono intrinsecamente interconnesse. Il team di rete rimane impegnato a trovare l’equilibrio ideale tra vari fattori, comprese le considerazioni topologiche e topografiche, per migliorare la tempestività e la connettività.
Questo blog post illustra il percorso ingegneristico che ha portato allo sviluppo del design Dynamic P2P di Cardano. Approfondisce i principi fondamentali del progetto, evidenzia le sfide incontrate lungo il percorso e svela le soluzioni ideate dal team per creare un sistema di rete robusto e scalabile.
Che cos’è il P2P dinamico?
L’implementazione del Dynamic P2P affina continuamente e dinamicamente la topologia attiva attraverso un processo di selezione dei peer, con l’obiettivo di ridurre il tempo di diffusione complessivo dell’intera rete. I risultati della ricerca suggeriscono che l’utilizzo di una politica basata esclusivamente su informazioni locali può portare a un risultato globale quasi ottimale. Questo risultato si ottiene monitorando la tempestività e la frequenza dei peer che forniscono un’intestazione di blocco, che alla fine viene incorporata nella catena.
L’obiettivo principale è quello di eliminare i peer altamente “non ottimali” mantenendo una forte connettività. A tal fine, i peer considerati meno utili in base a questa metrica vengono periodicamente “espulsi” e sostituiti con alternative selezionate a caso. I risultati delle simulazioni indicano che questo metodo di ottimizzazione converge verso un risultato globale quasi ottimale entro un numero relativamente basso di iterazioni.
In pratica, Dynamic P2P sostituisce la configurazione manuale della selezione dei peer (ad esempio, utilizzando lo strumento topology updater).
Con la configurazione manuale, gli stake pool operator (SPO) dovevano stabilire connessioni con un numero significativo di peer (ad esempio 50) per mantenere un minimo di 20 connessioni attive. Questo approccio era necessario a causa della natura statica dei peer configurati e della disponibilità variabile dei relay SPO.
Con il P2P dinamico, invece, i nodi possono essere configurati per mantenere un numero specifico di connessioni peer attive (ad esempio 20) e scegliere tra tutti i relay SPO registrati sulla catena. In caso di perdita di connessione con un peer, il nodo selezionerà automaticamente peer alternativi e tenterà persistentemente connessioni fino al raggiungimento dell’obiettivo desiderato.
Di conseguenza, il Dynamic P2P elimina la necessità di un over-provisioning delle connessioni, offrendo una soluzione di rete più efficiente e adattabile.
La visione progettuale
Cardano opera come un sistema cooperativo composto da nodi autonomi. Non è stato progettato come un modello client-server, il che significa che non esiste un punto di controllo centrale o una classe privilegiata di server gestiti centralmente. Sebbene la topologia di rete sia nata inizialmente come federata durante la fase di sviluppo di Byron, l’obiettivo era quello di evolverla in un sistema di rete distribuito completamente privo di fiducia, in grado di soddisfare le esigenze in evoluzione dell’ecosistema Cardano, garantendo al contempo connettività e prestazioni ottimali.
Quando il team di rete si è imbarcato in questa avventura ingegneristica, era ben consapevole che avrebbe incontrato numerose sfide e complessità lungo il percorso. Tuttavia, hanno affrontato queste sfide a testa alta, affinando continuamente le idee fondamentali che avrebbero dato forma al design del sistema Dynamic P2P:
-
Modularità ed estensibilità: il sistema è stato progettato tenendo conto della modularità, che consente di sostituire o migliorare facilmente i singoli componenti in base alle esigenze. Questa estensibilità consente di integrare senza problemi nuove funzionalità e miglioramenti, assicurando che il progetto rimanga adattabile alle esigenze in evoluzione dell’ecosistema Cardano. La modularità è particolarmente utile quando si applicano metodi formali per dimostrare la correttezza dei progetti di basso livello rispetto alle specifiche di alto livello. Scomponendo il sistema in componenti più piccoli e gestibili, è possibile applicare in modo più efficace i test basati sulle proprietà a ciascun modulo, assicurando che il comportamento di ciascuna parte sia ben definito e aderisca alle proprietà previste. Naturalmente, la scelta della programmazione funzionale con Haskell come linguaggio di programmazione principale ha avuto un ruolo significativo nel raggiungimento di questo livello di modularità ed estensibilità.
-
Scalabilità: con la crescita della rete, aumenta anche la richiesta di un sistema in grado di gestire un numero maggiore di nodi e transazioni rispettando i vincoli temporali di Ouroboros. Per rispondere a questo requisito di scalabilità nella visione del progetto P2P, il team ha considerato le proprietà di scalabilità fin dall’inizio e ha incorporato strategie come la selezione intelligente dei peer.
-
Sicurezza e resilienza: in una rete decentralizzata, la resilienza e la sicurezza sono di fondamentale importanza. L’obiettivo era costruire un sistema in grado di resistere alle interruzioni interne ed esterne. Per raggiungere questo obiettivo, il team di rete ha implementato robusti meccanismi di gestione degli errori progettati per resistere agli abusi, assicurando che gli utenti non possano attaccare il sistema attraverso attacchi asimmetrici di negazione del servizio che esauriscono le risorse di rete per gli altri utenti. Con l’approccio P2P, ogni nodo può dare priorità alla sua connessione ai peer configurati localmente. Questo garantisce che il nodo mantenga una connessione con i peer fidati e possa progredire nella rete. Le connessioni in entrata sono a velocità limitata e gli obiettivi configurabili dei peer consentono al nodo di regolare il consumo di risorse. Inoltre, un’attenta gestione degli stati di connessione permette di riutilizzare le connessioni duplex, consentendo ai nodi dietro i firewall di migliorare in modo sicuro la loro connettività e di ridurre la superficie di attacco complessiva.
-
Prestazioni: una rete altamente performante è fondamentale per garantire un’esperienza utente senza interruzioni. Sono stati compiuti notevoli sforzi per ottimizzare il progetto, impiegando tecniche come la trasmissione efficiente dei dati attraverso il multiplexing e l’utilizzo di protocolli che supportano il pipelining. Inoltre, la selezione intelligente dei peer svolge un ruolo fondamentale nel ridurre la latenza e garantire una rete reattiva e affidabile.
Per stabilire una comunicazione efficace all’interno della rete Cardano è necessario ottenere una bassa latenza e una buona connettività. Per soddisfare questi requisiti essenziali, Dynamic P2P è stato progettato per garantire una base robusta, scalabile e resiliente per la crescita continua dell’ecosistema. Tuttavia, è importante riconoscere che l’affidabilità dei peer è un fattore critico per mantenere una rete sicura e affidabile. Sebbene l’approfondimento dei dettagli sull’affidabilità esuli dagli scopi di questo blog post, vale la pena notare che il progetto P2P incorpora diverse misure per mitigare i rischi potenziali e salvaguardare la rete.
Analisi della selezione dei peer per i relay dei blocchi in Ouroboros
Garantire le prestazioni e la sicurezza di Ouroboros è fondamentale, e un aspetto critico è la trasmissione tempestiva di nuovi blocchi attraverso la rete. Idealmente, le connessioni all’interno della rete P2P dovrebbero essere organizzate in modo da ridurre al minimo il tempo necessario affinché un blocco venga trasmesso da un nodo a tutti gli altri nodi della rete.
Tuttavia, il raggiungimento di questo obiettivo rappresenta una sfida complessa, con un numero limitato di lavori precedenti applicabili in un ambiente trustless. Per affrontare efficacemente questo problema è stato necessario sviluppare soluzioni innovative in grado di trovare un equilibrio tra la rapidità della comunicazione e il mantenimento dell’integrità e della sicurezza della rete decentralizzata.
Problema
Una soluzione efficace per ottimizzare le prestazioni consiste nel ridurre al minimo il numero di “hop” che un blocco deve attraversare attraverso la rete. In termini grafici, ciò si traduce nella riduzione del numero medio di bordi attraversati da un blocco. Inoltre, la lunghezza di ogni hop o edge è fondamentale. I collegamenti locali hanno una latenza inferiore rispetto a quelli intercontinentali, anche se alcuni collegamenti intercontinentali sono necessari per il relay globale dei blocchi. Ad esempio, una soluzione non ottimale comporterebbe un eccesso di collegamenti intercontinentali, come l’instradamento dall’Europa all’Asia e viceversa.
Gli algoritmi di rete esistenti possono generare “alberi di spanning” ottimali che potrebbero servire come percorsi per il relay a blocchi. Tuttavia, questi algoritmi si basano sul fatto che i nodi si fidino l’uno dell’altro per scambiarsi informazioni accurate, il che non è adatto a una rete P2P blockchain in cui i nodi non possono intrinsecamente fidarsi l’uno dell’altro.
Una soluzione ideale dovrebbe basarsi su informazioni “locali” piuttosto che “globali”, ovvero su informazioni che i nodi possono valutare individualmente senza fare affidamento su dati condivisi e affidabili. Tuttavia, avere una soluzione ottimale che dipende da informazioni globali perfette può servire come punto di riferimento prezioso.
Ricerca preliminare
Il team di rete ha collaborato con ricercatori di rete dell’Università di Atene, specializzati in sistemi decentralizzati e relativi protocolli, per intraprendere un compito cruciale: simulare diverse politiche di rete e studiare i compromessi nel tempo di diffusione.
La questione centrale della diffusione è determinare quali nodi debbano inoltrare i blocchi tra loro o, più precisamente, quali collegamenti di diffusione debbano essere stabiliti tra i nodi per migliorare la velocità di diffusione.
Nell’affrontare questo problema, insieme ai ricercatori abbiamo seguito due approcci principali:
Il primo approccio presuppone che i collegamenti siano indipendenti dal processo di diffusione. Si tratta di simulare un overlay statico in cui i collegamenti vengono stabiliti in base a regole predefinite. Vengono quindi eseguite più disseminazioni per misurare le prestazioni.
Il secondo approccio prevede la regolazione dinamica dell’overlay. In questo approccio, i nodi stabiliscono inizialmente connessioni con nodi casuali della rete e monitorano continuamente le statistiche sulle prestazioni dei loro vicini. Periodicamente, ogni nodo regola il proprio set di vicini sulla base di queste statistiche, decidendo quali vicini mantenere e quali sostituire.
Figura 1. Confronto tra le politiche Close-Random
Il grafico mostra la rapida diffusione di un blocco in tutta la rete, che alla fine raggiunge tutti i nodi. In questo esperimento, tutti i nodi utilizzano la stessa politica Close-Random, ad esempio C6R4 significa che i nodi si connettono a sei peer vicini e a quattro peer casuali. Inizialmente, tutti i nodi non sono informati, cioè non hanno ancora ricevuto il blocco specifico. Tuttavia, a un certo punto dell’esperimento vengono informati. La linea tratteggiata rappresenta la soluzione teorica ottimale, ipotizzando che tutti i nodi informati possiedano una conoscenza completa di quali siano i peer più vantaggiosi, consentendo tali connessioni (god’s view policy).
È importante chiarire che la politica Close-Random non è stata implementata direttamente. Piuttosto, è stata utilizzata come strumento teorico pratico. Essa raggiunge un equilibrio incorporando fattori non locali, pur rimanendo abbastanza semplice da poter essere approssimata utilizzando solo informazioni locali.
Questa analisi dimostra quanto sia possibile avvicinarsi a una soluzione ideale utilizzando principalmente informazioni locali. L’aspetto interessante è che questo approccio supera le aspettative. Ottenere un risultato entro un fattore di due dalla perfezione sarebbe stato lodevole, ma il team ha scoperto che è possibile superare anche questo.
Figura 2. Politica Close-Random vs calibrazione a due gruppi
La Figura 2 confronta i risultati dei due approcci descritti in precedenza. La simulazione prevedeva che ogni nodo mantenesse sei vicini stretti (in base al Round Trip Time (RTT)) e quattro nodi casuali. Questi collegamenti sono stati mantenuti statici per tutta la durata dell’esperimento (da qui le linee blu costanti). Nella politica dei “due gruppi (<=100ms e >100ms)”, ogni nodo mantiene un numero fisso di collegamenti vicini e remoti: ‘vicino’ significa che l’RTT verso quel vicino è minore o uguale a 100 ms, mentre ‘remoto’ implica che l’RTT è superiore a 100 ms. I nodi iniziano con tutti i collegamenti casuali e si calibrano periodicamente. Durante questa calibrazione, mantengono fino a un numero fisso di vicini che hanno un RTT inferiore a 100 ms e sostituiscono alcuni dei vicini rimanenti con nodi casuali scelti di recente.
Questa politica a due gruppi è un’approssimazione semplice ed efficace per valutare il comportamento della politica di scoring. Vale la pena notare, tuttavia, che questa politica non è quella attualmente utilizzata.
Figura 3. Politica Close-Random vs Peer Score
Nella Figura 3 viene presentata un’analisi comparativa tra i risultati ottenuti con la politica Close-Random discussa in precedenza e una diversa politica di punteggio dei peer. Questa politica alternativa valuta i peer in base alla frequenza con cui forniscono un nuovo block header al nodo prima degli altri. In questa configurazione sperimentale, i nodi iniziano con collegamenti casuali e vengono periodicamente sottoposti a calibrazione. Durante questi intervalli di calibrazione, il 20% o il 40% dei peer con prestazioni inferiori vengono sostituiti con nuovi nodi selezionati a caso.
La linea blu del grafico rappresenta la politica attualmente in uso (ulteriori dettagli al riguardo sono riportati nella sezione successiva). La linea verde illustra l’optimum teorico.
Esaminando attentamente questo grafico e facendo un confronto con quello precedente, si possono individuare le principali variazioni nell’efficacia delle diverse politiche di punteggio. Tuttavia, è fondamentale tenere presente che queste variazioni non sono direttamente confrontabili a causa dei diversi parametri applicati in ogni esperimento. Alcuni esperimenti misurano il tempo di diffusione completo, mentre altri considerano il 99° percentile, che rappresenta un valore leggermente inferiore. Inoltre, le tracce di latenza tra i nodi differiscono da un esperimento all’altro, portando a risultati diversi.
In questo contesto, il 99° percentile per la politica del 20% mostra un equilibrio inferiore rispetto ai due gruppi. Tuttavia, non si tratta di un confronto diretto “mele a mele” per le ragioni sopra esposte.
La politica che adottiamo attualmente va oltre l’uso del RTT nella selezione dei peer. Nella nostra ricerca di un approccio più robusto e affidabile, abbiamo cercato un’alternativa che riflettesse accuratamente l’utilità di un peer. Questo ci ha portato al concetto di premiare i peer che sono stati i primi a presentare a un nodo un nuovo header o un blocco. Questo approccio rappresenta una misura autentica del contributo di un peer alla rete e, a differenza dell’RTT, non può essere facilmente manipolato o falsificato.
Rete P2P basata su informazioni locali
Nel progetto P2P dinamico, ogni nodo mantiene una visione locale della rete e valuta le potenziali connessioni considerando le prestazioni storiche. I nodi monitorano e regolano continuamente le loro connessioni, cercando peer più performanti per ottimizzare la loro posizione in rete e minimizzare il numero di hop necessari per il block relay.
Ogni nodo mantiene tre serie di nodi peer conosciuti:
-
Cold peer: peer conosciuti senza una connessione di rete stabilita.
-
Warm peer: peer con una connessione consolidata, utilizzati per le misurazioni di rete ma non per i protocolli di consenso a livello applicativo; il loro ruolo principale è quello di fungere da insieme di nodi prontamente disponibili.
-
Hot peer: peer con una connessione bearer attiva, utilizzati per i protocolli di consenso a livello applicativo.
Come già detto, i nodi mantengono informazioni limitate su questi peer, basate su precedenti interazioni dirette. Per i nodi freddi, queste informazioni possono essere spesso assenti a causa della mancanza di precedenti interazioni dirette. Queste informazioni assomigliano alla “reputazione” di altri sistemi, ma è essenziale sottolineare che sono puramente locali e non condivise con nessun altro nodo.
Figura 4. Scoperta dei peer su Cardano
La Figura 4 illustra il ciclo di promozione/dimissione, gestito dal governatore della selezione dei peer (PSG). Questo componente è responsabile del raggiungimento di obiettivi specifici, come il mantenimento di un determinato numero di peer noti e attivi.
Inoltre, è possibile utilizzare una configurazione statica locale per designare determinati nodi come peer caldi o tiepidi. Questo approccio consente di stabilire relazioni fisse tra i nodi gestiti da un’unica organizzazione, come ad esempio un pool di pali con più relè. Inoltre, facilita gli accordi di peering privato tra SPO e altri potenziali scenari di distribuzione.
In caso di comportamento avverso, un peer può essere immediatamente retrocesso dagli insiemi caldo, tiepido e freddo. Per limitare il consumo di risorse in un sistema senza permessi, si è deciso di non conservare le informazioni negative sui peer per periodi prolungati, in quanto ciò potrebbe potenzialmente semplificare gli attacchi Sybil.
Churning e politiche locali
Il peer churn governor (PCG) è un componente che svolge un ruolo fondamentale nella gestione della salute e dell’efficienza di una rete, affrontando i problemi legati alla partizione della rete e agli attacchi eclipse, regolando i valori degli obiettivi dei peer caldi, tiepidi e freddi in modo da favorirne il churning.
In questo processo, il PCG modifica la frequenza con la quale i peer vengono promossi (aggiornati da freddi a caldi o da caldi a caldi) o retrocessi (declassati da caldi a caldi o da caldi a freddi). Questa decisione è guidata da funzioni di punteggio che valutano i peer in base alla loro utilità e alle loro prestazioni.
Queste funzioni di valutazione comprendono:
-
Politica di retrocessione a caldo: ha il compito di determinare quali peer “caldi” (altamente attivi e di valore) devono essere retrocessi. Il punteggio viene calcolato in base al contributo di un peer alla rete, considerando fattori quali il numero di blocchi forniti per primi e/o il numero di byte forniti. Durante il normale funzionamento, per calcolare il punteggio viene utilizzata una combinazione di questi fattori. Tuttavia, durante la sincronizzazione dei dati di massa, il numero di byte forniti ha la precedenza.
-
Warm demotion policy e cold forget policy: gestiscono i peer “caldi” e “freddi”, determinando quali peer devono essere declassati o rimossi dalla rete. Queste decisioni sono influenzate da un certo livello di casualità e da varie caratteristiche. Tra i fattori presi in considerazione vi sono i fallimenti precedenti o un flag di tiepidezza, che indica una minore affidabilità o livelli di attività più bassi nei peer.
Durante il processo di sincronizzazione dei nodi, il PCG assicura che non vengano utilizzate più di due connessioni attive per evitare un sovrautilizzo delle risorse. Una volta che il nodo è completamente sincronizzato, il PCG facilita il churn periodico, aggiornando il 20% dei peer ogni ora. Questo favorisce una rete robusta e adattabile.
Sebbene le politiche Close-Random o Score-based esplorate nella ricerca non siano direttamente replicate nell’ambiente di produzione, hanno influenzato in modo significativo la progettazione delle politiche implementate. Pertanto, i risultati della ricerca hanno svolto un ruolo cruciale nella definizione delle politiche di rete nell’ambiente di produzione di Cardano.
Approccio allo Sviluppo
L’implementazione P2P di Cardano è costruita su Haskell, un linguaggio di programmazione funzionale ampiamente riconosciuto per la sua correttezza, sicurezza e manutenibilità. Il robusto sistema di tipi di Haskell aiuta a individuare potenziali problemi durante lo sviluppo, dando vita a un codice più robusto e affidabile. Inoltre, il team di rete ha sviluppato e utilizza io-sim, una libreria di simulazione a eventi discreti basata sul tempo che offre un controllo preciso dell’entropia e della tempistica nelle simulazioni. Questo strumento replica fedelmente il sistema di runtime di Haskell, comprese caratteristiche come la memoria transazionale del software (STM), _MVar_s e altre ancora. Questo livello di controllo consente la riproducibilità, i test di regressione e l’esame degli scenari peggiori. La combinazione di Haskell e io-sim consente di testare in modo rigoroso lo stesso codice utilizzato nel sistema di produzione P2P in un’ampia gamma di condizioni, garantendone la prontezza nell’affrontare le sfide del mondo reale.
Nell’impegno di costruire un sistema affidabile, il team di networking ha impiegato test estensivi basati sulle proprietà. Questi test sono stati concepiti specificamente per scoprire bug complessi e casi isolati che potrebbero passare inosservati negli approcci di test tradizionali, come i test unitari. Un aspetto distintivo del processo di test è l’inclusione di simulazioni che replicano anni di funzionamento del sistema. Questo approccio completo permette di imitare anni di attività, scoprendo bug rari che possono emergere solo in condizioni specifiche o prolungate. Tuttavia, è importante notare che la qualità di questi test dipende in ultima analisi dalla qualità dei generatori impiegati. I generatori svolgono un ruolo fondamentale nel produrre input diversi e rappresentativi per una valutazione approfondita.