C++, Rust e scambi crittografici decentralizzati: applicabilità ed efficienza

C++, Rust e scambi crittografici decentralizzati: applicabilità ed efficienza

C++, Rust e scambi crittografici decentralizzati: applicabilità ed efficienza

Introduzione

Gli argomenti linguistici diventano particolarmente fuorvianti nel settore delle criptovalute perché i sistemi stessi sono molto facili da descrivere in modo errato. La gente dice "costruisci un DEX" come se uno scambio decentralizzato fosse un eseguibile con un profilo di latenza, un modello di fiducia e un tipo di fallimento. In realtà un DEX serio è un organismo a strati. Può includere logica on-chain, interazioni tra validatori o nodi, consapevolezza della creazione di blocchi, monitoraggio di mempool, raccolta di dati di mercato, simulazione dello stato, prezzi, instradamento, controlli dei rischi, dashboard degli operatori e talvolta registro degli ordini o servizi adiacenti di corrispondenza che assomigliano sospettosamente a infrastrutture di scambio tradizionali che indossano il vocabolario blockchain.

Una volta riconosciuta questa realtà stratificata, il dibattito tra C++ e Rust diventa più calmo e molto più utile. La domanda giusta non è quale lingua meriti l’intera architettura come punto d’onore. La domanda giusta è quali livelli beneficiano della sicurezza di Rust e dell'adattamento all'ecosistema, quali livelli premiano ancora il controllo delle prestazioni di basso livello di C++ e dove la progettazione ibrida smette di essere un compromesso e inizia ad essere semplice buon senso.

Questo quadro è importante perché i sistemi di scambio decentralizzati vivono sotto pressioni contrastanti. Alcuni livelli vengono puniti più duramente per errori di correttezza, problemi di verificabilità e transizioni di stato non sicure. Altri livelli vengono penalizzati per latenza, velocità effettiva e incapacità di valutare le opportunità con sufficiente rapidità. Altri ancora sono servizi operativi in ​​cui il costo reale è la manutenzione a lungo termine e la velocità del team. Una lingua può essere eccellente per uno di questi oneri e semplicemente adeguata per un altro. L’architettura matura inizia quando lo ammettiamo apertamente.

Un DEX è uno stack, non una dichiarazione di identità

La prima e più importante correzione è concettuale. Un DEX non è una cosa. Un protocollo AMM orientato all’EVM, un ecosistema di programmi nativi di Solana, uno scambio perpetuo di catene di app e un sistema di ricerca che reagisce alle condizioni di mercato meritano tutti istinti ingegneristici diversi. La logica AMM on-chain vive all'interno di una serie di vincoli. I simulatori fuori catena e i valutatori di percorso vivono all'interno di un altro. Componenti simili a ordini o infrastrutture di ricerca ad alta frequenza possono sembrare, dal punto di vista del sistema, molto più vicini al classico software di scambio che al normale sviluppo di applicazioni web.

Questo è il motivo per cui i dibattiti sulla lingua si perdono così rapidamente. Un ingegnere indica Solana e osserva correttamente che Rust è il percorso naturale per lo sviluppo del programma lì. Un altro punta a un motore di routing o di simulazione sensibile alla latenza e osserva correttamente che C++ è ancora una scelta brutalmente forte. Entrambi hanno ragione nel contesto. Il problema inizia quando ogni osservazione viene gonfiata in una teoria totale dell’intero stack.

Un utile reset mentale è chiedersi, per ciascun sottosistema, per quale tipo di dolore viene punito. Se un componente è sbagliato, il problema è soprattutto la mancata correttezza pubblica? È un costo operativo privato? È l'incapacità di rispondere a uno stato in rapido cambiamento prima che l'opportunità si chiuda? Si tratta di oneri di audit, di assunzioni o di infrastrutture? Livelli diversi rispondono a queste domande in modo diverso, motivo per cui i sistemi DEX maturi spesso finiscono per mescolarsi linguisticamente anche quando i dibattiti pubblici bramano la purezza.

Dove la ruggine prende giustamente l'iniziativa

Rust guadagna il suo posto in modo più naturale laddove le transizioni statali, la disciplina della sicurezza e l’adattamento dell’ecosistema dominano l’architettura. Negli ambienti blockchain Rust-first come Solana, questo non è un vantaggio marginale. È il centro di gravità. La lingua non è semplicemente disponibile lì; è circondato da strutture, esempi, abitudini di sicurezza e strumenti che aiutano i team di protocollo a muoversi all’interno dell’ecosistema anziché contro di esso. Per i programmi on-chain, l’adattamento conta più del confronto linguistico astratto. Il linguaggio migliore sulla carta è spesso il linguaggio peggiore se ogni percorso operativo serio attorno ad esso prevede qualcos’altro.

La ruggine è attraente anche nei servizi greenfield che circondano un DEX quando il nemico principale non è la latenza ultra bassa ma la correttezza e la manutenibilità a lungo termine. I servizi del piano di controllo, i livelli di coordinamento e alcuni strumenti di interfacciamento con i protocolli possono davvero trarre vantaggio dalla disciplina incoraggiata da Rust. Il compilatore rileva categorie di errori che altrimenti richiederebbero il controllo di processo, vigilanza e cultura della revisione in C++. Questa non è un'affermazione romantica. È pratico. I team con un forte talento in Rust possono ridurre anticipatamente alcune classi di rischio e mantenere i confini del servizio più calmi nel tempo.

Un utile controesempio mantiene questo radicato. I team a volte deducono dalla forza di Rust nel lavoro nativo della catena che anche ogni sottosistema fuori catena circostante dovrebbe essere Rust per impostazione predefinita. Ma ciò avviene solo se i sistemi circostanti hanno lo stesso dolore dominante. Un simulatore di hot-path o un motore di ricerca che valuta ripetutamente lo stato del mercato sotto stretta pressione temporale non smette di essere un sistema nativo sensibile alle prestazioni solo perché serve un prodotto crittografico. La catena può essere a forma di Rust mentre il percorso di esecuzione circostante rimane molto a forma di C++.

Dove il C++ continua a guadagnarsi da vivere

Il C++ diventa difficile da sostituire laddove un DEX inizia a comportarsi meno come una piattaforma applicativa e più come un'infrastruttura di scambio. L'acquisizione di dati di mercato, l'ascolto di mempool, le pipeline di normalizzazione, la valutazione del percorso, la simulazione dello stato, la ricerca di arbitraggio, i motori di liquidazione e i servizi adiacenti al registro degli ordini condividono tutti una proprietà comune: eseguono lavoro ripetuto di basso livello sotto pressione e quel lavoro spesso si avvicina al layout della memoria, alla strategia di allocazione, all'efficienza del parser, al comportamento della coda o alla prevedibilità della CPU.

È qui che la lunga storia del C++ nei sistemi e nel trading continua ad avere importanza. Il linguaggio offre agli ingegneri il controllo diretto su strutture dati, modelli di threading, durata degli oggetti, allocatori personalizzati, layout vettoriali e strumenti prestazionali che sono stati testati proprio in questi tipi di ambienti. Beneficia inoltre di un ecosistema più vecchio e più denso di esempi di sistemi di rete ad alte prestazioni, simulatori, parser, gateway nativi e codice attento all'hardware. In un’era in cui agli assistenti di intelligenza artificiale viene chiesto di aiutare anche con questi problemi, quella densità aumenta il vantaggio.

Considera un ricercatore che ascolta i segnali del mercato, simula percorsi e decide se vale la pena perseguire un'opportunità. Il costo interessante è raramente una formula isolata. Il costo interessante è l'uso ripetuto e con stato di molte formule circondate da logica di acquisizione, decodifica, instradamento e decisione. Alcune copie evitabili, un lucchetto mal posizionato o una coda indisciplinata possono cambiare l’economia dell’intero percorso. Il C++ non è magico in questo caso, ma fornisce agli ingegneri un linguaggio profondamente familiare per porre domande esatte alla macchina. Nei sistemi che vivono e muoiono ripetendosi sotto la pressione del tempo, ciò conta ancora.

L’economia cambia la risposta linguistica

Uno dei motivi per cui questi dibattiti si surriscaldano è che gli ingegneri parlano come se la condizione di vittoria fosse l’eleganza. Nei sistemi DEX la condizione di vittoria è solitamente economica. La latenza è importante perché le opportunità perse hanno un costo. L’efficienza è importante perché la simulazione ripetuta su larga scala ha un costo. La sicurezza è importante perché le transizioni di stato errate hanno un costo. La semplicità operativa conta perché un sistema che spaventa costantemente i suoi operatori ha un costo. Una volta formulata la tesi in questi termini, la scelta della lingua smette di essere simbolica e diventa finanziaria.

La ruggine spesso si ripaga da sola laddove il costo futuro maggiore deriverebbe da errori di correttezza nella logica hard stateful o dal mantenimento di servizi complessi senza un’adeguata disciplina strutturale. Il C++ spesso si ripaga da solo laddove il costo futuro maggiore deriverebbe dall'inefficienza del percorso caldo, da un'eccessiva astrazione nei calcoli ripetuti o dalla difficoltà di integrazione con l'infrastruttura nativa ad alte prestazioni. Un team sensato si chiede quale costo prevarrà sulla vita del sottosistema e sceglie di conseguenza.

Questa prospettiva aiuta anche a risolvere una confusione comune: la velocità di regolamento e la velocità del percorso di esecuzione non sono la stessa cosa. Una blockchain può avere una serie di caratteristiche temporali a livello di protocollo mentre i sistemi off-chain che la circondano vivono in un mondo di latenza completamente diverso. La lentezza della risoluzione on-chain non rende irrilevante la valutazione veloce off-chain. Infatti, quando le opportunità vengono contestate, la velocità off-chain può diventare ancora più preziosa perché determina chi reagisce, chi valuta in modo accurato e chi invia per primo un’azione utile. Gli ingegneri che appiattiscono questi due domini temporali in un unico concetto chiamato velocità di solito finiscono per disperdere lo sforzo.

L’architettura ibrida è spesso la risposta degli adulti

Molte delle architetture DEX più serie diventano più facili da ragionare una volta che la progettazione ibrida diventa rispettabile. La logica on-chain può vivere nel linguaggio e nell'ambiente quadro che la catena si aspetta. Il piano di controllo e i servizi del prodotto possono scegliere il linguaggio che mantiene la manutenzione sana. La simulazione del percorso caldo, l'instradamento, l'elaborazione dei dati di mercato o i componenti adiacenti di corrispondenza possono rimanere vicini alle tradizioni prestazionali che li rendono più facili da ottimizzare e verificare. Il risultato non è un compromesso ideologico. È un sistema in cui ciascuna parte può ottimizzare il proprio carico reale.

Ciò richiede maturità. I sistemi ibridi sono sani solo quando i confini sono espliciti. I team hanno bisogno di interfacce chiare, di una ristretta suddivisione delle responsabilità e di onestà riguardo alla collocazione della complessità. Ma questo è vero indipendentemente dalla lingua. Un’architettura monolingue con confini confusi non è più semplice di un’architettura bilingue con confini puliti. A volte è semplicemente un'espressione monolingue della stessa confusione.

C'è anche una dimensione relativa al personale. I team spesso immaginano di dover scegliere una lingua perché l'assunzione in più domini nativi risulta difficile. Questa preoccupazione è comprensibile, ma può diventare una scusa per la pigrizia architettonica. Una domanda migliore è se il livello più sensibile alle prestazioni abbia davvero bisogno del proprio linguaggio o se il profiler non abbia ancora giustificato tale costo. Alcuni team dovrebbero assolutamente rimanere per lo più in Rust e introdurre il C++ solo quando un percorso caldo lo ha guadagnato. Altri hanno già una profonda esperienza in C++ e si danneggerebbero forzando tutto in un flusso di lavoro a forma di Rust che non corrisponde al loro istinto di sistema più forte. Ancora una volta il contesto conta più del prestigio.

Cosa cambia l’ingegneria assistita dall’intelligenza artificiale

L’arrivo dei sistemi di codifica basati sull’intelligenza artificiale rafforza in realtà la necessità di una scelta linguistica contestuale anziché indebolirla. Negli ecosistemi blockchain Rust-first, gli agenti possono aiutare con impalcature compatibili con il framework, codice di servizio di routine e alcune categorie di refactoring più comodamente di prima. Ma nei sottosistemi nativi di basso livello e ad alte prestazioni, la bilancia pende ancora verso il C++ per una semplice ragione: il codice pubblico, gli strumenti pubblici e gli esempi di integrazione pubblica sono molto più densi lì. Gli agenti attualmente dispongono di più materiale storico da cui produrre bozze utili per i tipi di infrastrutture a percorso caldo di cui spesso i sistemi DEX hanno bisogno.

Ciò non significa che l’intelligenza artificiale renda il C++ universalmente superiore. Significa che la gravità del vecchio ecosistema è ora amplificata da un nuovo strumento. Quando un assistente aiuta a eseguire il debug di un'integrazione CMake, suggerisce una riprogettazione della coda, migliora un parser o elabora un benchmark per un ciclo di simulazione, trae vantaggio dalla profonda memoria nativa del mondo C++ pubblico. Quando un assistente lavora all'interno di un ambiente on-chain Rust-first, può essere vero il contrario. La decisione linguistica rientra ancora nel carico di lavoro, ma l’era dell’intelligenza artificiale rende la densità ambientale ancora più consequenziale di prima.

La mia raccomandazione pratica

Se stai costruendo programmi nativi della catena in un ecosistema Rust-first, non combattere il terreno per amore della retorica linguistica. Lasciamo che Rust guidi dove è già la sede naturale della correttezza, degli strumenti e della pratica comunitaria. Se stai costruendo un'infrastruttura fuori catena che si comporta come un'ingegneria di scambio sensibile alle prestazioni, non abbandonare il C++ semplicemente perché il dominio del prodotto è crittografico. Lascia che C++ svolga il lavoro che svolge ancora eccezionalmente bene: acquisizione rapida, simulazione ripetuta, logica di routing rigorosa e controllo dei sistemi di basso livello.

E se la tua architettura abbraccia davvero entrambi i mondi, accettalo senza imbarazzo. La buona ingegneria non diventa più pura fingendo che ogni componente soffra dello stesso tipo di guasto. È reso più forte assegnando a ciascun componente un linguaggio che rispetti la fisica del suo lavoro effettivo.

C’è un discreto ottimismo nell’affrontare il problema in questo modo. Ricorda agli ingegneri che l’architettura può essere più calma del discorso pubblico. Non dobbiamo scegliere una lingua per vincere la discussione per sempre. Dobbiamo solo scegliere lo strumento giusto per il successivo livello onesto del sistema. Questo è un tipo di intelligenza molto più redditizio.

Laboratorio pratico: crea un piccolo valutatore di percorsi AMM

Costruiamo qualcosa di abbastanza piccolo da poter essere compreso e abbastanza reale da poter essere toccato.

L'obiettivo non è ricreare Uniswap. L’obiettivo è sentire quanto velocemente il lavoro DEX diventa una questione di ripetute simulazioni e confronti.

__CODICE_0__

#include <cmath>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

struct Pool {
    std::string name;
    double reserve_in;
    double reserve_out;
    double fee; // 0.003 for 0.3%
};

double swap_out(const Pool& p, double amount_in) {
    const double effective_in = amount_in * (1.0 - p.fee);
    return (effective_in * p.reserve_out) / (p.reserve_in + effective_in);
}

double two_hop(const Pool& a, const Pool& b, double amount_in) {
    const double mid = swap_out(a, amount_in);
    return swap_out(b, mid);
}

int main() {
    Pool eth_usdc_a{"ETH/USDC pool A", 500.0, 1750000.0, 0.003};
    Pool eth_usdc_b{"ETH/USDC pool B", 650.0, 2262000.0, 0.0005};
    Pool usdc_dai{"USDC/DAI stable pool", 900000.0, 901200.0, 0.0001};

    const double trade_eth = 4.0;

    const double direct_a = swap_out(eth_usdc_a, trade_eth);
    const double direct_b = swap_out(eth_usdc_b, trade_eth);
    const double routed = two_hop(eth_usdc_b, usdc_dai, trade_eth);

    std::cout << std::fixed << std::setprecision(4);
    std::cout << "Input: " << trade_eth << " ETH\n";
    std::cout << "Direct via " << eth_usdc_a.name << ": " << direct_a << " USDC\n";
    std::cout << "Direct via " << eth_usdc_b.name << ": " << direct_b << " USDC\n";
    std::cout << "Two-hop via " << eth_usdc_b.name << " -> " << usdc_dai.name
              << ": " << routed << " DAI\n";

    if (direct_b > direct_a) {
        std::cout << "Best direct route: " << eth_usdc_b.name << "\n";
    } else {
        std::cout << "Best direct route: " << eth_usdc_a.name << "\n";
    }
}

Costruire

Su Linux o macOS:

g++ -O2 -std=c++20 -o amm_router main.cpp
./amm_router

Su Windows:

cl /O2 /std:c++20 main.cpp
.\main.exe

Perché questo è importante

Anche questo minuscolo programma suggerisce già la reale forma del lavoro DEX off-chain:

  • valutazione del percorso ripetuto
  • confronto a pagamento
  • uscita dipendente dallo stato
  • tensione costante tra correttezza e velocità

Scala questo fino a centinaia di pool, aggiornamenti frequenti dello stato e pressione temporale degli avversari e inizi a capire perché la scelta della lingua smette di essere astratta molto rapidamente.

Attività di prova per appassionati

  1. Aggiungi tolleranza allo slittamento e rifiuta percorsi il cui output effettivo scende al di sotto di una soglia configurata.
  2. Estendi il programma per confrontare cinque o dieci pool invece di due e profilare il tempo che passa.
  3. Aggiungi un circuito che rivaluta il percorso un milione di volte con riserve leggermente variabili e misura come un router "giocattolo" inizia ad assomigliare a un vero percorso caldo.
  4. Sostituisci la formattazione dell'output in virgola mobile con la registrazione numerica strutturata e osserva quanto lavoro "non matematico" appare attorno alla logica del percorso effettivo.
  5. Aggiungi una seconda versione in Rust o in un altro linguaggio e confronta non solo il runtime grezzo, ma anche quanto risulta comodo il linguaggio una volta che il ciclo di simulazione diventa il centro del lavoro.

Questo è un buon esercizio perché rivela qualcosa di sottile: nei software di scambio, la difficoltà interessante spesso non risiede in una singola formula, ma nell'uso ripetuto, con stato e sensibile alla latenza di molte formule ordinarie contemporaneamente.

Riepilogo

C++ e Rust appartengono entrambi all'ingegneria degli scambi decentralizzati, ma vi appartengono per ragioni diverse. Rust guadagna fiducia negli ecosistemi e nei livelli in cui la sicurezza dello stato, la verificabilità e il flusso di lavoro nativo della catena sono centrali. Il C++ guadagna fiducia nei livelli in cui il lavoro inizia ad assomigliare di nuovo a un'infrastruttura di scambio: simulazione ripetuta, elaborazione dei dati di mercato, routing, ricerca e altri sistemi hot-path che premiano uno stretto controllo su memoria, pianificazione e verifica delle prestazioni.

La domanda più utile quindi non è quale lingua vince l’intero stack. Riguarda quale livello stiamo effettivamente progettando e quale tipo di fallimento quel livello può meno permettersi. Una volta posta onestamente la domanda, l’architettura di solito diventa molto più chiara e l’argomentazione diventa meno ideologica. Un DEX ben progettato è raramente un monumento alla purezza del linguaggio. Si tratta di una disposizione pratica di componenti, ciascuno scritto nella lingua che meglio rispetta il peso che porta con sé.

Riferimenti

  1. Libro bianco su Uniswap v3: https://uniswap.org/whitepaper-v3.pdf
  2. Repository principale di Uniswap v3: https://github.com/Uniswap/v3-core
  3. Documentazione MEV di Ethereum.org: https://ethereum.org/developers/docs/mev/
  4. Panoramica dei programmi Solana: https://solana.com/docs/core/programs
  5. Sviluppo del programma Solana Rust: https://solana.com/docs/programs/rust
  6. Documentazione di ancoraggio: https://www.anchor-lang.com/docs
  7. Documentazione della catena dYdX: https://docs.dydx.exchange/
  8. Documentazione sull'integrazione dYdX: https://docs.dydx.xyz/
  9. dYdX su order book off-chain con regolamento on-chain: https://integral.dydx.exchange/dydx-closes-10m-series-b-investment/
  10. Documentazione dell'SDK di Cosmos: https://docs.cosmos.network/
Philip P.

Philip P. – CTO

Back to Blogs

Contatto

Inizia la conversazione

Bastano poche righe chiare. Descrivi il sistema, la pressione e la decisione che è bloccata. Oppure scrivi direttamente a midgard@stofu.io.

01 What the system does
02 What hurts now
03 What decision is blocked
04 Optional: logs, specs, traces, diffs
0 / 10000