<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Venerito Gianmarco </title>
    <description>The latest articles on DEV Community by Venerito Gianmarco  (@gianmarcodev).</description>
    <link>https://dev.to/gianmarcodev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F816168%2Fac38e3f1-7b34-495a-bc49-42dcb23d5daf.png</url>
      <title>DEV Community: Venerito Gianmarco </title>
      <link>https://dev.to/gianmarcodev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gianmarcodev"/>
    <language>en</language>
    <item>
      <title>Trie: struttura dati ad albero ordinato</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Tue, 14 Feb 2023 06:54:03 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/trie-struttura-dati-ad-albero-ordinato-11gg</link>
      <guid>https://dev.to/gianmarcodev/trie-struttura-dati-ad-albero-ordinato-11gg</guid>
      <description>&lt;h2&gt;
  
  
  Il trie: cos'è e come funziona
&lt;/h2&gt;

&lt;p&gt;Il trie, o albero di prefissi, è una struttura dati ad albero utilizzata per memorizzare e cercare rapidamente stringhe o sequenze di caratteri. In un trie, ogni nodo rappresenta un carattere all'interno della stringa e gli archi che collegano i nodi rappresentano le possibili scelte di caratteri successivi. Il percorso dalla radice dell'albero fino ad una foglia rappresenta una specifica stringa.&lt;/p&gt;

&lt;p&gt;L'accesso a un valore all'interno del trie è molto veloce e richiede solo un numero di operazioni proporzionale alla lunghezza della stringa. Questa caratteristica lo rende particolarmente utile per le applicazioni che richiedono la ricerca di stringhe in un grande insieme di dati, come i suggerimenti di completamento automatico nei motori di ricerca.&lt;/p&gt;




&lt;h2&gt;
  
  
  La storia del trie
&lt;/h2&gt;

&lt;p&gt;Il trie è stato sviluppato per la prima volta negli anni '50 come un tipo di struttura dati per la ricerca di parole in un dizionario. Il suo nome deriva dalla parola "retrieval" (recupero) e fu coniato da René de la Briandais, uno dei primi ricercatori a sviluppare questa tecnologia. Nel corso degli anni, il trie è stato esteso e utilizzato in una vasta gamma di applicazioni.&lt;/p&gt;




&lt;h2&gt;
  
  
  Utilizzi del trie
&lt;/h2&gt;

&lt;p&gt;Il trie è utilizzato principalmente per le applicazioni che richiedono l'accesso efficiente e veloce alle stringhe. In particolare, il trie è particolarmente utile per l'implementazione di suggerimenti di completamento automatico in un motore di ricerca o in un'app di messaggistica. Ad esempio, quando un utente inizia a digitare una parola, il trie può essere utilizzato per suggerire le possibili completamenti sulla base delle stringhe già presenti nel dizionario.&lt;/p&gt;

&lt;p&gt;Il trie è inoltre utilizzato nella compressione dei dati. In questo caso, la struttura viene utilizzata per memorizzare le sequenze di caratteri comuni all'interno di un insieme di dati, riducendo così lo spazio di archiviazione richiesto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefici e svantaggi del trie
&lt;/h2&gt;

&lt;p&gt;Tra i principali vantaggi del trie ci sono la velocità di ricerca, la capacità di ridurre lo spazio di archiviazione necessario per una vasta gamma di stringhe e la flessibilità nell'aggiungere e rimuovere stringhe.&lt;/p&gt;

&lt;p&gt;Tuttavia, ci sono anche alcuni svantaggi nel suo utilizzo. La complessità di implementazione del trie può essere piuttosto elevata, soprattutto per stringhe molto lunghe. Inoltre, le prestazioni del trie possono essere influenzate dalla dimensione dell'alfabeto utilizzato nella stringa, il che può portare a un aumento delle dimensioni e della complessità della struttura dati. Infine, il trie può richiedere più spazio di archiviazione rispetto ad altre strutture dati simili, come le tabelle hash.&lt;/p&gt;




&lt;h2&gt;
  
  
  Coding Time
&lt;/h2&gt;

&lt;p&gt;Concentriamoci su questo esempio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XSx292yO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9tmnrd8r0n6njio6oct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XSx292yO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9tmnrd8r0n6njio6oct.png" alt="Trie di esempio" width="205" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Per creare questo trie, è sufficiente procedere in questo modo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trie = new Trie();
trie.insert('HEY');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vediamo ora i dati che ci aspettiamo nei nostri nodi del trie di esempio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3C5h3nSu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rv8n2v8yvcwjag5bpgew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3C5h3nSu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rv8n2v8yvcwjag5bpgew.png" alt="Dati nel trie di esempio" width="407" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Qui, la casella all'interno del JSON indica un riferimento all'altro nodo.&lt;/p&gt;

&lt;p&gt;1) Il nodo radice memorizza un riferimento al nodo H nella chiave H della sua proprietà children.&lt;/p&gt;

&lt;p&gt;2) Il primo nodo memorizza un riferimento al nodo E nella chiave E della sua proprietà children.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Si noti che solo l'ultimo nodo Y ha impostato la proprietà &lt;code&gt;isWord&lt;/code&gt; su &lt;code&gt;true&lt;/code&gt;. Questa proprietà dovrebbe indicare se il nodo è la fine di una parola.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Partiamo creando due file Javascript: nel primo file, chiamato TrieNode.js, scriveremo il codice necessario per creare la classe TrieNode. &lt;br&gt;
Questa classe è utilizzata per creare un oggetto che rappresenta un nodo all'interno di un trie, con una chiave, una lista di figli e un indicatore per segnalare se il nodo rappresenta una parola completa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TrieNode {
    constructor(key) {
        this.key = key;
        this.children = {};
        this.isWord = false;
    }
}

module.exports = TrieNode;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Come possiamo vedere dal codice, la classe &lt;code&gt;TrieNode&lt;/code&gt; ha un costruttore che prende come parametro una chiave (o un carattere). La chiave è memorizzata all'interno della proprietà 'key' del nodo. Il nodo ha anche una proprietà 'children', che è un oggetto vuoto inizialmente, e viene utilizzato per memorizzare i figli del nodo. Infine, troviamo una proprietà 'isWord', inizializzata a 'false', che viene utilizzata per indicare se il nodo rappresenta la fine di una parola.&lt;/p&gt;

&lt;p&gt;Utilizziamo poi l'espressione &lt;code&gt;module.exports = TrieNode&lt;/code&gt; per esportare la classe TrieNode, in modo che possa essere utilizzata nel secondo file.&lt;/p&gt;




&lt;p&gt;Nel secondo file, che ho chiamato per comodita' Trie.js, creiamo la classe Trie: essa ha un costruttore che inizializza un nodo radice utilizzando la classe &lt;code&gt;TrieNode&lt;/code&gt; che abbiamo scritto nel file precedente. Il nodo radice rappresenta la radice del trie e ha una lista di figli vuota.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const TrieNode = require('./TrieNode');

class Trie {
    constructor() {
        this.root = new TrieNode();
    }
    insert(word) {
        let currentnode = this.root;
        const chararray = word.split("");

        for (let i = 0; i &amp;lt; chararray.length; i++) {
            const alphabet = chararray[i];
            if (!(alphabet in currentnode.children)) {
                currentnode.children[alphabet] = new TrieNode(alphabet);
            }
            currentnode = currentnode.children[alphabet];
        }
        currentnode.isWord = true;
    }
}

module.exports = Trie;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parafrasando il codice..&lt;br&gt;
La classe Trie ha un metodo &lt;code&gt;insert(word)&lt;/code&gt; che prende come parametro una parola e la inserisce all'interno del trie. Il metodo crea un puntatore a 'currentnode' che viene inizializzato con il nodo radice. Successivamente, la parola viene divisa in un array di caratteri utilizzando il metodo split(). Viene quindi effettuata un'iterazione attraverso l'array di caratteri e, per ciascun carattere, viene controllato se esiste un nodo figlio corrispondente nel nodo corrente. Se non esiste, viene creato un nuovo nodo figlio per il carattere corrente. Il puntatore 'currentnode' viene quindi aggiornato per puntare al nodo figlio corrispondente al carattere corrente.&lt;/p&gt;

&lt;p&gt;Alla fine del ciclo, il nodo corrente viene marcato come una parola completa impostando l'indicatore 'isWord' su 'true'.&lt;/p&gt;


&lt;h2&gt;
  
  
  Il Branching
&lt;/h2&gt;

&lt;p&gt;Un aspetto importante del trie è la sua capacità di branching, ovvero di ramificarsi e di avere molti figli. Vediamo un esempio più ampio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QtwKUFN0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c62vl955g4pzb9i8x355.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QtwKUFN0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c62vl955g4pzb9i8x355.png" alt="Esempio piu' ampio" width="262" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In questo esempio, sia la lettera E che la prima L avranno due figli.&lt;br&gt;
I dati per la E sarebbero:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    key: "E",
    isWord: false,
    children: {
        'L': lNode,
        'R': rNode,
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In questo caso, &lt;code&gt;hNode&lt;/code&gt;, &lt;code&gt;lNode&lt;/code&gt; e &lt;code&gt;rNode&lt;/code&gt; sono riferimenti agli oggetti di quei particolari nodi.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nell'esempio precedente, ci sono tre nodi che dovrebbero avere &lt;code&gt;isWord&lt;/code&gt; impostato su &lt;code&gt;true&lt;/code&gt;. Si tratta di D, O e T.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nel codice che abbiamo scritto nel secondo file, il branching nel trie viene effettuato nel metodo insert(word) della classe Trie.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!(alphabet in currentnode.children)) {
                currentnode.children[alphabet] = new TrieNode(alphabet);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il branching in questo caso avviene quando incontriamo un carattere che non ha un nodo figlio corrispondente nel nodo corrente. &lt;br&gt;
In questo caso, viene creato un nuovo nodo figlio per il carattere corrente e il puntatore &lt;code&gt;currentnode&lt;/code&gt; viene aggiornato per puntare al nodo figlio appena creato. &lt;/p&gt;

&lt;p&gt;Questo è ciò che viene comunemente definito branching all'interno del trie, poiché il flusso della struttura dati si divide in due percorsi separati, uno per la parola corrente e uno per le parole future. Questo processo viene ripetuto per ogni carattere della parola che viene inserita nel trie.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Ethereum, Patricia Trie e Patricia Merkle Trie</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Mon, 23 Jan 2023 23:25:13 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/ethereum-e-gli-alberi-patricia-trie-54i4</link>
      <guid>https://dev.to/gianmarcodev/ethereum-e-gli-alberi-patricia-trie-54i4</guid>
      <description>&lt;p&gt;INDICE&lt;/p&gt;

&lt;p&gt;1. Introduzione&lt;br&gt;
2. Uno sguardo in parallelo a Bitcoin&lt;br&gt;
3. Radix Trie&lt;br&gt;
4. Patricia Merkle Trie&lt;br&gt;
4.1 Utilità dei PMT in Ethereum&lt;br&gt;
4.2 Utilità dell'intestazione del blocco Ethereum&lt;br&gt;
4.3 Trie dello Stato di Ethereum&lt;br&gt;
4.4 Trie delle transazioni Ethereum&lt;br&gt;
4.5 Trie delle ricevute delle transazioni Ethereum&lt;br&gt;
5. Conclusioni&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduzione
&lt;/h2&gt;

&lt;p&gt;Bitcoin fu la prima rete decentralizzata basata su blockchain che ha reso popolare l'uso degli alberi di Merkle per un tipo di &lt;strong&gt;inclusione scalabile delle transazioni&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Qualche anno più tardi, Ethereum entrò i campo schierando anch'esso gli alberi di Merkle ma, essendo un progetto completamente diverso per sua natura, fu scelta anche un'altra importante struttura di dati ad albero, con riferimento ad alcune delle sue esigenze di archiviazione dei dati.&lt;/p&gt;

&lt;p&gt;Gli alberi utilizzati in Ethereum sappiamo che non sono dei semplici alberi di Merkle, e richiedono delle caratteristiche aggiuntive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;L'albero deve essere &lt;strong&gt;facilmente modificabile&lt;/strong&gt;, in quanto i dati contenuti in esso cambiano frequentemente;&lt;/li&gt;
&lt;li&gt;La radice dell'albero &lt;strong&gt;deve dipendere solo dai dati e non dall'ordine in cui gli aggiornamenti ad esso vengono fatti&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;L'albero deve &lt;strong&gt;avere una "profondità" limitata&lt;/strong&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E la soluzione a queste funzionalità è il "Merkle Patricia trie", rivisitato e adattato all'infrastruttura Ethereum. &lt;/p&gt;

&lt;p&gt;Dei &lt;strong&gt;Patricia Trie&lt;/strong&gt; se ne parlava già nel lontano 1968: a &lt;a href="https://dl.acm.org/doi/10.1145/321479.321481"&gt;pubblicare il paper all'epoca fu un certo &lt;strong&gt;Donald R. Morrison&lt;/strong&gt; all'interno del Journal of the Association for Computing Machinery&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;Ritorniamo ora per qualche momento sulla struttura di Bitcoin.&lt;/p&gt;




&lt;h2&gt;
  
  
  Uno sguardo in parallelo a Bitcoin
&lt;/h2&gt;

&lt;p&gt;L'architettura di Bitcoin è "semplice": consiste in un libro mastro che tiene traccia delle transazioni utilizzando un &lt;a href="https://dev.to/gianmarcodev/utxo-e-modelli-di-account-4ne"&gt;modello UTXO&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Poiché Ethereum tiene traccia di una maggiore quantità di dati di stato, l'architettura dei blocchi è completamente diversa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--__nk4ovx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gs1nl30yxrevqqojc71u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--__nk4ovx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gs1nl30yxrevqqojc71u.png" alt="Architettura blocchi Ethereum" width="880" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perché ora siamo passati a questa architettura a blocchi, non stavamo parlando di alberi?&lt;/p&gt;

&lt;p&gt;Perché questi blocchi contengono riferimenti alle strutture dati ad albero di cui stiamo parlando. &lt;/p&gt;

&lt;p&gt;L'obiettivo è quello di mostrare prima l'architettura a blocchi e poter comparare e avere familiarità con tre delle proprietà fondamentali dei blocchi di Ethereum incluse nel diagramma qui sopra: &lt;br&gt;
1) &lt;strong&gt;State Root&lt;/strong&gt;, &lt;br&gt;
2) &lt;strong&gt;Transaction Root&lt;/strong&gt;, &lt;br&gt;
3) &lt;strong&gt;Receipt Root&lt;/strong&gt; - proprio come nell'ultima sezione abbiamo trattato il significato di merkleRootHash nel contesto di un blocco Bitcoin, ora esamineremo tre nuovi usi simili dell'albero in Ethereum.&lt;/p&gt;

&lt;p&gt;Teniamo questo a mente, dopo ci torneremo! &lt;/p&gt;




&lt;h2&gt;
  
  
  Radix Trie o Patricia Trie
&lt;/h2&gt;

&lt;p&gt;Il PATRICIA trie viene descritto come un albero che permette di conservare una serie di dati di tipo &lt;strong&gt;chiave - valore&lt;/strong&gt; e poi di recuperarli in modo semplice ed efficiente. &lt;/p&gt;

&lt;p&gt;La chiave indica il "percorso" da seguire per giungere alla foglia, la quale contiene il valore corrispondente. &lt;/p&gt;

&lt;p&gt;Il PATRICIA Trie, per recuperare un valore stringa, percorre un ramo di nodi che memorizzano riferimenti associati (chiavi) e che insieme portano al valore finale, e che può essere quindi restituito.&lt;/p&gt;

&lt;p&gt;I PATRICIA Tries presentano però una grande limitazione: sono inefficienti. Se si vuole memorizzare solo una coppia (chiave/ valore) in cui si trova il percorso (nel caso del trie di stato di Ethereum), lunga 64 caratteri in bytes32, servirà oltre un kilobyte di spazio aggiuntivo per memorizzare un livello per carattere, e per ogni ricerca o eliminazione verranno eseguiti tutti i 64 passaggi. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KFJd4T5V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fa26vxf01hitkw7ndye0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KFJd4T5V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fa26vxf01hitkw7ndye0.png" alt="radix trie" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il Patricia Merkle Trie risolve questo problema.&lt;/p&gt;

&lt;p&gt;Come scrivevamo prima, Ethereum utilizza la struttura di dati &lt;strong&gt;radix trie&lt;/strong&gt; (detta anche Patricia Trie o radix tree) ma solo per quei dati permanenti, e per i dati più effimeri e variabili combina questa struttura di dati con un albero di Merkle per creare un &lt;strong&gt;Patricia Merkle Trie&lt;/strong&gt; (PMT).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Patricia Trie + Albero di Merkle = Patricia Merkle Trie (a volte pronunciato come tree, "albero", a volte come trie, "prova") 👀&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7qEOozkG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjal5st4fqif16bkygqi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7qEOozkG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjal5st4fqif16bkygqi.jpg" alt="Confusion Crescendo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CURIOSITA': Cosa significa Trie?&lt;br&gt;
"Trie" deriva dalla parola "&lt;em&gt;retrieval&lt;/em&gt;", ovvero recupero, con riferimento al modo ben ottimizzato con il quale i Patricia Merkle Tries riescono a recuperare dati all'interno di particolare strutture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ripetiamo: I patricia Merkle Tries sono spesso chiamati anche Patricia Merkle Trees 🎄.&lt;/p&gt;




&lt;h2&gt;
  
  
  Radix Trie o Patricia Trie
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Una Patricia Merkle trie è una struttura dati che memorizza coppie chiave-valore&lt;/strong&gt;, proprio come una tabella hash. &lt;br&gt;
Inoltre, consente di verificare l'integrità dei dati e l'inclusione di una coppia chiave-valore.&lt;/p&gt;

&lt;p&gt;I Patricia Merkle Trie raggruppano i nodi con valori simili nell'albero. In questo modo per esempio, la ricerca di "HELP" porta allo stesso percorso della ricerca di "HELLO" - essendo le prime tre lettere voci condivise di parole diverse. &lt;br&gt;
È un'ottima soluzione per l'efficienza di spazio e delle operazioni di lettura/scrittura.&lt;/p&gt;

&lt;p&gt;I PMT sono in pratica alberi di Merkle sotto steroidi: efficienti per la verifica dei dati, ma anche per la loro modifica.&lt;/p&gt;

&lt;p&gt;E finalmente sveliamo l'arcano: perchè Patricia?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P = &lt;strong&gt;Practical&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A = &lt;strong&gt;Algorithm&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;T = &lt;strong&gt;To&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;R = &lt;strong&gt;Retrieve&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;I = &lt;strong&gt;Information&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;C = &lt;strong&gt;Coded&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;I = &lt;strong&gt;In&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A = &lt;strong&gt;Alphanumeric&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Utilità dei PMT in Ethereum
&lt;/h2&gt;

&lt;p&gt;Torniamo sui motivi per cui è stata scelto questo algoritmo.&lt;/p&gt;

&lt;p&gt;In genere, esistono due tipi diversi di dati:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Permanenti&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Una volta che si verifica una transazione, quel record viene sigillato per sempre.&lt;br&gt;
Ciò significa che una volta individuata una transazione nel &lt;strong&gt;trie delle transazioni di un blocco&lt;/strong&gt;, è possibile tornare allo stesso percorso più volte per recuperare lo stesso risultato.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Dati effimeri&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nel caso di Ethereum, gli stati dei conti cambiano continuamente! (Ad esempio, un utente riceve qualche ETH, interagisce con un contratto, ne consuma altri in gas fee ecc.)&lt;br&gt;
Tra queste tipologie di dati figurano: &lt;strong&gt;nonce&lt;/strong&gt;, &lt;strong&gt;balance&lt;/strong&gt;, &lt;strong&gt;storageRoot&lt;/strong&gt;, &lt;strong&gt;codeHash&lt;/strong&gt;;&lt;/p&gt;

&lt;p&gt;È logico che i dati permanenti, come le transazioni minate, e i dati effimeri, come i conti Ethereum (saldo, nonce, ecc.), debbano essere archiviati separatamente. &lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Gli alberi di Merkle, ancora una volta, sono perfetti per i dati permanenti&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I PMT sono perfetti per i dati effimeri&lt;/strong&gt;, di cui Ethereum è estremamente ricco rispetto a Bitcoin (ecco perchè vi ho annoiato con il parallelismo con Bitcoin lol).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A differenza della cronologia delle transazioni, lo stato degli account di Ethereum deve essere aggiornato frequentemente. Il saldo-balance e il nonce dei conti vengono spesso modificati e, inoltre, vengono frequentemente inseriti nuovi account e rispettive chiavi in memoria, anch'esse frequentemente inserite e cancellate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Intestazione del blocco Ethereum
&lt;/h2&gt;

&lt;p&gt;L'intestazione del blocco contiene molti dati. L'intestazione del blocco è il risultato dell'hash di tutti gli elementi di dati contenuti in un blocco: una sorta di packaging di tutti i dati del blocco.&lt;/p&gt;

&lt;p&gt;Se guardiamo il diagramma dell'architettura di Ethereum inserito all'inizio di questo post, l'intestazione del blocco finisce per fare da hash a tutte le proprietà dei dati del blocco. Esso include anche:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;State Root&lt;/strong&gt;: l'hash della radice del trie di stato;&lt;br&gt;
2) &lt;strong&gt;Transactions Root&lt;/strong&gt;: l'hash della radice delle transazioni del blocco;&lt;br&gt;
3) &lt;strong&gt;Receipts Root&lt;/strong&gt;: l'hash della radice del trie delle ricevute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trie dello Stato di Ethereum
&lt;/h2&gt;

&lt;p&gt;Come mostrato nel diagramma qui sotto, il *&lt;em&gt;trie di stato *&lt;/em&gt; di Ethereum funge da mappatura tra gli indirizzi e gli stati degli account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JahfOheI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mj04cmz1u3ljxfq9jj3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JahfOheI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mj04cmz1u3ljxfq9jj3.png" alt="Trie di stato" width="880" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esso può essere visto come uno stato globale che viene costantemente aggiornato dall'esecuzione delle transazioni. &lt;/p&gt;

&lt;p&gt;La rete Ethereum è un computer decentralizzato e lo state trie è considerato un disco rigido.&lt;br&gt;
Tutte le informazioni sugli account sono memorizzate nello state trie globale ed è possibile recuperare le informazioni interrogandolo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esempio di conto&lt;/strong&gt;&lt;br&gt;
Come già detto, lo state trie è solo una mappatura che utilizza un indirizzo come chiave e lo stato del conto (nonce, saldo, ecc.) come valore restituito.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--69DDX3Mc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdasi7pm7zg7feywgjmy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--69DDX3Mc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdasi7pm7zg7feywgjmy.png" alt="Esempio di conto" width="880" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questo è ciò che si ottiene da una richiesta JavaScript allo stato globale di Ethereum. &lt;br&gt;
Solo un oggetto contenente alcuni dati! Questo è tutto ciò che è lo stato dell'account.&lt;br&gt;
Essendo troppi i dati da memorizzare, si utilizza un hash radice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trie delle transazioni Ethereum
&lt;/h2&gt;

&lt;p&gt;Il trie delle transazioni registra le transazioni in Ethereum. Una volta che il blocco è stato estratto, il trie delle transazioni non viene mai aggiornato.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3zf3c7FI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7820rxc60txwcon4hblg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3zf3c7FI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7820rxc60txwcon4hblg.png" alt="Transaction trie" width="880" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ogni transazione in Ethereum registra più elementi specifici per ogni transazione, come il prezzo del gas e il valore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esempio di transazione&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Probabilmente lo avete visto attraverso servizi come Etherscan. Tutto ciò che questi servizi fanno è interrogare la blockchain di Ethereum per trovare i dati delle transazioni e poi indicizzarli in un visualizzatore di transazioni organizzato.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--13YzhTZu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l93chk8h103lppqccty8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--13YzhTZu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l93chk8h103lppqccty8.png" alt="Esempio di transazione" width="880" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si può anche provare a interrogare direttamente il trie delle transazioni usando strumenti esterni, come Alchemy Composer. Basterà prendere un hash casuale di tx e usare il metodo &lt;code&gt;eth_getTransactionByHash&lt;/code&gt;: si otterrà una risposta molto simile all'oggetto nell'immagine qui sopra.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trie delle ricevute delle transazioni Ethereum
&lt;/h2&gt;

&lt;p&gt;Il trie delle ricevute delle transazioni registra le ricevute (i risultati) delle transazioni. I dati includono &lt;code&gt;gasUsed&lt;/code&gt; e &lt;code&gt;log&lt;/code&gt; (gli eventi emessi sono contenuti in questo trie).&lt;/p&gt;

&lt;p&gt;Una volta che il blocco è stato estratto, il trie di ricezione delle transazioni non viene mai aggiornato. Un esempio qui sotto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f8tLK_-9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dymy8otwq4j7nw8968mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f8tLK_-9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dymy8otwq4j7nw8968mk.png" alt="Trie delle ricevute delle transazioni Ethereum" width="880" height="346"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusioni
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OYb8REXl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/csuofzx1tjvp2i5xq0nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OYb8REXl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/csuofzx1tjvp2i5xq0nc.png" alt="Diagramma blocchi Ethereum" width="880" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il diagramma sopra riportato è un'eccellente visualizzazione di come i Trie finiscono per essere impegnati in ogni blocco tramite il loro hash principale. &lt;br&gt;
I dati grezzi sono memorizzati altrove in Ethereum, in particolare nei nodi di archiviazione.&lt;/p&gt;

&lt;p&gt;Il diagramma dell'architettura a blocchi di Ethereum vi sembra meno minaccioso rispetto all'inizio? Se sì, bene! Abbiamo trattato, seppur velocemente, alcuni degli aspetti di livello più basso dell'archiviazione dei dati in Ethereum, e sono importantissimi! Non solo si ha una comprensione più olistica di Ethereum, ma si tratta di conoscenze applicabili a tutta l'informatica e persino alla fisica 🤯.&lt;/p&gt;

&lt;p&gt;L'aspetto più importante di questa lezione è stato sicuramente capire perché queste strutture dati di basso livello sono usate da Ethereum:&lt;br&gt;
a) ottimizzare lo spazio dei dati;&lt;br&gt;
b) ottimizzare l'efficienza di lettura/scrittura;&lt;/p&gt;

&lt;p&gt;Alcuni testi e letture per approfondire gli argomenti trattati:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.ethereum.org/2015/11/15/merkling-in-ethereum"&gt;Merkling in Ethereum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/codechain/modified-merkle-patricia-trie-how-ethereum-saves-a-state-e6d7555078dd"&gt;Modified Merkle Patricia Trie — How Ethereum saves a state
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ethereum</category>
      <category>patriciatrie</category>
      <category>merkle</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Gli alberi di Merkle in Bitcoin</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Fri, 20 Jan 2023 09:18:24 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/gli-alberi-di-merkle-in-bitcoin-4n1f</link>
      <guid>https://dev.to/gianmarcodev/gli-alberi-di-merkle-in-bitcoin-4n1f</guid>
      <description>&lt;p&gt;In quest'ultima analisi sugli alberi di Merkle ci soffermeremo nel capire come essi vengano usati all'interno della tecnologia Bitcoin :) &lt;/p&gt;

&lt;p&gt;Come detto nei precedenti post, la struttura degli alberi di Merkle li rende estremamente efficienti per la &lt;strong&gt;verifica dei dati&lt;/strong&gt;. &lt;br&gt;
Nello specifico, in ₿ Bitcoin gli alberi di Merkle sono utilizzati &lt;strong&gt;per memorizzare in modo efficiente ogni transazione estratta dalla rete Bitcoin&lt;/strong&gt;. Diamo ora uno sguardo alla struttura di un blocco Bitcoin:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xYpUEGHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eyojdzod3wuyif1vhrhy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xYpUEGHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eyojdzod3wuyif1vhrhy.jpg" alt="Struttura blocco Bitcoin" width="532" height="444"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Il diagramma qui sopra mostra l'architettura di un blocco di bitcoin. Pensavate che un blocco di bitcoin contenesse tutte le transazioni per blocco? In un certo senso sì, ma tramite gli alberi di Merkle!&lt;/p&gt;

&lt;p&gt;Come? &lt;br&gt;
Tutte le transazioni per ogni blocco sono organizzate in un mega albero di Merkle. Ciò che in realtà finisce per essere incluso nel blocco è l'hash della radice di quell'albero di Merkle.&lt;/p&gt;

&lt;p&gt;Includendo l'hash della radice dell'albero, i dati delle transazioni possono essere memorizzati fuori dalla catena (i nodi completi, ad esempio, memorizzano i record delle transazioni su un LevelDB integrato in tutti i nodi completi).&lt;/p&gt;

&lt;p&gt;Grazie agli alberi di Merkle, l'archiviazione sulla blockchain è molto efficiente: risulta infatti necessario impegnare solo un pezzo di dati invece di migliaia di transazioni per blocco, che gonfierebbero davvero il sistema!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lo scopo principale dell'utilizzo degli alberi di Merkle su insiemi di dati (solitamente transazioni) di grandi dimensioni è quello di &lt;strong&gt;mantenere la dimensione della blockchain il più piccola possibile&lt;/strong&gt;. &lt;br&gt;
Data la natura del loro utilizzo, le blockchain crescono in continuazione, quindi è necessario prevedere un'archiviazione efficiente dei dati. Mantenere le dimensioni della blockchain contenute significa che più utenti possono sostenere l'esecuzione di nodi completi, il che aiuta la decentralizzazione della rete.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Grazie agli alberi di Merkle, esiste un modo efficiente per verificare l'esistenza di alcuni dati in un hash radice. Prendete l'immagine qui sotto: riuscite a immaginare quanto sarebbe gonfio ogni blocco se fosse necessario memorizzare ogni singola transazione? Molto meglio memorizzare un solo hash radice che rappresenti tutte le transazioni per blocco!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IbXb_rKS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixk5twkezviay6nnktsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IbXb_rKS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixk5twkezviay6nnktsl.png" alt="Hash Tree" width="880" height="368"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Prova di Merkle
&lt;/h2&gt;

&lt;p&gt;Come abbiamo visto nel post precedente, il vantaggio del design dell'albero di Merkle - un algoritmo ricorsivo basato sull'hashing - è che consente di dimostrare in modo efficiente che alcuni dati esistono all'interno della costruzione dell'hash della radice (effettivamente contenuti nel blocco, nel nostro caso); in altre parole, consente di ottenere prove Merkle. &lt;br&gt;
Una prova Merkle può confermare che delle transazioni specifiche rappresentate da una foglia o da un ramo hash siano all'interno di una radice hash Merkle.&lt;/p&gt;

&lt;p&gt;Quindi, se qualcuno ha bisogno di provare che una transazione è esistita in un determinato momento nella blockchain, deve solo fornire una prova Merkle :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bsNzzn5N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8q93cnbxjbm2cyphdci0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bsNzzn5N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8q93cnbxjbm2cyphdci0.png" alt="Image description" width="564" height="329"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Nel diagramma qui sopra, supponiamo di voler dimostrare che C (ovvero una qualche transazione tx casuale) esiste in questo blocco. Grazie alle prove Merkle, sono necessari solo 3 dati in tutto - &lt;strong&gt;D&lt;/strong&gt;, &lt;strong&gt;H(A-B)&lt;/strong&gt;, &lt;strong&gt;H(E-H)&lt;/strong&gt; - per costruire l'hash della radice dell'albero** H(A-H)**. &lt;br&gt;
Potrebbe sembrare poco per un albero così piccolo, ma che dire di un albero contenente oltre 10.000 o 100.000 transazioni? &lt;br&gt;
Se si riuscisse a costruire con successo l'hash della radice si otterrebbe una prova sufficiente che la transazione in questione facesse effettivamente parte di quell'albero Merkle in quel dato momento. &lt;/p&gt;




&lt;h2&gt;
  
  
  Casi d'uso degli alberi Merkle
&lt;/h2&gt;

&lt;p&gt;Ricapitolando, gli alberi Merkle sono:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;efficienti dal punto di vista spaziale e computazionale;&lt;/li&gt;
&lt;li&gt;ottimi per la scalabilità e la decentralizzazione;&lt;/li&gt;
&lt;li&gt;non c'è bisogno di riempire un blocco di transazioni: basta impegnare un hash della radice Merkle e mantenere le transazioni in altri luoghi in grado di gestirle;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In termini più profondi, essi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Riducono significativamente la memoria necessaria per verificare che i dati abbiano mantenuto la loro integrità e non siano stati alterati.&lt;/li&gt;
&lt;li&gt;Richiedono la trasmissione di meno dati attraverso la rete blockchain per verificare i dati e le transazioni. Ciò migliora l'efficienza di una blockchain.&lt;/li&gt;
&lt;li&gt;Consentono la verifica semplice dei pagamenti (SPV), che consente di verificare una transazione senza scaricare un intero blocco o blockchain. Ciò consente di inviare e ricevere transazioni utilizzando un nodo light-client, più comunemente noto come portafoglio di criptovalute.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PROVER E VERIFIER&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quando si verificano i dati utilizzando un albero di Merkle, ci imbatteremo in un Prover e un Verifier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un Prover esegue tutti i calcoli necessari per creare la radice di Merkle (solo un hash!).&lt;/li&gt;
&lt;li&gt;Un verifier, o verificatore: esso non ha bisogno di conoscere tutti i valori per avere la certezza che un valore sia presente nell'albero.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Scala logaritmica
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--evSWq-l4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jiftia7heo5vl84wzcny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--evSWq-l4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jiftia7heo5vl84wzcny.png" alt="Scala logaritmica" width="880" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: La quantità di prove Merkle necessarie cresce in modo logaritmico rispetto alla dimensione dell'array di dati da inserire nell'algoritmo di hash dell'albero di Merkle. &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Conclusione
&lt;/h2&gt;

&lt;p&gt;Gli alberi di Merkle sono una struttura di dati molto popolare nelle blockchain e la ragione alla base è mantenere l'archiviazione dei dati snella ed efficiente; questa comprensione è essenziale quando si inizia a costruire una dApp, perché si vuole sempre essere snelli ed efficienti con l'archiviazione dei dati. Perché? Meno efficiente è l'uso dell'archiviazione dei dati, più costoso sarà il nostro programma per noi e per i nostri utenti.&lt;/p&gt;

&lt;p&gt;Nella prossima sezione vedremo &lt;strong&gt;Patricia Merkle Tries&lt;/strong&gt;, una struttura di dati ampiamente utilizzata in Ethereum.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Terminologia&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Albero di Merkle&lt;/strong&gt;: struttura utilizzata per la validazione dei dati.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Radice di Merkle&lt;/strong&gt;: l'hash contenuto nell'intestazione del blocco, derivato dagli hash di tutte le altre transazioni del blocco.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merkle path&lt;/strong&gt;: rappresenta l'informazione di cui l'utente ha bisogno per calcolare il valore atteso per la radice di Merkle di un blocco, a partire dall'hash della propria transazione contenuta in quel blocco. Il percorso di Merkle viene utilizzato come parte della prova di Merkle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prova di Merkle&lt;/strong&gt;: dimostra l'esistenza di una transazione specifica in un blocco specifico (senza che l'utente debba esaminare tutte le transazioni del blocco). Include la radice Merkle e il percorso Merkle.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Costruire una prova di Merkle e verificarla</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Wed, 18 Jan 2023 05:13:10 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/costuire-una-prova-di-merkle-518f</link>
      <guid>https://dev.to/gianmarcodev/costuire-una-prova-di-merkle-518f</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/gianmarcodev/gli-alberi-di-merkle-55f5"&gt;Nel post precedente&lt;/a&gt; abbiamo imparato a conoscere gli alberi di Merkle, capire a cosa servono e i loro punti di forza. &lt;/p&gt;

&lt;p&gt;Vediamo ora come costruire una prova di Merkle, ovvero la prova che un particolare nodo foglia esiste all'interno di un dato albero &lt;/p&gt;

&lt;p&gt;In questa verifica, vogliamo includere solo gli hash necessari per creare l'hash della radice dal nostro nodo foglia target.&lt;/p&gt;

&lt;p&gt;Esempio di prova - Merkle ABCDE&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Radice
     / \
    ABCD E
    / \ |
   AB CD E
  / \ / \ |
  A B C D E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prova di C&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dimostriamo che C è compresa nella radice di Merkle!&lt;/p&gt;

&lt;p&gt;Costruiamo il percorso per creare la radice da C:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hash(Hash(AB + Hash(C + D)) + E)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I quattro hash utilizzati sono AB, C, D ed E. Poiché iniziamo con C, non ne avremo bisogno nella prova. Avremo bisogno di conoscere AB, D ed E.&lt;/p&gt;

&lt;p&gt;Inoltre, dobbiamo conoscere l'ordine in cui devono essere combinati. Hash(A + B) non sarà uguale a Hash(B + A). La nostra prova deve contenere i dati (l'hash) e se il nodo si trova o meno nella posizione di sinistra.&lt;/p&gt;

&lt;p&gt;La nostra prova risultante avrà il seguente aspetto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
 { dati: 'D', left: false },
 { dati: 'AB', left: true },
 { dati: 'E', left: false }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Osservando questa prova, possiamo facilmente ottenere la combinazione radice. Partiamo da C, concateniamo D a destra (CD), concateniamo AB a sinistra (ABCD) e poi concateniamo E a destra per ottenere la radice ABCDE.&lt;/p&gt;

&lt;p&gt;Ma guarda un po'! Non avevamo nemmeno bisogno di conoscere A o B, ma solo l'hash combinato dei due.&lt;/p&gt;

&lt;p&gt;Un altro esempio?&lt;/p&gt;

&lt;p&gt;Dimostriamo che A appartiene all'albero di Merkle ABCDEFGHIJ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       Radice
        / \
     ABCDEFGH  IJ
       / \      |
    ABCD EFGH   IJ
    / \ / \     |
  AB CD EF GH   IJ
 / \ / \ / \ / \ / \      
 A B C D E F G H I J
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Per dimostrare che A si trova in questo albero abbiamo bisogno del seguente percorso di prova:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hash(Hash(Hash(A + B) + CD) + EFGH) + IJ)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Avremo quindi bisogno di quattro hash: B, CD, EFGH e IJ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
 { dati: 'B', left: false },
 { dati: 'CD', left: false },
 { dati: 'EFGH', left: false }
 { dati: 'IJ', left: false }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un albero così grande e abbiamo bisogno solo di quattro hash per dimostrare A?! Senza considerare che per I o J il risparmio sarebbe ancora maggiore in questo albero: solo due hash necessari per le loro prove. Noice :) &lt;/p&gt;

&lt;h2&gt;
  
  
  In codice
&lt;/h2&gt;

&lt;p&gt;Tenendo a mente il codice del post precedente, aggiungiamo un metodo &lt;code&gt;getProof&lt;/code&gt; alla nostra classe &lt;code&gt;MerkleTree&lt;/code&gt;. Questa funzione accetta l'indice di un nodo foglia e restituisce una prova di Merkle.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;La Merkle Proof *&lt;/em&gt; sarà un array di oggetti con le proprietà &lt;code&gt;data&lt;/code&gt; (l'hash) e &lt;code&gt;left&lt;/code&gt; (un booleano che indica se l'hash è a sinistra).&lt;/p&gt;

&lt;h2&gt;
  
  
  Approccio consigliato
&lt;/h2&gt;

&lt;p&gt;L'approccio è simile a quello seguito per l'algoritmo &lt;code&gt;getRoot&lt;/code&gt;. Pensiamo all'algoritmo suddiviso a livelli.&lt;/p&gt;

&lt;p&gt;Utilizziamo l'albero di Merkle ABCDE come esempio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Radice
     / \
   ABCD E
   / \  |
  AB CD E
 / \ / \ |
 A B C D E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supponiamo di voler dimostrare che C esiste nell'albero. Ci viene dato l'indice 2, che corrisponde alla posizione di C nell'array passato nel nostro costruttore dell'albero di Merkle.&lt;/p&gt;

&lt;p&gt;Quindi iniziamo da C nel livello inferiore. Di che cosa abbiamo bisogno per prima cosa?&lt;/p&gt;

&lt;p&gt;Dobbiamo sapere se C è il nodo sinistro o destro all'interno della sua coppia. Possiamo determinarlo controllando l'indice di C (2). Due è pari, quindi è un nodo di sinistra. Ora che lo sappiamo, dobbiamo aggiungere 1 al nostro indice per ottenere il nodo destro: D. Aggiungiamo D alla nostra prova e possiamo affermare che è un nodo a sinistra: falso (perché è a destra).&lt;/p&gt;

&lt;p&gt;La nostra prova finora:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  { dati: 'D', left: false }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Poiché siamo partiti da C e abbiamo D nella nostra prova, vogliamo ottenere la parte che si combina con CD. Dobbiamo salire di un livello e spostarci all'indice di CD. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Poiché il nostro albero di Merkle è un albero binario&lt;/strong&gt;, ogni livello combina le sue coppie, ottenendo un numero di nodi dimezzato. Ciò significa che dovremmo dimezzare il nostro indice e arrotondare per difetto. Potete verificarlo voi stessi dando un'occhiata a ogni singolo nodo e pensando a dove volete essere al prossimo livello:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per A all'indice 0, vogliamo spostarci su AB all'indice 0;&lt;/li&gt;
&lt;li&gt;Per B a indice 1, vogliamo spostarci in AB a indice 0;&lt;/li&gt;
&lt;li&gt;Per C all'indice 2, vogliamo spostarci su CD all'indice 1;&lt;/li&gt;
&lt;li&gt;Per D all'indice 3, vogliamo spostarci su CD all'indice 1;&lt;/li&gt;
&lt;li&gt;Per E all'indice 4, vogliamo spostarci su EF all'indice 2;&lt;/li&gt;
&lt;li&gt;Per F all'indice 5, vogliamo spostarci su EF all'indice 2;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Si noti che ogni volta dobbiamo dividere l'indice a metà e arrotondare per difetto.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ora ci spostiamo all'indice 1 del secondo livello, che è CD. Verifichiamo se CD è un nodo sinistro o destro: poiché è un numero dispari, è un nodo destro. Sottraiamo uno per ottenere il nodo sinistro AB e lo aggiungiamo alla nostra prova:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[
  { dati: 'D', left: false }, 
  { dati: 'AB', left: true }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se ripetiamo questo schema, divideremo il nostro indice (1) per 2, prenderemo il livello (0) e ci troveremo in ABCD. Prendiamo il nodo destro E e lo aggiungiamo alla nostra prova:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  { dati: 'D', left: false },
  { dati: 'AB', left: true },
  { dati: 'E', left: false }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A questo punto raggiungeremo il livello superiore, con un solo nodo e potremo restituire la nostra prova.&lt;/p&gt;

&lt;p&gt;In codice, aggiungiamo il metodo &lt;code&gt;getProof&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; getProof(index) {
        let currentLayer = this.leaves;

        let proof = [];
        while (currentLayer.length &amp;gt; 1) {
            let newLayer = [];
            let isOdd = currentLayer.length % 2 !== 0;
            let toRange = isOdd ? currentLayer.length - 1 : currentLayer.length;

            for (let i = 0; i &amp;lt; toRange; i += 2) {
                newLayer.push(
                    this.concat(currentLayer[i], currentLayer[i + 1])
                );
                if (i === index) {
                    proof.push({ data: currentLayer[i + 1], left: false });
                }
                if (i + 1 === index) {
                    proof.push({ data: currentLayer[i], left: true });
                }
            }

            if (isOdd) {
                newLayer.push(currentLayer[currentLayer.length - 1]);
            }

            index = Math.floor(index / 2);
            currentLayer = newLayer;
        }

        return proof;
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verificare la prova di Merkle
&lt;/h2&gt;

&lt;p&gt;E ora che abbiamo ottenuto la prova?&lt;/p&gt;

&lt;p&gt;È ora di verificarla. &lt;/p&gt;

&lt;p&gt;Creiamo una funzione &lt;code&gt;verifyProof&lt;/code&gt; che accetti quattro parametri: &lt;code&gt;proof&lt;/code&gt;, &lt;code&gt;node&lt;/code&gt;, &lt;code&gt;root&lt;/code&gt; e &lt;code&gt;concat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ecco le loro definizioni:&lt;/p&gt;

&lt;p&gt;1) &lt;code&gt;proof&lt;/code&gt; - Un array di oggetti le cui proprietà sono &lt;code&gt;data&lt;/code&gt; e &lt;code&gt;left&lt;/code&gt;. (La prova creata nella fase precedente);&lt;br&gt;
2) &lt;code&gt;node&lt;/code&gt; - Un nodo foglia che stiamo cercando di dimostrare essere all'interno dell'albero di Merkle.&lt;br&gt;
3) &lt;code&gt;root&lt;/code&gt; - La radice Merkle valida.&lt;br&gt;
4) &lt;code&gt;concat&lt;/code&gt; - Il metodo usato per combinare i nodi foglia.&lt;/p&gt;

&lt;p&gt;Questo metodo prende il nodo e lo combina con tutti i dati forniti nella prova.&lt;/p&gt;

&lt;p&gt;A questo punto si avrà la propria radice derivata dal nodo e dalla prova. Infine, la confrontiamo con la vera radice per vedere se corrispondono.&lt;/p&gt;

&lt;p&gt;In codice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function verifyProof(proof, node, root, concat) {
    for (let i = 0; i &amp;lt; proof.length; i++) {
        let proofNode = proof[i];
        if (proofNode.left) {
            node = concat(proofNode.data, node);
        } else {
            node = concat(node, proofNode.data);
        }
    }
    return node === root;
}

module.exports = verifyProof;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>merkle</category>
      <category>blockchain</category>
      <category>cryptography</category>
      <category>web3</category>
    </item>
    <item>
      <title>Gli alberi di Merkle</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Wed, 18 Jan 2023 04:50:32 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/gli-alberi-di-merkle-55f5</link>
      <guid>https://dev.to/gianmarcodev/gli-alberi-di-merkle-55f5</guid>
      <description>&lt;p&gt;Gli alberi di Merkle ci permettono di verificare se un dato è contenuto/compreso all'interno di una struttura di dati più grande, senza il vincolo di dover avere tutti i dati di quella struttura. Ciò significa che possono essere utilizzati per verificare le incoerenze in tutti i tipi di sistemi distribuiti, che è la funzione che ci interessa di più :)&lt;/p&gt;

&lt;p&gt;Per le blockchain ed i sistemi distribuiti, la memorizzazione delle transazioni come alberi di Merkle ci permette di esaminare un blocco e verificare che una transazione ne faccia parte, disponendo solo di una parte dei dati!&lt;/p&gt;

&lt;p&gt;Ricordate che i dati di un blocco blockchain sono, semplificando, un insieme di transazioni.&lt;/p&gt;

&lt;p&gt;Vediamo un esempio.&lt;/p&gt;




&lt;p&gt;Albero di Merkle ipotetico: ABCDEFGHIJ&lt;/p&gt;

&lt;p&gt;In questo albero ogni lettera rappresenta un &lt;em&gt;hash&lt;/em&gt;, e le lettere combinate rappresentano la concatenazione degli hash e l'hashing di questi ultimi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      Radice 
        / \
    ABCD EFGHIJ
     | / \
    ABCD EFGH IJ
    / \ / \ |
   AB CD EF GH IJ
  / \ / \ / \ / \ / \      
  A B C D E F G H I J
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Per dimostrare che l'hash A fa parte della Radice di Merkle non è necessario conoscere gli hash C o D, ma solo l'hash CD. La prova necessaria per A è:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠   Hash(Hash(A + B) + CD) + EFGHIJ) ,&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;nella quale abbiamo bisogno di conoscere solo gli hash B, CD e EFGHIJ per dimostrare che A è nella radice di Merkle.&lt;/p&gt;

&lt;p&gt;Se tutto questo vi sembra senza senso, non preoccupatevi :)&lt;/p&gt;

&lt;p&gt;Presto uniremo i puntini (&lt;a href="https://www.youtube.com/watch?v=4Wj-vpWtmF0"&gt;"looking backwards"&lt;/a&gt;) e torneremo su questo argomento.&lt;/p&gt;




&lt;h2&gt;
  
  
  Combinare due foglie
&lt;/h2&gt;

&lt;p&gt;Bene, costruiamo un albero di Merkle! &lt;/p&gt;

&lt;p&gt;Un albero di Merkle prende un array di nodi foglia, combinandoli insieme due alla volta, strato per strato, fino a ridurli a un singolo nodo radice. Questo forma una struttura ad albero di hashing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Obiettivo: radice di due foglie&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Per prima cosa, scriviamo un costruttore per la classe MerkleTree. Questo costruttore accetta due argomenti passati in quest'ordine:&lt;/p&gt;

&lt;p&gt;1) Un array di nodi foglia;&lt;br&gt;
2) Una funzione di combinazione utilizzata per concatenare e fare l'hash di due foglie;&lt;/p&gt;

&lt;p&gt;Diamo un'occhiata più da vicino alla funzione di combinazione.&lt;/p&gt;
&lt;h2&gt;
  
  
  Funzione di combinazione
&lt;/h2&gt;

&lt;p&gt;Per semplificare l'implementazione di questo albero di Merkle e per facilitarne il debug, passeremo una funzione di combinazione  al costruttore &lt;code&gt;MerkleTree&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Questa funzione prenderà due argomenti: un nodo foglia sinistro e un nodo foglia destro e restituirà la combinazione risultante.&lt;/p&gt;

&lt;p&gt;Per esempio, in un albero a quattro foglie:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Radice   
    / \    
   AB CD
  / \ / \ 
  A B C  D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La funzione viene utilizzata tre volte, per ogni combinazione. La indicheremo qui come &lt;code&gt;Hash&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hash(Hash(A + B) + Hash(C + D))&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Per prima cosa combiniamo A e B. Poi combiniamo C e D. Infine combiniamo il risultato di queste due combinazioni AB e CD per ottenere l'hash della radice.&lt;/p&gt;

&lt;p&gt;Confronteremo poi la stringa creata con il risultato atteso.&lt;/p&gt;

&lt;p&gt;Aggiungiamo quindi una funzione &lt;code&gt;getRoot&lt;/code&gt; alla classe &lt;code&gt;MerkleTree&lt;/code&gt;. Questa funzione troverà la radice di Merkle.&lt;/p&gt;

&lt;p&gt;Come detto prima, in questa fase è necessario prendere solo due foglie e metterle in hash insieme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Radice
    / \ 
   A   B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In questo esempio, A e B sono i nodi foglia e la radice è il risultato della combinazione. È sufficiente prendere il primo e il secondo nodo foglia e utilizzare la funzione di combinazione per ottenere il risultato.&lt;/p&gt;

&lt;p&gt;Non ci preoccupiamo ancora di generalizzare il nostro codice: più avanti passeremo ad uno scenario più approfondito.&lt;/p&gt;

&lt;p&gt;In codice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MerkleTree {
    constructor(leaves, concat) {
        this.leaves = leaves;
        this.concat = concat;
    }
    getRoot() {
        this.root = this.concat(this.leaves[0], this.leaves[1]);
        return this.root;
    }
}

module.exports = MerkleTree;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Strati multipli
&lt;/h2&gt;

&lt;p&gt;Ora è il momento di gestire un albero di Merkle più grande! &lt;/p&gt;

&lt;p&gt;Questo albero avrà più livelli. Ad esempio, con quattro nodi foglia si combineranno i primi due nodi e poi gli ultimi due. Quindi si prenderanno i due risultati e li si combinerà per ottenere il nodo radice.&lt;/p&gt;

&lt;p&gt;🧠 &amp;gt; Prima di generalizzare l'algoritmo, potrebbe essere utile rivedere lo scopo dell'albero di Merkle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scopo dell'albero di Merkle
&lt;/h2&gt;

&lt;p&gt;Consideriamo l'esempio delle quattro foglie:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ABCD
    / \ 
   AB CD
  / \ / \
  A B C  D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Di cosa abbiamo bisogno per dimostrare che C è compresa in ABCD? &lt;/p&gt;

&lt;p&gt;Si potrebbe dire che abbiamo bisogno di A, B e D. Ma in realtà queste sono più informazioni di quelle che ci servono!&lt;/p&gt;

&lt;p&gt;In realtà abbiamo bisogno solo di AB e D, infatti:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hash(AB, Hash(C, D))&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In questa derivazione di ABCD, possiamo dimenticarci di A e B. Non abbiamo bisogno di sapere cosa sono per dimostrare che C è nella Radice. Abbiamo solo bisogno di D e AB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questa ottimizzazione è la forza degli alberi di Merkle&lt;/strong&gt;. Diventa ancora più evidente con alberi più grandi, dove sono necessari meno dati per dimostrare che un nodo foglia fa parte dell'albero. Un albero Merkle di 128 nodi richiede solo altri 7 hash per dimostrare che un nodo fogliare appartiene all'insieme.&lt;/p&gt;

&lt;p&gt;Aggiornarniamo ora la funzione &lt;code&gt;getRoot&lt;/code&gt; per gestire alberi di Merkle con più di due nodi foglia.&lt;/p&gt;

&lt;p&gt;Nella scomposizione della logica degli alberi di Merkle, prima otteniamo l'hash di A e B, poi di C e D. Poi passiamo all'hash della combinazione di A e B (AB) con la combinazione di C e D (CD). Qualcosa del genere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ABCD
    / \ 
   AB CD
  / \ / \
  A B C  D

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Nella stesura del codice sarà utile pensare all'albero come se avesse più livelli:&lt;/p&gt;

&lt;p&gt;1) Il primo strato è costituito dalle foglie (A, B, C, D).&lt;br&gt;
2) Il secondo è la combinazione di entrambe le combinazioni (AB, CD).&lt;br&gt;
3) L'ultimo strato è la combinazione finale: la radice di Merkle (ABCD).&lt;/p&gt;

&lt;p&gt;In ogni strato, dovremo combinare gli elementi due alla volta fino a raggiungere uno strato con un solo elemento. A quel punto possiamo fermarci, sapendo di aver trovato la radice.&lt;/p&gt;
&lt;h2&gt;
  
  
  Approccio consigliato
&lt;/h2&gt;

&lt;p&gt;Ci sono diversi modi per affrontare la scrittura di questo algoritmo. Innanzitutto, occorre &lt;strong&gt;scegliere tra ricorsione e iterazione&lt;/strong&gt;. Personalmente, trovo l'approccio ricorsivo più elegante e facile da usare. Sentitevi liberi di scegliere l'approccio con cui vi sentite più a vostro agio :)&lt;/p&gt;

&lt;p&gt;In ogni caso, vediamo il processo mentale su come affrontare il problema.&lt;/p&gt;

&lt;p&gt;Abbiamo un albero di Merkle con un numero arbitrario di nodi foglia. Forse è un albero a quattro foglie:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Radice
    / \ 
   AB CD
  / \ / \
  A B C D

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forse è l'albero magico dalle otto foglie:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
      Radice
       / \
    ABCD EFGH
    / \ / \
   AB CD EF GH
  / \ / \ / \ / \
  A B C D E F G H
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O forse ancora peggio lol&lt;/p&gt;

&lt;p&gt;L'approccio consigliato per questo problema è quello di suddividerlo in livelli.&lt;/p&gt;

&lt;p&gt;Consideriamo l'albero a otto foglie. Per ogni livello, vogliamo prendere 2 nodi e combinarli.&lt;/p&gt;

&lt;p&gt;Quindi, se ci troviamo nel livello inferiore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combinare A e B per ottenere AB&lt;/li&gt;
&lt;li&gt;Combinare C e D per ottenere CD&lt;/li&gt;
&lt;li&gt;Combinare E e F per ottenere EF&lt;/li&gt;
&lt;li&gt;Combinare G e H per ottenere GH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dopodiché, saliamo di livello! Il prossimo livello:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combinare AB e CD per ottenere ABCD&lt;/li&gt;
&lt;li&gt;Combinare EF e GH per ottenere EFGH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combinare ABCD ed EFGH per ottenere ABCDEFGH&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;A ogni livello si controlla se è rimasto un solo elemento. Se rimane un solo elemento, abbiamo trovato la radice. &lt;/p&gt;

&lt;p&gt;💡 &amp;gt; In alternativa, si può calcolare in anticipo quanti strati ci saranno nell'albero. In questo modo si saprà quando restituire la radice in base al numero di livelli su cui si è lavorato.&lt;/p&gt;




&lt;h2&gt;
  
  
  Caso 2: Gestire un numero dispari di foglie
&lt;/h2&gt;

&lt;p&gt;Consideriamo ora il caso di un albero Merkle con un numero dispari di foglie.&lt;/p&gt;

&lt;p&gt;Come fare? Possiamo adottare questa strategia: ogni volta che non abbiamo una coppia per un dato elemento, vogliamo semplicemente portare quella foglia "single" ad un livello più in alto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Radice
    / \ 
   AB  C
  / \  |
  A B  C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In questo caso non usiamo il nodo C finché non lo combiniamo con AB per creare la radice Merkle. &lt;br&gt;
Gestiamo questa casistica nella nostra funzione &lt;code&gt;getRoot&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  La regola degli alberi dispari
&lt;/h2&gt;

&lt;p&gt;La regola per gli alberi dispari è sempre quella di utilizzare tutto ciò che si trova sul lato sinistro prima di riempire il lato destro dell'albero.&lt;/p&gt;

&lt;p&gt;Ipotizziamo un albero con cinque foglie: utilizziamo le prime quattro come lato sinistro e portiamo la quinta fino all'ultima combinazione.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Radice
     /  \
    ABCD  E
    / \   |
   AB CD  E
  / \ / \ |
  A B C D E


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In codice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MerkleTree {
    constructor(leaves, concat) {
        this.leaves = leaves;
        this.concat = concat;
    }
    // Funzione di combinazione
    combine(newLeaves, leafLength) {
        let n = leafLength;

        if (leafLength == 1) {
            // console.log(newLeaves)
            return newLeaves;
        }
        else {
            let i = 0;
            for (i = 0; i &amp;lt; n - 1; i += 2) {
                newLeaves[i / 2] = this.concat(newLeaves[i], newLeaves[i + 1])
            }
            newLeaves[i / 2] = newLeaves[leafLength - 1];
            return this.combine(newLeaves.slice(0, Math.ceil(leafLength / 2)), Math.ceil(leafLength / 2))
        }
    }

    getRoot() {
        // this.root = this.concat(this.leaves[0], this.leaves[1])
        // console.log(this.combine(this.leaves, this.leaves.length))
        return this.combine(this.leaves, this.leaves.length)
    }

}

module.exports = MerkleTree;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






</description>
    </item>
    <item>
      <title>Albero binario di ricerca (BST)</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Thu, 12 Jan 2023 09:59:06 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/albero-binario-di-ricerca-bst-35fe</link>
      <guid>https://dev.to/gianmarcodev/albero-binario-di-ricerca-bst-35fe</guid>
      <description>&lt;p&gt;INDICE&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Albero di ricerca binario&lt;/li&gt;
&lt;li&gt;Creare un nodo&lt;/li&gt;
&lt;li&gt;Il nodo radice&lt;/li&gt;
&lt;li&gt;Costruzione del primo livello&lt;/li&gt;
&lt;li&gt;Generalizzare l'albero&lt;/li&gt;
&lt;li&gt;Implementazione della ricerca&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Albero di ricerca binario
&lt;/h2&gt;

&lt;p&gt;Nella programmazione, gli alberi sono una struttura di dati che si presenta sorprendentemente spesso. Hanno una serie di utilizzi diversi, che vanno dall'archiviazione efficiente dei dati alla rappresentazione di una gerarchia di file.&lt;/p&gt;

&lt;p&gt;In particolare, in questo post esamineremo l'albero di ricerca binaria. Il suo nome può sembrare intimidatorio, ma in realtà è molto semplice!&lt;/p&gt;

&lt;h3&gt;
  
  
  Concetti
&lt;/h3&gt;

&lt;p&gt;Gli alberi iniziano con un nodo radice che si dirama verso i nodi sottostanti (i suoi figli). La parola binario indica che ogni nodo ha al massimo 2 figli. Si chiama albero di ricerca perché l'ordine dei nodi è ordinato in base al valore dei dati. Vediamo un esempio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgp3dx8ul09hg1r7pi67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgp3dx8ul09hg1r7pi67.png" alt="Rappresentazione BST" width="359" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ogni figlio che si trova a sinistra del suo genitore è più piccolo. Ogni figlio che si trova a destra del suo genitore è maggiore. Per esempio, la radice 5 ha due figli 3 e 7. Poiché 3 è minore di 5, è alla sinistra di 5.&lt;/p&gt;

&lt;p&gt;Sapendo che i dati sono in quest'ordine, ci vorrà meno tempo per trovare un particolare nodo. Ad esempio, cerchiamo il 4. &lt;br&gt;
Partendo dalla radice, sappiamo che è minore di 5 e quindi andiamo a sinistra. Poi incontriamo 3 e sappiamo che 4 è maggiore di 3, quindi andiamo a destra. E qui troviamo il 4. &lt;br&gt;
In media questo metodo sarà più veloce di una ricerca casuale. Il risparmio di tempo diventa tanto maggiore quanto più grande è l'albero.&lt;/p&gt;

&lt;p&gt;Ora proviamo a costruire il nostro albero di ricerca binaria scrivendo un po' di codice, che non fa mai male :)&lt;/p&gt;


&lt;h3&gt;
  
  
  Creare un nodo
&lt;/h3&gt;

&lt;p&gt;Creiamo innanzitutto la classe Node, dalla quale creeremo ogni elemento del nostro albero:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filyw5cljd0fvyw9x1xep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filyw5cljd0fvyw9x1xep.png" alt="Nodo" width="231" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il nodo deve contenere dei dati, che inseriremo successivamente. Deve inoltre contenere i riferimenti al figlio sinistro (left) e al figlio destro (right).&lt;/p&gt;

&lt;p&gt;Completiamo il metodo costruttore e la funzione costruttore sul nodo. Successivamente, memorizziamo i dati in una proprietà &lt;code&gt;data&lt;/code&gt; dell'istanza.&lt;/p&gt;

&lt;p&gt;Infine, memorizziamo &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt; e &lt;code&gt;right&lt;/code&gt; nelle proprietà utilizzando &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esempio di utilizzo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;


    }
}

module.exports = Node;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Il nodo radice
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedne16dhmsxwcu7m39g3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedne16dhmsxwcu7m39g3.png" alt="Radice" width="231" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ora è il momento di creare il nostro albero. &lt;br&gt;
Un albero terrà traccia di una proprietà specifica: il riferimento al nodo radice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Radice&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Completiamo la funzione costruttore della classe &lt;code&gt;Tree&lt;/code&gt; nel nuovo file &lt;code&gt;Tree.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tutto ciò che occorre fare per ora è memorizzare &lt;code&gt;null&lt;/code&gt; nella proprietà &lt;code&gt;root&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Tree {
    constructor() {
        this.root = null;
    }
}

module.exports = Tree;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Aggiunta di una radice
&lt;/h3&gt;

&lt;p&gt;In questa fase creeremo un nuovo metodo per aggiungere nodi al nostro albero. È un compito difficile da generalizzare, quindi lo affronteremo pezzo per pezzo :)&lt;/p&gt;

&lt;p&gt;Per prima cosa iniziamo ad aggiungere una radice a un albero vuoto.&lt;/p&gt;

&lt;p&gt;Creiamo un nuovo metodo &lt;code&gt;addNode&lt;/code&gt; sulla classe &lt;code&gt;Tree&lt;/code&gt; che prenda un nuovo nodo e lo aggiunga all'albero.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfz5cxdcfa4v6hmjp0it.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfz5cxdcfa4v6hmjp0it.png" alt="Add a root" width="181" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si supponga che l'albero sia vuoto per questa fase. È sufficiente impostare la radice come il nodo passato nel metodo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    addNode(newNode) {
        this.root = newNode;
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Costruzione del primo livello
&lt;/h3&gt;

&lt;p&gt;Ora è il momento di concentrarsi sull'aggiunta del primo strato di nodi sotto la nostra radice! :)&lt;/p&gt;

&lt;p&gt;Ogni nodo che non presenta archi uscenti è detto &lt;strong&gt;foglia&lt;/strong&gt; (leaf node) e in ogni albero finito, cioè con un numero finito di nodi, si trova almeno un nodo foglia. Ovviamente, un nodo può essere contemporaneamente padre (se ha archi uscenti) e figlio (se ha un arco entrante, ovvero se è diverso dalla radice).&lt;/p&gt;

&lt;p&gt;Manteniamo il codice utilizzato per superare l'ultima fase e aggiungiamo un'altra casistica per quando esiste già una radice:&lt;/p&gt;

&lt;p&gt;Quando la radice esiste già, dobbiamo decidere da che parte aggiungere il nuovo nodo foglia.&lt;/p&gt;

&lt;p&gt;Se i dati del nuovo nodo sono inferiori a quelli della radice, lo aggiungeremo a sinistra.&lt;/p&gt;

&lt;p&gt;Al contrario, se i dati sono maggiori, lo aggiungeremo a destra. &lt;/p&gt;

&lt;p&gt;Modifichiamo ora la funzione addNode per gestire anche l'aggiunta dei primi figli della radice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Nuovo metodo: se la root esiste, e se il dato del nuovo nodo e' minore, aggiungiamo il nodo a sinistra. Viceversa, a destra.

    addNode(newNode) {
        if (this.root) {
            if (newNode.data &amp;lt; this.root.data) {
                this.root.left = newNode;
            } else {
                this.root.right = newNode;
            }

            // Se non dovesse esistere una gia' una radice..
        } else {
            this.root = newNode;
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Generalizzare l'albero
&lt;/h2&gt;

&lt;p&gt;Ora è il momento di far funzionare la funzione &lt;code&gt;addNode&lt;/code&gt; per generali livelli dell'albero.&lt;br&gt;
Completiamo la funzione &lt;code&gt;addNode&lt;/code&gt; in modo che possa gestire l'aggiunta di nodi indipendentemente dalle dimensioni dell'albero.&lt;/p&gt;

&lt;p&gt;Possiamo farlo in modo iterativo o ricorsivo! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Soluzione ricorsiva&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Abbiamo già scritto il codice per aggiungere un nodo sotto un altro nodo. Tutto ciò che dobbiamo fare è applicarlo in modo &lt;strong&gt;ricorsivo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Un buon modo per iniziare la soluzione ricorsiva è scrivere una nuova funzione su Albero che prenda due argomenti: un genitore e un figlio. Questa funzione deve aggiungere il figlio sotto il nodo genitore.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Caso 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se i dati del figlio sono inferiori a quelli del genitore, sceglieremo di andare a sinistra.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se il genitore ha già un nodo sinistro, chiameremo questa nuova funzione ricorsivamente con quel nodo sinistro come genitore;&lt;/li&gt;
&lt;li&gt;Se il genitore non ha un nodo sinistro, impostiamo il nuovo nodo come nuovo nodo sinistro;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Caso 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se i dati del figlio sono maggiori di quelli del genitore, sceglieremo di andare a destra.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se il genitore ha già un nodo destro, chiameremo questa nuova funzione ricorsivamente con quel nodo destro come genitore;&lt;/li&gt;
&lt;li&gt;Se il genitore non ha un nodo destro, impostiamo il nuovo nodo come nuovo nodo destro;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ora è possibile invocare questo metodo da &lt;code&gt;addNode&lt;/code&gt; se esiste una radice. Inizialmente la radice sarà il genitore, che si espanderà man mano che verranno aggiunti altri nodi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor() {
        this.root = null;
    }

    // Soluzione ricorsiva
    insertNode(root, newNode) {
        if (newNode.data &amp;lt; root.data) {
            if (root.left) {
                this.insertNode(root.left, newNode);
            } else {
                root.left = newNode;
                return;
            }
        } else {
            if (root.right) {
                this.insertNode(root.right, newNode);
            } else {
                root.right = newNode;
                return;
            }
        }
    }
    addNode(newNode) {
        if (this.root) {
            this.insertNode(this.root, newNode);
        } else {
            this.root = newNode;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Implementazione della ricerca
&lt;/h3&gt;

&lt;p&gt;È il momento di raccogliere i frutti della creazione del nostro albero di ricerca binario. E' il momento della ricerca :) &lt;/p&gt;

&lt;p&gt;Il nostro obiettivo: costruire il metodo &lt;code&gt;hasNode&lt;/code&gt;.&lt;br&gt;
Il metodo &lt;code&gt;hasNode&lt;/code&gt; prende come input un numero e cerca nel nostro albero un nodo che abbia quel numero all'interno della sua proprietà dati.&lt;/p&gt;

&lt;p&gt;Se esiste un nodo con il numero, restituisce true. In caso contrario, restituisce false.&lt;/p&gt;

&lt;p&gt;Utilizziamo l'ordine di ordinamento per trovare i nodi dell'albero. Ad esempio, se cercassimo il nodo 4, potremmo usare l'ordine di ordinamento per trovare i nodi nell'albero:&lt;/p&gt;

&lt;p&gt;1) Partiamo dalla radice 5, riconosciamo che 4 è minore di 5 e ci spostiamo a sinistra. &lt;/p&gt;

&lt;p&gt;2) Troviamo 3, riconosciamo che 4 è maggiore di 3 e ci spostiamo a destra. &lt;/p&gt;

&lt;p&gt;3) Troviamo 4, riconosciamo che è quello che stiamo cercando e restituiamo true.&lt;/p&gt;

&lt;p&gt;Se cerchiamo un nodo mancante, restituiamo false.&lt;/p&gt;

&lt;p&gt;Ad esempio, se cercassimo 7 in questo albero:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95xhzbi2blwnu9wqgfu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95xhzbi2blwnu9wqgfu1.png" alt="Quando restituire false" width="379" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ci accorgeremmo che 7 è maggiore di 5, e spostandoci a destra non troveremo nessun nodo destro! Restituiamo quindi false.&lt;/p&gt;

&lt;p&gt;Come implementiamo lato codice tutto questo bel ragionare?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    hasNode(data) {
        return this.findNode(this.root, data);
    }
    findNode(root, data) {

        // Caso base ricorsivo
        if (!root) {
            return false; // Se la root non viene trovata, restituiamo false
        } else if (root.data === data) {
            return true;
        // Chiamata ricorsiva a sinistra
        } else if (root.data &amp;gt; data) {
            return this.findNode(root.left, data); 
        // Chiamata ricorsiva a destra    
        } else if (root.data &amp;lt; data) {
            return this.findNode(root.right, data); 
        }
    }

const tree = new Tree();
const node1 = new Node(4);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nel prossimo approfondimento analizzeremo gli alberi di Merkle, la loro struttura e il loro funzionamento, il tutto condito con del sano codice JS :) &lt;/p&gt;

&lt;p&gt;Grazie per la lettura ed il tempo dedicato!&lt;/p&gt;

</description>
      <category>career</category>
      <category>devto</category>
      <category>gratitude</category>
    </item>
    <item>
      <title>Strutture dati ad albero</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Mon, 09 Jan 2023 06:19:00 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/strutture-dati-ad-albero-7gf</link>
      <guid>https://dev.to/gianmarcodev/strutture-dati-ad-albero-7gf</guid>
      <description>&lt;h2&gt;
  
  
  Introduzione
&lt;/h2&gt;

&lt;p&gt;Le reti blockchain utilizzano le transazioni per cambiare lo stato e tenere traccia dei saldi degli utenti, come abbiamo visto nella sezione precedente. Scaviamo ancora più a fondo nella complessità di questi sistemi e iniziamo a vedere quali strutture dati utilizzano per memorizzare tutti questi dati di stato in continua evoluzione.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un orientamento agli alberi
&lt;/h2&gt;

&lt;p&gt;Prima di tutto, gli informatici sono strani. A noi piace disegnare gli alberi al contrario lol&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5wY-9FqJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4mdbfiu6bbw3rwut1gzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5wY-9FqJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4mdbfiu6bbw3rwut1gzl.png" alt="Upside Down Tree" width="880" height="1017"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Come nella vita reale esistono molti tipi di alberi, anche in informatica esistono molte strutture di dati simili ad alberi. Vediamo di familiarizzare con alcuni di questi alberi.&lt;/p&gt;

&lt;p&gt;Assicuratevi di dare un'occhiata ai termini in grassetto, poiché si tratta di un vocabolario molto importante da imparare per le blockchain in generale!&lt;/p&gt;




&lt;h2&gt;
  
  
  I nodi
&lt;/h2&gt;

&lt;p&gt;Il primo termine che vedrete ampiamente utilizzato nelle strutture dati: &lt;strong&gt;nodi&lt;/strong&gt;. Un nodo è un'unità di base di una struttura di dati.&lt;/p&gt;

&lt;p&gt;Nei sistemi informatici, "nodo" può anche riferirsi ai nodi di rete che comunicano dati su una rete peer-to-peer (come sono Bitcoin ed Ethereum!). Il contesto è importante!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Albero semplice&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sFSjfS7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygzph3wwkycrei04m3nt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sFSjfS7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygzph3wwkycrei04m3nt.png" alt="Albero semplice" width="672" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nel nodo semplice come nella foto qui sopra, vediamo un nodo arancione in alto, definito genitore, mentre i nodi verdi in basso vengono definiti figli (rispetto al nodo genitore).&lt;/p&gt;




&lt;h2&gt;
  
  
  Albero binario
&lt;/h2&gt;

&lt;p&gt;E' tipico osservare qualche proprietà di applicazione delle strutture "albero" per distinguerne i diversi tipi di dati.&lt;/p&gt;

&lt;p&gt;Un albero è considerato &lt;strong&gt;binario&lt;/strong&gt; quando ogni genitore ha al massimo due figli. La parola chiave di questo albero è "binario" che, come altri termini che precedono "albero", stabilisce un tipo di regola per l'albero, in questo caso che ogni nodo genitore può avere al massimo due figli.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Ln8KeRs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywj8gkw5qezvjpcr2luf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Ln8KeRs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywj8gkw5qezvjpcr2luf.png" alt="Albero binario" width="803" height="732"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si noti che l'albero nel diagramma precedente ha ora quattro nuovi nodi grigi. Questi vengono ora chiamati foglie, poiché sono l'ultimo livello dell'albero e non hanno altri figli.&lt;/p&gt;




&lt;h2&gt;
  
  
  Un albero generico
&lt;/h2&gt;

&lt;p&gt;L'albero qui sopra mostra che un albero può essere un genitore qualsiasi con un numero qualsiasi di figli. Non è necessario che l'albero sia sottoposto a regole, è semplicemente un albero di dati.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LQIcpTdr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uiskby4wnvux41lv89k2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LQIcpTdr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uiskby4wnvux41lv89k2.png" alt="Un albero generico" width="880" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vedremo emergere uno schema in cui la parola "albero" è solitamente preceduta da un termine che indica quali tipi di regole l'albero applicherà. Un albero binario applica la regola secondo cui i genitori possono avere al massimo due figli. Un albero senza aggettivi... beh è solo un albero! &lt;/p&gt;




&lt;h2&gt;
  
  
  Albero vs. Elenco collegato
&lt;/h2&gt;

&lt;p&gt;Anche un elenco collegato è un albero, solo che è molto lungo e ha solo un figlio per ogni genitore in una lunga catena continua. Un albero non è necessariamente un elenco collegato. Ecco le due implementazioni del codice per un &lt;code&gt;LinkedListNode&lt;/code&gt; e &lt;code&gt;unTreeNode&lt;/code&gt;, per aiutare a distinguere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class LinkedListNode {
    constructor(data) {
        this.data = data;
        this.next = null;
    }
}

class TreeNode {
    constructor(data) {
        this.data = data;
        this.children = []; // riferimento al figlio 
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si noti che il TreeNode contiene i dati tipici e un array per contenere i riferimenti ai figli di quel nodo (genitore).&lt;/p&gt;

&lt;p&gt;Il LinkedListNode tiene solo traccia di un nodo successivo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Vocaboli utili
&lt;/h2&gt;

&lt;p&gt;Notate tutte le relatività che si verificano quando un albero cresce di dimensioni. Un nodo che era un nodo foglia diventa un nodo genitore una volta aggiunto un nuovo figlio sotto di esso.&lt;/p&gt;

&lt;p&gt;Ecco alcuni vocaboli utili quando si parla di strutture dati ad albero:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;chiave&lt;/strong&gt; (key): dati effettivi contenuti nel nodo;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;radice&lt;/strong&gt; (root): il nodo padre di un albero;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fratelli&lt;/strong&gt; (siblings): nodi sotto lo stesso genitore e allo stesso livello;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sottoalbero&lt;/strong&gt; (subtree): una volta isolata una parte di un albero più ampio, è possibile formare un albero nuovo con nuove relazioni;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quando usare un albero 🌲
&lt;/h2&gt;

&lt;p&gt;A volte gli alberi si formano in modo del tutto naturale! LOL &lt;br&gt;
Prendiamo ad esempio un file system:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HY0aGD5c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdm5tfiq5xetmv8zy7gd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HY0aGD5c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdm5tfiq5xetmv8zy7gd.png" alt="Es. file system" width="880" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un file system ad esempio può essere un albero con una quantità arbitraria di figli in ogni directory.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Uso dell'albero:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se i dati possono essere memorizzati in modo gerarchico, l'uso di un albero può essere una buona struttura di dati da utilizzare.&lt;br&gt;
Un albero è anche una struttura dati molto efficiente per la &lt;strong&gt;ricerca e l'ordinamento dei dati.&lt;/strong&gt;&lt;br&gt;
Gli &lt;strong&gt;algoritmi ricorsivi&lt;/strong&gt; sono spesso utilizzati insieme agli alberi.&lt;br&gt;
Questi ultimi infatti possono essere strutture di dati molto efficienti per la ricerca e l'ordinamento dei dati proprio per le regole che stabiliscono, come abbiamo visto per l'albero binario, o addirittura un insieme di regole ancora più rigide, come con l'albero di ricerca binario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Albero di ricerca binario
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H1zXuuyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98i1npp2ijspcm3axwor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H1zXuuyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98i1npp2ijspcm3axwor.png" alt="Albero di ricerca binario" width="650" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Un albero di ricerca binario&lt;/strong&gt;, come quello sopra descritto, ha le seguenti proprietà:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;è un albero binario;&lt;/li&gt;
&lt;li&gt;il sottoalbero sinistro di un nodo contiene solo nodi con chiavi minori della chiave del nodo stesso;&lt;/li&gt;
&lt;li&gt;il sottoalbero destro di un nodo contiene solo nodi con chiavi maggiori della chiave del nodo stesso;&lt;/li&gt;
&lt;li&gt;anche i sottoalberi sinistro e destro di ogni nodo devono essere un albero di ricerca binario;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questi tipi di imposizioni rendono l'albero di ricerca binario una struttura dati molto richiesta, poiché gli algoritmi possono ora tenere conto di queste regole e la memorizzazione/ricerca è molto più efficiente;&lt;/p&gt;

&lt;h2&gt;
  
  
  Curiosità sull'albero di ricerca binario
&lt;/h2&gt;

&lt;p&gt;Sapendo che ogni figlio sinistro è minore del genitore e ogni figlio destro è maggiore del genitore, quanti tentativi sono necessari per trovare un numero (chiave) al massimo?&lt;/p&gt;

&lt;p&gt;L'aggiunta di un nuovo livello di elementi aggiunge solo 1 tentativo di ricerca in più, nella peggiore delle ipotesi. Grazie alle proprietà di applicazione del BST (acronimo di Binary Search Tree), il tempo di ricerca rimane sempre &lt;strong&gt;O(log n)&lt;/strong&gt;, dove &lt;em&gt;n&lt;/em&gt; è il numero di nodi dell'albero.&lt;/p&gt;

&lt;p&gt;L'albero nel diagramma qui sopra è un BST di altezza (quanti livelli ha un albero) pari a tre, con nodi a ogni livello che aumentano di una potenza di due a ogni livello inferiore. L'ultimo livello contiene 4 nodi, il che significa che il livello successivo conterrà 8 nodi (al massimo). Ecco la vera magia degli alberi a proprietà forzata come i BST: &lt;strong&gt;anche se aggiungiamo un intero nuovo livello di nuovi dati, il tempo di ricerca aumenta solo di uno&lt;/strong&gt;. &lt;strong&gt;In altre parole, mentre la dimensione dell'albero cresce in modo esponenziale, il tempo di ricerca rimane sempre O(log n).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ecco un grafico per visualizzare quanto il tempo di ricerca dell'algoritmo sia influenzato dalla crescita dell'input (n).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3MhOEIBN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2sasqs65pnivci0eftg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3MhOEIBN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2sasqs65pnivci0eftg.png" alt="Correlazione tempo/input" width="880" height="583"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Poiché le blockchain sono fondamentalmente dei database, la notazione O-Grande è molto importante per aiutare a scegliere la struttura dei dati più efficiente (bassi costi di archiviazione, facilità di ricerca e recupero). &lt;br&gt;
Quando si progetta un sistema con esigenze di dati, si desidera che la struttura dei dati sia il più possibile vicina al tempo costante (la linea blu del grafico).&lt;/p&gt;

&lt;p&gt;La notazione O-Grande ci dà un indicatore approssimativo del rendimento di un algoritmo in termini di N (numero di elementi in ingresso). Vogliamo che i nostri algoritmi siano efficienti.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusione&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Abbiamo trattato le strutture dati ad albero di base, i diversi tipi di applicazione sugli alberi e il vocabolario generale delle strutture dati ad albero. Si tratta di informazioni importanti per addentrarci ancora di più in alberi più specifici e con imposizioni più specifiche. Nel prossimo post invece, affronteremo  gli alberi di Merkle.&lt;/p&gt;

</description>
      <category>data</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>italia</category>
    </item>
    <item>
      <title>UTXO e Modelli di Account</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Mon, 09 Jan 2023 05:52:10 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/utxo-e-modelli-di-account-4ne</link>
      <guid>https://dev.to/gianmarcodev/utxo-e-modelli-di-account-4ne</guid>
      <description>&lt;p&gt;Con le piattaforme tradizionali basate su server web2, tenere traccia dei dati e delle informazioni degli utenti è molto più facile che con le blockchain. Questo perché c'è un unico server centralizzato che memorizza lo stato degli account degli utenti. Non c'è bisogno di consenso o di risolvere le discrepanze perché c'è un solo luogo centrale che memorizza le informazioni.&lt;/p&gt;

&lt;p&gt;Tuttavia, quando si passa a un sistema decentralizzato, il problema della memorizzazione dei saldi degli utenti diventa complicato. Le reti decentralizzate come Bitcoin ed Ethereum hanno bisogno di modelli specifici per tenere traccia dello stato degli utenti. Bitcoin utilizza il modello UTXO per tenere traccia dei saldi degli utenti. Ethereum e altre catene EVM utilizzano il modello di account per tenere traccia dei saldi degli utenti. &lt;/p&gt;

&lt;p&gt;Approfondiamo... :) &lt;/p&gt;




&lt;p&gt;UTXO è l'acronimo di "&lt;strong&gt;Unspent Transaction Output&lt;/strong&gt;". Vedrete il termine UTXO usato un po' in questo post.&lt;br&gt;
Bitcoin utilizza il modello UTXO, quindi ci piace includerlo perché ci aiuta a capire i compromessi nei modelli di archiviazione della blockchain e ci aiuta a fare un confronto con Ethereum e il suo uso del modello Account.&lt;/p&gt;
&lt;h2&gt;
  
  
  Le transazioni
&lt;/h2&gt;

&lt;p&gt;Il miglior punto di partenza, prima di esaminare come le blockchain tengono traccia dei saldi degli utenti, è il luogo in cui i saldi degli utenti hanno inizio: la transazione. Esploriamo con la seguente domanda:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Di cosa abbiamo bisogno in una transazione?&lt;/strong&gt;&lt;br&gt;
Principalmente, di 3 cose:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;importo&lt;/strong&gt;: l'importo da inviare a qualcuno&lt;br&gt;
2) &lt;strong&gt;pagante&lt;/strong&gt;: la persona che invia l'importo del trasferimento&lt;br&gt;
3) &lt;strong&gt;beneficiario&lt;/strong&gt;: la persona che riceve l'importo del trasferimento.&lt;/p&gt;

&lt;p&gt;Dal momento che lavoriamo in sistemi basati su una crittografia molto sicura, abbiamo bisogno di un'altra cosa per completare tutto ciò che è necessario per una transazione blockchain di successo: l'autorizzazione del pagante. Una sorta di autorizzazione non falsificabile fornita dall'iniziatore della transazione.&lt;br&gt;
Questo quarto elemento finirebbe per essere la firma digitale, che è fondamentalmente un hash estremamente difficile da replicare se non si dispone degli input corretti - in questo caso, le chiavi private di un utente. Senza le chiavi private, non è possibile autorizzare un pagamento. L'unico modo per farlo sarebbe quello di "hackerare" la crittografia di base, cosa praticamente impossibile.&lt;/p&gt;


&lt;h2&gt;
  
  
  Qual è lo scopo di una transazione?
&lt;/h2&gt;

&lt;p&gt;Cambiare lo stato di un utente! Se Alice invia a Bob 5 $DAI, il saldo $DAI di Alice dovrebbe andare a -5, quello di Bob a +5. La transazione di Alice è responsabile della modifica dello stato dei loro saldi. La modifica dello stato è estremamente importante nelle blockchain (che sono tipicamente reti basate sulle transazioni!), quindi tenetelo a mente!&lt;/p&gt;

&lt;p&gt;Bitcoin, Ethereum e le normali banche si affidano a modelli basati sulle transazioni per tenere traccia dei saldi degli utenti. Diamo un'ulteriore occhiata qui di seguito...&lt;/p&gt;
&lt;h2&gt;
  
  
  Modello basato sul conto
&lt;/h2&gt;

&lt;p&gt;Se avete un conto corrente bancario, conoscete bene questo modello per tenere traccia dei saldi degli utenti. Il modello basato sui conti è proprio questo: conti. Tiene traccia dei saldi degli utenti in base allo stato generale del loro conto, senza tenere traccia di ciò che costituisce il saldo stesso. In altre parole, un libro mastro basato sui conti segnerebbe una voce come questa:&lt;/p&gt;

&lt;p&gt;Acct #12345 -&amp;gt; Nome: Rick Sanchez -&amp;gt; Saldo: 142,62 dollari&lt;br&gt;
Notate come lo stato del conto sia mantenuto ad un livello molto alto? Il saldo del conto di Rick è un importo in dollari e centesimi e basta. Non vengono fornite ulteriori informazioni sulla ripartizione del saldo, ad esempio: 142,62 dollari corrispondono a una banconota da 100 dollari, una banconota da 20 dollari, due banconote da 10 dollari, otto quarti di dollaro, cinque monete, due monetine e due penny. Quando Rick si reca al bancomat e preleva dal suo saldo, lo riceve in qualsiasi banconota + spiccioli che la banca ha a disposizione, non negli spiccioli esatti che sono serviti per formare il saldo.&lt;/p&gt;

&lt;p&gt;Come si presenta una transazione in un modello basato sul conto?&lt;br&gt;
Alice ha un saldo totale di 60 dollari&lt;br&gt;
Bob ha un saldo totale di 20 dollari&lt;br&gt;
Bob invia ad Alice 5 dollari&lt;br&gt;
Al saldo di Bob vengono sottratti 5 dollari, se il saldo rimanente è maggiore di 0 si procede, altrimenti si torna indietro&lt;br&gt;
Il saldo di Alice viene sommato a 5 dollari&lt;br&gt;
Il libro mastro viene contrassegnato da entrambe le parti per aggiornare i saldi totali e questa è la fine della transazione in un modello basato sui conti.&lt;br&gt;
Questo potrebbe sembrare strano. Perché dovremmo tenere traccia di questi dettagli per qualcosa di così semplice come un saldo totale? Vediamo un modello per la conservazione dei saldi degli utenti che include questa funzione: il modello UTXO.&lt;/p&gt;
&lt;h2&gt;
  
  
  Modello basato su UTXO
&lt;/h2&gt;

&lt;p&gt;Ethereum utilizza il modello basato sugli account, mentre Bitcoin utilizza gli UTXO (acronimo di Unspent Transaction Outputs) per tenere traccia dello stato e dei saldi degli utenti.&lt;/p&gt;

&lt;p&gt;Il modello UTXO è molto diverso dal modello basato sui conti. È un po' più complesso, soprattutto perché non è un'interfaccia familiare come il modello del conto! Tuttavia, presenta alcune caratteristiche interessanti...&lt;/p&gt;


&lt;h2&gt;
  
  
  Note importanti sugli UTXO:
&lt;/h2&gt;

&lt;p&gt;1) Tutti gli UTXO non sono fungibili (curiosità: la prima raccolta NFT in assoluto è stata... Bitcoin!).&lt;br&gt;
2) Per spendere un UTXO, è necessario fare riferimento a quello specifico UTXO. Gli UTXO di un utente sono sparsi in blocchi.&lt;/p&gt;

&lt;p&gt;3) Una volta che un UTXO viene "consumato", qualsiasi resto della transazione crea nuovi UTXO che rappresentano gli importi del cambiamento.&lt;br&gt;
4) Un UTXO, spesso chiamato "moneta", può essere speso una sola volta. Non è possibile spendere due volte!&lt;br&gt;
5) In Bitcoin, a ogni UTXO è associato uno script. Gli script sono sostanzialmente un codice programmato che ogni UTXO memorizza. Di solito contengono le condizioni per sbloccare l'UTXO per ulteriori spese. &lt;/p&gt;


&lt;h2&gt;
  
  
  Modello di conto vs UTXO
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wAX66_TZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z3hkfy3nfhjbv99hkwyv.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wAX66_TZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z3hkfy3nfhjbv99hkwyv.PNG" alt="UTXO vs ACCOUNTS" width="880" height="246"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusione
&lt;/h2&gt;

&lt;p&gt;Decidere quale modello adottare è un gioco di compromessi progettuali. Ethereum utilizza il modello delle transazioni basato sugli account, che deve essere più flessibile per tenere conto dei numerosi elementi di stato in movimento nel sistema. Bitcoin utilizza gli UTXO, in quanto è una rete progettata appositamente per essere il più semplice e senza stato possibile.&lt;/p&gt;


&lt;h2&gt;
  
  
  (UTXO) - Uscite di transazione non spese
&lt;/h2&gt;

&lt;p&gt;Bitcoin utilizza gli Output di transazione non spesi per gestire la proprietà delle monete da parte degli utenti. Ciò si contrappone al modello basato sugli account utilizzato da Ethereum, che tiene traccia dei saldi di determinati indirizzi.&lt;/p&gt;

&lt;p&gt;Consideriamo un paio di esempi. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esempio UTXO 1&lt;/strong&gt;&lt;br&gt;
Bob gestisce un minatore Bitcoin. Calcola con successo un blocco e si ricompensa con 12,5 BTC secondo le regole di emissione. Questo è un nuovissimo Unspent Transaction Output (UTXO) che Bob ha introdotto nel sistema.&lt;/p&gt;

&lt;p&gt;Supponiamo ora che Bob voglia inviare ad Alice 6,0 BTC. Può farlo utilizzando il suo UTXO con 12,5 BTC. Ma, aspettate, Bob non vuole inviare ad Alice 12,5 BTC! Come gestire il resto? &lt;/p&gt;

&lt;p&gt;Si scopre che Bitcoin consente di designare più uscite per ogni transazione. In questa particolare transazione, creeremo un UTXO di 6,0 BTC per Alice e un altro UTXO di 6,5 BTC per Bob (il resto). Quindi, contrassegneremo l'UTXO di 12,5 BTC come speso, poiché è stato utilizzato come ingresso per la transazione. Ottimo! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esempio UTXO 2&lt;/strong&gt;&lt;br&gt;
Una cosa che può accadere spesso quando si utilizza questo modello è che gli utenti si ritrovino con molti piccoli UTXO. Man mano che Alice effettua transazioni con la rete, l'UTXO si frammenta in uscite più piccole, finché non le rimangono 3 UTXO del valore di 1,0 BTC, 1,5 BTC e 0,8 BTC.&lt;/p&gt;

&lt;p&gt;Supponiamo che Alice voglia acquistare qualcosa per 3,0 BTC. Può farlo specificando diversi input alla transazione. Può inserire tutti e tre i suoi UTXO come input nella transazione per un totale di 3,3 BTC. Dopo l'esecuzione della transazione, riceverà un nuovo UTXO di 0,3 BTC e i suoi input precedenti saranno tutti contrassegnati come spesi.&lt;/p&gt;

&lt;p&gt;Ok, per ora gli esempi sono sufficienti! Impariamo da soli con&lt;br&gt;
alcuni esercizi di coding.&lt;/p&gt;



&lt;p&gt;Ora è il momento di creare un oggetto per i Transaction Outputs (TXO).&lt;/p&gt;

&lt;p&gt;Utilizzando un Bitcoin Block Explorer è possibile cercare i TXO sulla rete reale. Se volessimo cercare gli UTXO per un particolare indirizzo, per esempio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blockchain.info/unspent?active=1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"&gt;https://blockchain.info/unspent?active=1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il valore dopo active= è un indirizzo. Questo particolare indirizzo è quello che Satoshi ha usato quando ha estratto il primo blocco di Bitcoin.&lt;/p&gt;

&lt;p&gt;Completiamo il metodo constructor e i metodi di spesa (&lt;code&gt;spend&lt;/code&gt;) per la classe TXO nel file TXO.js.&lt;/p&gt;

&lt;p&gt;Il costruttore deve memorizzare i valori che gli vengono passati nelle proprietà con lo stesso nome. Dovrebbe anche creare una proprietà spent e impostarla come predefinita su &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
La funzione spend deve impostare la proprietà spent su true. Ad esempio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TXO {
    constructor(owner, amount) {
        this.owner = owner;
        this.amount = amount;
        this.spent = false;
    }
    spend() {
        this.spent = true;
    }
}
const txo = new TXO("1FNv3tXLkejPBYxDHDaZz6ENNz3zn3G4GM", 10);
console.log("Owner address: ", txo.owner); // uguale a 1FNv3tXLkejPBYxDHDaZz6ENNz3zn3G4GM
console.log("Amount: ", txo.amount); //uguale a 10
console.log("IsSpent", txo.spent); // uguale a false
txo.spend(); // funzione di spesa della somma 
console.log("IsSpent", txo.spent); //uguale a true
module.exports = TXO;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si noti come spent sia inizialmente falso quando creiamo il nuovo TXO. Dopo aver invocato la funzione spend, spent viene impostato a true.&lt;/p&gt;




&lt;h2&gt;
  
  
  Le transazioni
&lt;/h2&gt;

&lt;p&gt;Le transazioni sulla rete Bitcoin possono avere molti ingressi e molte uscite.&lt;/p&gt;

&lt;p&gt;Si può dare un'occhiata a questa transazione Bitcoin per vedere un esempio di transazione con molte uscite.&lt;/p&gt;

&lt;p&gt;Questo, combinato con un sistema di scripting su ogni transazione, permette agli utenti Bitcoin di impegnarsi in accordi finanziari più complessi rispetto al semplice invio di denaro da parte di un individuo all'altro.&lt;/p&gt;

&lt;p&gt;Per una transazione media, lo script richiede semplicemente che i nuovi UTXO possano essere spesi solo dall'indirizzo associato.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obiettivo? Garantire che gli input siano UTXO.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ora, introduciamo un nuovo file &lt;code&gt;Transaction.js.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nel costruttore della transazione vengono passati due argomenti: &lt;code&gt;inputUTXO&lt;/code&gt; e &lt;code&gt;outputUTXO&lt;/code&gt;. Entrambi gli oggetti sono array contenenti istanze di output della transazione.&lt;/p&gt;

&lt;p&gt;Memorizziamo &lt;code&gt;inputUTXO&lt;/code&gt; e &lt;code&gt;outputUTXO&lt;/code&gt; nell'oggetto transazione.&lt;br&gt;
Nella funzione &lt;code&gt;execute&lt;/code&gt; faremo solo una cosa per ora: assicurarci che nessuno degli &lt;code&gt;inputUTXO&lt;/code&gt; sia già stato speso. Non possiamo permettere che i TXO vengano spesi due volte!&lt;br&gt;
Lanceremo un errore in &lt;code&gt;execute&lt;/code&gt; se un TXO di input è già stato speso.&lt;br&gt;
La terminologia tra UTXO e TXO può talvolta creare confusione. &lt;br&gt;
&lt;strong&gt;Ricordate che un TXO è solo la nomenclatura di un UTXO già speso!&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

class Transaction {
    constructor(inputUTXOs, outputUTXOs) {
        this.inputUTXOs = inputUTXOs;
        this.outputUTXOs = outputUTXOs;
    }
    execute() {
        for (let utxo of this.inputUTXOs) {
            if (utxo.spent) {
                throw "UTXO already spent";
            }
        }
    }
}

module.exports = Transaction;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Ingressi e uscite
&lt;/h2&gt;

&lt;p&gt;Con una moltitudine di UTXO di ingresso e di uscita consentiti in ogni transazione, esistono molte possibilità di scambio.&lt;/p&gt;

&lt;p&gt;Il software del portafoglio Bitcoin a volte sceglie di includere molti UTXO di ingresso solo per aggregarli in un UTXO più grande da inviare al proprietario.&lt;/p&gt;

&lt;p&gt;Ad esempio, se si dispone di cinque UTXO, ciascuno con un importo di 0,1 BTC, il portafoglio potrebbe scegliere di combinarli in 0,5 BTC nella transazione successiva. La magia dietro le quinte :)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;La parte importante è assicurarsi che il valore totale degli UTXO in ingresso sia sufficiente a coprire l'importo totale degli UTXO in uscita.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Il nostro obiettivo: garantire un ingresso sufficiente.&lt;/p&gt;

&lt;p&gt;Assicuriamoci che gli UTXO di input abbiano un valore totale sufficiente a coprire il valore totale degli UTXO di output.&lt;br&gt;
Se il valore totale degli ingressi è inferiore al valore totale delle uscite, lanceremo un errore nella funzione &lt;code&gt;execute&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Transaction {
    constructor(inputUTXOs, outputUTXOs) {
        this.inputUTXOs = inputUTXOs;
        this.outputUTXOs = outputUTXOs;
    }
    execute() {
        let totalInput = 0;
        let totalOutput = 0;
        for (let utxo of this.inputUTXOs) {
            if (utxo.spent) {
                throw "UTXO già spesi";
            }
            totalInput += utxo.amount;
        }
        for (let utxo of this.outputUTXOs) {
            totalOutput += utxo.amount;
        }

        if (totalInput &amp;lt; totalOutput) {
            throw new Error("Non hai abbastanza fondi da spendere");
        }
    }
}

module.exports = Transaction;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Riuscita delle transazioni
&lt;/h2&gt;

&lt;p&gt;Quando una transazione ha successo e viene inserita nella blockchain, gli UTXO in uscita diventano nuovi TXO pronti per essere spesi. Gli UTXO in entrata devono essere contrassegnati come spesi, per garantire che non vengano spesi di nuovo :)&lt;/p&gt;

&lt;p&gt;Dopotutto, lo scopo della blockchain è proprio quello di risolvere il problema della doppia spesa. &lt;/p&gt;

&lt;p&gt;Qui il nostro obiettivo è contrassegnare gli input come spesi.&lt;br&gt;
Se non vengono innescati errori durante la funzione di esecuzione della transazione, questa ha avuto successo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Transaction {
    constructor(inputUTXOs, outputUTXOs) {
        this.inputUTXOs = inputUTXOs;
        this.outputUTXOs = outputUTXOs;
    }
    execute() {
        let totalInput = 0;
        let totalOutput = 0;
        for (let utxo of this.inputUTXOs) {
            if (utxo.spent) {
                throw "UTXO già spesi";
            }
            totalInput += utxo.amount;
        }
        for (let utxo of this.outputUTXOs) {
            totalOutput += utxo.amount;
        }

        if (totalInput &amp;lt; totalOutput) {
            throw new Error("Non hai abbastanza fondi da spendere");
        }
        for (let utxo of this.inputUTXOs) {
            utxo.spent = true;
        }
    }
}

module.exports = Transaction;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  COMMISSIONI DI MINING
&lt;/h2&gt;

&lt;p&gt;A questo punto ci chiediamo perché nel terzo step abbiamo richiesto solo che la quantità totale di input sia superiore alla quantità totale di output.&lt;/p&gt;

&lt;p&gt;Non dovremmo mostrare un errore anche quando la quantità in uscita risulta inferiore? &lt;/p&gt;

&lt;p&gt;No! In realtà, il resto viene dato al miner. &lt;/p&gt;

&lt;p&gt;Questa è una scelta progettuale del sistema Bitcoin. Si tratta della cosiddetta &lt;strong&gt;tassa di transazione&lt;/strong&gt;, o &lt;em&gt;transaction fee&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;La commissione di transazione può contribuire ad accelerare la richiesta. Un miner è molto più propenso a includere la vostra transazione nel blocco successivo se includete un bel premio da riscuotere! &lt;/p&gt;

&lt;p&gt;Bitcoin ha un'offerta controllata. Per un periodo di tempo limitato, ogni blocco prevede una ricompensa per il miner. A un certo punto, questo si interromperà e l'unica ricompensa per il miner diventerà la commissione di transazione.&lt;/p&gt;

&lt;p&gt;Il nostro obiettivo: calcolare la commissione!&lt;br&gt;
Alla fine della funzione execute, calcoliamo la tariffa come somma di tutti gli input meno la somma di tutti gli output.&lt;/p&gt;

&lt;p&gt;Dato che lanciamo un errore se gli input sono insufficienti, questo numero dovrebbe essere almeno pari a zero. Ogni volta che le uscite sono inferiori, il compenso deve essere positivo.&lt;br&gt;
Memorizziamo perciò l'importo della tassa in una proprietà chiamata &lt;code&gt;fee&lt;/code&gt; sulla transazione stessa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const minerFee = totalInput - totalOutput;
        if (minerFee &amp;lt; 0) {
            throw "Miner fee inferiore a zero. Il miner non pagherà per te lol";
        }
        this.fee = minerFee;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Nel prossimo post vedremo nel dettaglio le strutture dati ad albero e i principali metodi per interagire con queste strutture.&lt;/p&gt;

</description>
      <category>utxo</category>
      <category>bitcoin</category>
      <category>web3</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Blockchain e struttura dei dati</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Mon, 09 Jan 2023 03:07:31 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/blockchain-e-struttura-dei-dati-gno</link>
      <guid>https://dev.to/gianmarcodev/blockchain-e-struttura-dei-dati-gno</guid>
      <description>&lt;p&gt;In questo post impareremo a conoscere i blocchi, gli hash e il modo in cui i blocchi sono collegati tra loro per creare una struttura blockchain crittograficamente sicura.&lt;/p&gt;

&lt;p&gt;L'implementazione della blockchain risultante avrà un aspetto simile a questo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqat8gfz2nz1w8qd4lip9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqat8gfz2nz1w8qd4lip9.png" alt="Rappresentazione semplificativa dei blocchi" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ogni blocco contiene un &lt;strong&gt;Hash precedente&lt;/strong&gt; che rappresenta il contenuto del suo predecessore, e i dati (nello specifico, il payload) che sono le informazioni memorizzate nel blocco.&lt;/p&gt;




&lt;h2&gt;
  
  
  DEFINIZIONE
&lt;/h2&gt;

&lt;p&gt;Blockchain è effettivamente un nome appropriato: si tratta infatti di una catena di blocchi. Ogni blocco contiene dati transazionali, alcuni metadati che descrivono il blocco stesso e un collegamento al blocco precedente. Questi componenti vengono inseriti in una funzione di hash per creare una sequenza unica di bit che rappresenta il blocco.&lt;/p&gt;

&lt;p&gt;Il primo blocco di una blockchain viene spesso chiamato &lt;strong&gt;blocco genesi&lt;/strong&gt;. Il blocco ha solitamente un indice pari a 0 - questa è l'informatica, dove sappiamo ormai che tutto è indicizzato a 0 :) &lt;/p&gt;

&lt;p&gt;L'aggiunta dell'hash del blocco precedente (&lt;code&gt;previousHash&lt;/code&gt;) al nuovo blocco creerà un collegamento tra i due.&lt;/p&gt;

&lt;h2&gt;
  
  
  FUNZIONI DI HASH
&lt;/h2&gt;

&lt;p&gt;Le funzioni hash sono utilizzate per prendere in input dati di qualsiasi dimensione e restituire una serie unica di bit di dimensioni specifiche che rappresentano i dati originali.&lt;/p&gt;

&lt;p&gt;Una funzione hash crittografica ideale può, dato un qualsiasi input, restituire un output coerente ma apparentemente casuale.&lt;/p&gt;

&lt;p&gt;È importante che l'output sia coerente, in modo da poter contare sul fatto di inserire gli stessi input e ricevere lo stesso output.&lt;/p&gt;

&lt;p&gt;È anche importante che la casualità sia abbastanza forte da rendere impossibile ricostruire l'input dall'output. In questo modo, sappiamo che è a prova di manomissione.&lt;/p&gt;

&lt;p&gt;Ad esempio, l'algoritmo SHA256 accetta un input come "Music" e restituisce un output coerente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const hash = SHA256("Music");
console.log( hash.toString() ); // b12595…1cbe7e abbreviato per comodita'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il log è abbreviato, in realtà è lungo 64 caratteri esadecimali. SHA256 produce 256 bit. Poiché un carattere esadecimale richiede 4 bit, ci sono 64 caratteri esadecimali in un hash SHA256.&lt;/p&gt;

&lt;p&gt;Se invece il mio input fosse "music" in minuscolo, il risultato sarebbe completamente diverso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const hash = SHA256("music");
console.log( hash.toString() ); // ec4f2d...56f1cb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Questi risultati hash sono apparentemente casuali rispetto ai loro input: "Music" e "music". Sono anche coerenti: inserendo questi input si ottengono sempre gli stessi output. Per questi motivi sha256 è una funzione hash crittografica ideale e viene spesso utilizzata nei programmi crittografici.&lt;/p&gt;




&lt;h2&gt;
  
  
  Crypto-JS
&lt;/h2&gt;

&lt;p&gt;La libreria crypto-js ci fornisce diverse utilità crittografiche da poter implementare scrivendo codice in Javascript. In particolare, il metodo SHA256 di questa libreria è un'implementazione dell'algoritmo SHA256 progettato dall'NSA.&lt;/p&gt;

&lt;p&gt;Questa funzione accetta come argomento qualsiasi stringa, indipendentemente dalla sua dimensione, e la sottopone ad hash in un array di 256 bit. Se chiamiamo &lt;code&gt;toString()&lt;/code&gt; sull'oggetto restituito, riceveremo una stringa esadecimale di 64 caratteri.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esadecimale&lt;/strong&gt;&lt;br&gt;
Si noterà che gli output mostrati consistono in un insieme di caratteri che vanno da &lt;em&gt;a&lt;/em&gt; a &lt;em&gt;f&lt;/em&gt; e da &lt;em&gt;0&lt;/em&gt; a &lt;em&gt;9&lt;/em&gt;. Si tratta di caratteri esadecimali: è ormai consuetudine utilizzare l'esadecimale quando si visualizza un hash.&lt;/p&gt;

&lt;p&gt;Spesso si incontra anche un hash con un prefisso 0x davanti. Questo prefisso significa che viene utilizzata la notazione esadecimale. Quindi, se si vede una stringa di caratteri "0x123abc", lo "0x" indica l'uso di esadecimali e il valore della stringa è in realtà solo la parte successiva, ovvero "123abc".&lt;/p&gt;

&lt;p&gt;Per il file di prova che troverete qui sotto, si noterà che l'hash del blocco viene testato dall'espressione regolare (regex) /^[0-9A-F]{64}$/i. L'espressioneSta semplicemente verificando che si tratti di un output esadecimale di 64 caratteri.&lt;/p&gt;

&lt;p&gt;Le espressioni regolari possono aiutare a definire un modello di ricerca per i dati in ingresso. Potete trovare maggiori informazioni sulle &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions" rel="noopener noreferrer"&gt;espressioni regolari su MDN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perché 64 caratteri esadecimali?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Un bit può rappresentare due valori: 0 e 1. Due bit possono rappresentare quattro valori: 00, 01, 10 e 11. Quattro bit possono rappresentare 16 valori da 0000 a 1111. Possiamo mappare ciascuno di questi valori con un carattere dell'alfabeto esadecimale, poiché contiene 16 caratteri :) &lt;/p&gt;

&lt;p&gt;Poiché SHA256 produce 256 bit, dividiamo questo valore per il numero di bit che rappresentano un carattere esadecimale (4) per ottenere 64 caratteri.&lt;/p&gt;

&lt;p&gt;Guardiamo ora come implementare un modello semplificativo tramite JS. &lt;/p&gt;



&lt;p&gt;In un file che chiameremo &lt;em&gt;Block.js&lt;/em&gt;, abbiamo una classe &lt;code&gt;Block&lt;/code&gt;. Utilizzando la funzione &lt;code&gt;SHA256&lt;/code&gt; della libreria Crypto JS, otteniamo un hash valido nella funzione &lt;code&gt;toHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Iniziamo con l'aggiungere dati alla funzione di hash:&lt;br&gt;
In questo modo si assicura che l'hash del blocco sia legato al suo contenuto.&lt;/p&gt;

&lt;p&gt;Quando si crea un nuovo blocco, i dati vengono passati al suo costruttore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const block = new Block("Alice ha inviato a Bob 1 BTC");

console.log( block.data ); // Alice ha inviato a Bob 1 BTC

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Come mostrato sopra, aggiungiamo una proprietà &lt;code&gt;data&lt;/code&gt; al blocco.&lt;/p&gt;

&lt;p&gt;Successivamente, aggiungiamo un costruttore alla nostra classe &lt;code&gt;Block&lt;/code&gt; che prenda un parametro &lt;code&gt;data&lt;/code&gt; e lo assegni a &lt;code&gt;this.data&lt;/code&gt;&lt;br&gt;
Una volta aggiunti i dati al blocco, li utilizziamo per calcolare l'hash del blocco nella funzione &lt;code&gt;toHash&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const SHA256 = require("crypto-js/sha256");

// 
class Block {
  constructor(data) {
    this.data = data;
  }

  // Ritorniamo l'hash di data
  toHash() {
    return SHA256(this.data + this.previousHash);
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Ora creiamo un nuovo file: &lt;code&gt;Blockchain.js&lt;/code&gt; :) &lt;/p&gt;

&lt;p&gt;Il file si concentrerà sull'aggiunta del primo blocco alla nostra nuova classe &lt;code&gt;Blockchain&lt;/code&gt;. Il primo blocco viene spesso chiamato blocco Genesi.&lt;/p&gt;

&lt;p&gt;Il file Blockchain.js contiene la classe &lt;code&gt;Blockchain&lt;/code&gt; che al suo interno contiene un array chiamato &lt;code&gt;chain&lt;/code&gt;. Aggiungiamo il blocco Genesi a questo array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Block = require('./Block');

class Blockchain {
    constructor() {
        this.chain = [new Block()];
    }
}

module.exports = Blockchain;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creiamo quindi un nuovo blocco nel costruttore di Blockchain e aggiungiamo l'array &lt;em&gt;chain&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Funzione AddBlock&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Creiamo una funzione addBlock nella nostra classe Blockchain.&lt;/p&gt;

&lt;p&gt;Questa funzione accetta un nuovo blocco e lo aggiunge all'array &lt;code&gt;chain&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;addBlock(block) {
    // Aggiunge il previousHash al nuovo blocco, collegandoli.

    block.previousHash = this.chain[this.chain.length - 1].toHash();
    this.chain.push(block);
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ora dovremmo avere sia il blocco genesi che il nuovo blocco.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Funzione di Linking dei blocchi&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;È il momento di aggiungere un altro input cruciale al calcolo dell'hash del nostro blocco: l'hash del blocco precedente nella catena.&lt;br&gt;
In questo modo si crea una catena in cui qualsiasi modifica ai dati di un blocco precedente si ripercuote su ogni blocco successivo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ivt3io0amk6vogzh2b1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ivt3io0amk6vogzh2b1.png" alt="Linking example" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Per collegare i blocchi occorre fare due cose:&lt;/p&gt;

&lt;p&gt;1) Aggiungere una proprietà previousHash a ogni blocco. Il valore di questa proprietà deve essere l'hash del blocco precedente nella catena.&lt;br&gt;
2) Utilizzare questa proprietà previousHash nel calcolo dell'hash del blocco.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Block = require("./Block");
const SHA256 = require("crypto-js/sha256");

class Blockchain {
    constructor() {
        const block = new Block("Music");
        this.chain = [block]; // genisis block
    }
    addBlock(newBlock) {
        newBlock.previousHash = this.chain[this.chain.length - 1].toHash();
        newBlock.data = "Altri dati";
        this.chain.push(newBlock);
    }
}
const blockchain = new Blockchain();
const block = new Block();

blockchain.addBlock(block);

module.exports = Blockchain;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;La Chain Validation&lt;/strong&gt;&lt;br&gt;
Le blockchain sono gestite da una rete di nodi, come dicevamo. Quando un nodo trova un nuovo blocco, trasmette la nuova versione della blockchain a tutti i suoi pari. In qualsiasi momento possono esistere più versioni della blockchain. Tuttavia, la blockchain valida più a lungo è quella accettata.&lt;/p&gt;

&lt;p&gt;Creiamo ora una funziona per validare i blocchi.&lt;/p&gt;

&lt;p&gt;Creare una funzione chiamata &lt;code&gt;isValid&lt;/code&gt; sulla nostra Blockchain che restituisca &lt;code&gt;true&lt;/code&gt; o &lt;code&gt;false&lt;/code&gt; se un blocco è rispettivamente valido o non valido.&lt;br&gt;
&lt;code&gt;isValid&lt;/code&gt; deve controllare l'integrità di ogni blocco nella sua catena, guardando il campo &lt;code&gt;previousHash&lt;/code&gt; di ogni blocco e assicurandosi che sia uguale all'hash del blocco precedente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
isValid() {
    let bool = true;

    for (let i = 0; i &amp;lt; this.chain.length - 2; i++) {
      const hashPrev = this.chain[i].toHash();
      const prevHash = this.chain[i + 1].previousHash;

      if (hashPrev.toString() != prevHash.toString()) {
        bool = false;
        break;
      }
    }

    return bool;
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;Il blocco Genesi e il Blockchain Explorer&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;È un buon momento per parlare del blocco genesi, (Genesis Block) e di Bitcoin.&lt;/p&gt;

&lt;p&gt;Guardiamo il blocco genesi di Bitcoin dall'explorer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81dytm8sh79jy9sd3xhy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81dytm8sh79jy9sd3xhy.PNG" alt="Blocco genesi, visionabile su blockchain.com" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Il numero di conferme è il numero di blocchi dal blocco genesi. Poiché il blocco genesi è il primo blocco, questo è anche l'altezza del blocco della blockchain!&lt;/p&gt;

&lt;p&gt;È interessante notare che se si guarda al nonce del blocco genesi, esso è 2.083.236.893. Se si dà un'occhiata a un blocco più recente, ad esempio il 632900, si vedrà che il nonce è in realtà molto più basso. Perché? La difficoltà non dovrebbe aumentare con la crescita della rete? &lt;/p&gt;

&lt;p&gt;Scopriamo così che il nonce del blocco è in realtà un campo di 32 bit e 2^32 fa 4.294.967.296, quindi questa è la dimensione massima di un nonce. Cosa succede quando il miner raggiunge questo punto? Può cambiare qualsiasi altra cosa nell'intestazione del blocco per aumentare la casualità. Altre proprietà includono:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Versione del software&lt;/strong&gt; - Traccia gli aggiornamenti del software Bitcoin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hash del blocco precedente&lt;/strong&gt; - Hash del blocco precedente a questo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merkle Root&lt;/strong&gt; - Non l'abbiamo ancora analizzato, è un hash che rappresenta tutte le transazioni!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp&lt;/strong&gt; - Ora approssimativa (meno di due ore nel futuro secondo le regole del consenso)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target&lt;/strong&gt; - Obiettivo di difficoltà che stabilisce quanto deve essere piccola la Proof Of Work.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>gratitude</category>
    </item>
    <item>
      <title>L'algoritmo ECDSA</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Sat, 07 Jan 2023 19:08:06 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/lalgoritmo-ecdsa-1ee3</link>
      <guid>https://dev.to/gianmarcodev/lalgoritmo-ecdsa-1ee3</guid>
      <description>&lt;h4&gt;
  
  
  &lt;em&gt;In questo post esploreremo come un algoritmo di curva ellittica, nello specifico l'algoritmo di firma digitale a curva ellittica (ECDSA), venga utilizzato sul web e come possa migliorare le prestazioni generali e la sicurezza.&lt;/em&gt;
&lt;/h4&gt;




&lt;h2&gt;
  
  
  UN PO' DI STORIA
&lt;/h2&gt;

&lt;p&gt;Quando visitiamo un sito che inizia con https:// anziché http://, il nostro browser si connette a quel sito tramite una connessione crittografata. &lt;br&gt;
Il browser verifica che il sito web sia esattamente chi che afferma di essere utilizzando la crittografia a chiave pubblica insieme ad un certificato digitale.&lt;/p&gt;

&lt;p&gt;Nella crittografia a chiave pubblica, ogni utente ha una coppia di chiavi: una chiave pubblica e una privata. Di solito si tratta di numeri scelti in modo tale da avere una relazione matematica specifica. &lt;/p&gt;

&lt;p&gt;In RSA (crittografia a chiave simmetrica), la chiave pubblica è il risultato del prodotto di due numeri primi, a cui si somma un numero più piccolo. La chiave privata è un numero correlato. &lt;/p&gt;

&lt;p&gt;In ECC (Crittografia a curva ellittica) la chiave pubblica corrisponde ad un'equazione per una curva ellittica ed un punto che si trova su quella curva. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8i6Sx3Yc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5sokeikb2346w3cwmr3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8i6Sx3Yc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5sokeikb2346w3cwmr3e.png" alt="Rappresentazione grafica" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La chiave privata associata alla chiave pubblica può essere utilizzata per creare una firma digitale per qualsiasi tipo di dati utilizzando un algoritmo di firma digitale. Questo processo solitamente implica il prelievo di un &lt;strong&gt;hash crittografico&lt;/strong&gt; dei dati e l'esecuzione di una operazione matematica su di esso utilizzando la chiave privata. Chiunque abbia la chiave pubblica può verificare che questa firma sia stata creata utilizzando sia la chiave privata, sia l'algoritmo di convalida della firma appropriato. &lt;br&gt;
La firma digitale risulta oggi uno strumento efficace in quanto consente di attestare pubblicamente qualsiasi messaggio.&lt;/p&gt;

&lt;p&gt;Un certificato per sito web di solito contiene due elementi:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Informazioni riguardanti l'identità&lt;/strong&gt;: di solito, chi possiede il certificato e per quali domini il certificato è valido.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Una chiave pubblica&lt;/strong&gt;: fornita la chiave pubblica di una coppia di chiavi, il proprietario del sito controlla e mantiene segreta la chiave privata associata a quella pubblica.&lt;/p&gt;

&lt;p&gt;Il certificato è successivamente firmato digitalmente da un'autorità di certificazione affidabile che convalida l'identità del proprietario del sito.&lt;/p&gt;

&lt;p&gt;Dall'introduzione di SSL da parte di Netscape nel 1994, i certificati per i siti web hanno di solito utilizzato una coppia di chiavi pubbliche/private basata sull'algoritmo RSA. Man mano che il protocollo SSL si e' evoluto in TLS, ad esso è stato aggiunto il supporto per diversi altri tipi algoritmi di chiave pubblica.&lt;/p&gt;


&lt;h2&gt;
  
  
  SCELTE ED UTILIZZI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6eK29mQB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33kobxpzyhiqoun76yjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6eK29mQB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33kobxpzyhiqoun76yjg.png" alt="Courtesy of @learnmeabitcoin" width="862" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sebbene ECDSA non abbia preso piede tra le applicazioni web, l'algoritmo è diventato lo schema di firma digitale scelto per tutta una serie di nuove applicazioni crittografiche non web.&lt;/p&gt;

&lt;p&gt;Bitcoin è un buon esempio di sistema che si affida a ECDSA per la sicurezza. &lt;br&gt;
Ogni indirizzo Bitcoin è costituito da un hash crittografico di una chiave pubblica ECDSA. &lt;br&gt;
La proprietà del conto Bitcoin è determinata da chi controlla la chiave privata ECDSA. Per trasferire una quantità di Bitcoin a un'altra persona, il mittente esegue una transazione, firma quella transazione con la sua chiave privata e lo invii alla blockchain Bitcoin per la sua validazione. &lt;br&gt;
In questo caso, il perno della sicurezza e della coerenza del sistema Bitcoin risiede proprio nella sicurezza delle chiavi private ECDSA.&lt;/p&gt;

&lt;p&gt;Le curve ellittiche e, in particolare, le curve ECDSA sono utilizzate per garantire la sicurezza delle applicazioni di messaggistica. Nel recente whitepaper di Apple sulla sicurezza di iOS, gli sviluppatori di Cupertino hanno riferito come utilizzino ampiamente ECDSA nell'ecosistema Apple. Due rapidi esempi: le conversazioni tramite iMessage sono firmate con ECDSA e la sincronizzazione del portachiavi iCloud si basa anch'essa su ECDSA. Sempre più tecnologie utilizzano ECDSA per la sicurezza, incluse le app di messaggistica a end-to-end criptate TextSecure e CryptoCat.&lt;/p&gt;


&lt;h2&gt;
  
  
  La grande battaglia: ECDSA vs RSA
&lt;/h2&gt;

&lt;p&gt;Perché ECDSA è l'algoritmo scelto per i nuovi protocolli quando RSA è disponibile ed è stato il gold standard per la crittografia asimmetrica dal 1977? Il motivo è che noi umani siamo più bravi a violare RSA che a violare ECC.&lt;/p&gt;

&lt;p&gt;Nello specifico, la sicurezza di una chiave dipende dalla sua dimensione e dal suo algoritmo. Alcuni algoritmi sono più facili da decifrare di altri e richiedono chiavi più grandi per lo stesso livello di sicurezza. Per decifrare una chiave RSA è necessario fattorizzare un numero grande. Purtroppo o per fortuna, nel corso degli anni, siamo diventati abbastanza bravi a fattorizzare numeri grandi e miglioriamo continuamente. &lt;br&gt;
Per decifrare una chiave ECDSA invece, diventa necessario risolvere un particolare problema, quello del &lt;strong&gt;logaritmo discreto della curva ellittica (ECDLP).&lt;/strong&gt; La comunità matematica non ha fatto grandi progressi nel migliorare gli algoritmi per risolvere questo problema da quando è stato introdotto in modo indipendente dai matematici *&lt;em&gt;Koblitz *&lt;/em&gt; e **Miller **nel 1985.&lt;/p&gt;

&lt;p&gt;Ciò significa che con ECDSA è possibile ottenere lo stesso livello di sicurezza di RSA, ma con chiavi più piccole: e le chiavi più piccole sono migliori di quelle più grandi per diversi motivi: &lt;br&gt;
1) Le chiavi più piccole sono caratterizzate da algoritmi più veloci per la generazione delle firme, perché i calcoli riguardano ovviamente numeri più piccoli. &lt;br&gt;
2) Chiavi pubbliche più piccole significano certificati più piccoli e meno dati da trasmettere per stabilire una connessione TLS. Ciò significa connessioni più veloci e tempi di caricamento più rapidi sui siti web.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.keylength.com/en/3/"&gt;Secondo le raccomandazioni di ECRYPT II&lt;/a&gt; sulla lunghezza delle chiavi, una chiave a curva ellittica a 256 bit fornisce la stessa protezione di una chiave asimmetrica a 3.248 bit. &lt;/p&gt;

&lt;p&gt;Ora effettuiamo un piccolo test.&lt;br&gt;
Sappiamo che e chiavi RSA tipiche dei certificati dei siti web sono a 2048 bit. &lt;/p&gt;

&lt;p&gt;Se confrontiamo la parte dell'handshake TLS che avviene sul server per le chiavi ECDSA a 256 bit con le chiavi RSA a 2048 bit, crittograficamente molto più deboli, otteniamo quanto segue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                            sign/s
256 bit ecdsa (nistp256)    9516.8
rsa 2048 bits               1001.8

(openssl 1.0.2 beta on x86_64 with enable-ec_nistp_64_gcc_128)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La sezione qui sopra mostra il numero di firme ECDSA e RSA possibili al secondo (sign/s). &lt;br&gt;
Come visionabile dal test effettuato, &lt;strong&gt;l'uso di un certificato ECDSA riduce il costo dell'operazione di chiave privata di di circa 9,5 volte, risparmiando in modo consistente sui cicli della CPU.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ESISTE UNA DANGER ZONE?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EenS5BU3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e26u63nkvypav71jhn92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EenS5BU3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e26u63nkvypav71jhn92.png" alt="Danger zone of ECDSA" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Possiamo essere relativamente fiduciosi sulla sicurezza matematica connessa alle ECDSA. &lt;br&gt;
La storia della crittografia ci mostra che la buona crittografia è stata ripetutamente sconfitta non a causa di una cattiva matematica, ma a causa di cattive implementazioni della buona matematica.&lt;/p&gt;

&lt;p&gt;Una particolarità interessante dell'algoritmo ECDSA è che ogni firma richiede come input alcuni dati casuali o imprevedibili. Se la fonte di casualità è prevedibile per un attaccante, questi può scoprire la chiave privata. E storicamente, hacker black-hat hanno sfruttato questa vulnerabilità in diversi casi di alto profilo.&lt;/p&gt;

&lt;p&gt;Nel 2010 ad esempio, una falla nel modo in cui venivano utilizzati i numeri casuali &lt;a href="https://www.exophase.com/20540/hackers-describe-ps3-security-as-epic-fail-gain-unrestricted-access/"&gt;in ECDSA su Playstation 3 di Sony&lt;/a&gt; ha portato alla fuga di una chiave privata. Più di recente, si è scoperto che alcuni dispositivi Android generavano in modo errato valori casuali, che ha causato un &lt;a href="https://bitcoin.org/en/alert/2013-08-11-android"&gt;massiccio furto di Bitcoin&lt;/a&gt; da dispositivi che eseguivano il software BTC sulla macchina.&lt;/p&gt;




&lt;p&gt;Esistono altri attacchi più esoterici contro specifiche implementazioni di ECDSA. &lt;br&gt;
&lt;a href="https://eprint.iacr.org/2014/161.pdf"&gt;In un paper pubblicato&lt;/a&gt; da un gruppo di ricercatori australiani e britannici, si descrive un attacco all'implementazione di ECDSA di OpenSSL per la curva secp256k1 (la specifica curva utilizzata dal protocollo Bitcoin). Fortunatamente, questo attacco non rappresenta attualmente una minaccia per i server remoti occupati.&lt;/p&gt;

&lt;p&gt;Esiste inoltre un pericolo legato alla perdita di chiavi tramite dati casuali di scarsa qualità o attacchi side channel, ma rimane una casistica gestibile con una preparazione adeguata e con una attenta attivita' di prevenzione. &lt;br&gt;
La chiave di volta sta nell'assicurare che il generatore di numeri casuali (PRNG - &lt;em&gt;pseudorandom number generator&lt;/em&gt;) del sistema abbia un'entropia sufficiente. &lt;/p&gt;

&lt;p&gt;Tale crittografia è difficile da implementare correttamente, soprattutto nel contesto di un protocollo complesso come TLS, come dimostrato da alcune famose correzioni di bug recenti. Detto questo, i vantaggi sembrano superare i rischi in questo caso.&lt;/p&gt;




</description>
      <category>ecdsa</category>
      <category>cryptography</category>
      <category>math</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Blockchain 101 - Public key cryptography</title>
      <dc:creator>Venerito Gianmarco </dc:creator>
      <pubDate>Tue, 27 Dec 2022 19:11:51 +0000</pubDate>
      <link>https://dev.to/gianmarcodev/blockchain-101-public-key-cryptography-1j6m</link>
      <guid>https://dev.to/gianmarcodev/blockchain-101-public-key-cryptography-1j6m</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;CONTEXT&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Public key cryptography is a fundamental part of modern digital security, and it plays a crucial role in ensuring the privacy and integrity of information transmitted over the internet. It allows individuals and organizations to communicate securely and authenticate the identity of users, without the need for a shared secret key.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;THE PRINCIPLE&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The basic principle behind public key cryptography is that each user has a &lt;strong&gt;pair of keys&lt;/strong&gt; - a public key and a private key - that are mathematically related. The public key is used to encrypt messages, while the private key is used to decrypt them. This means that anyone can use a user's public key to send an encrypted message, but only the user with the corresponding private key can decrypt and read the message.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ECDSA&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One important algorithm used in public key cryptography is the Elliptic Curve Digital Signature Algorithm (ECDSA). ECDSA is a cryptographic algorithm used to generate digital signatures, which are used to verify the authenticity of a message or document. It is based on the mathematical concept of elliptic curves and provides a high level of security.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ELLIPTIC CURVES&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Elliptic curves are a type of mathematical curve that can be defined over a finite field, such as the set of integers or the set of points on a plane. They have a number of interesting properties that make them well-suited for use in cryptography.&lt;/p&gt;

&lt;p&gt;One of the key properties of elliptic curves is that they allow for the efficient generation of a large number of points that are very difficult to distinguish from each other. This makes them useful for &lt;strong&gt;generating cryptographic keys&lt;/strong&gt;, as it ensures that the keys are effectively random and cannot be easily guessed or derived by an attacker.&lt;/p&gt;

&lt;p&gt;In addition to their key generation capabilities, elliptic curves also allow for the &lt;strong&gt;efficient implementation&lt;/strong&gt; of various cryptographic algorithms, such as the Elliptic Curve Digital Signature Algorithm (ECDSA). &lt;/p&gt;

&lt;p&gt;The security of ECDSA and other algorithms based on elliptic curves derives from the difficulty of solving certain mathematical problems that are related to elliptic curves. These problems are believed to be computationally infeasible to solve, even with the use of powerful computers, making it very difficult for an attacker to break the encryption or forge a digital signature.&lt;/p&gt;

&lt;p&gt;When users want to send a message, they use their private key to create a digital signature. This signature is then attached to the message and sent along with it. When the recipient receives it, they use the sender's public key to verify the signature and confirm that the message is authentic. If the signature is valid, it indicates that the message was indeed sent by the user with the corresponding private key.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;SIGNING A MESSAGE WITH secp256k1&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With secp256k1, the process of signing a message includes returning the signature along with the recovery bit. This allows us to recover the public key from the signature, enabling a blockchain node to identify the address that authenticated a given transaction based on the signature. This is a crucial aspect of blockchain transactions, as they not only demonstrate the intent of the signer but also authenticate their identity through public key cryptography.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;noble-secp256k1: A JS LIBRARY&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The noble-secp256k1 library (&lt;a href="https://github.com/paulmillr/noble-secp256k1#signmsghash-privatekey" rel="noopener noreferrer"&gt;official Github here&lt;/a&gt;) is a JavaScript implementation of the secp256k1 elliptic curve cryptography algorithm. &lt;br&gt;
It allows users to sign and verify messages, recover public keys from signatures, and transform public keys into Ethereum addresses. The library is designed to be fast and easy to use, with a simple API and no dependencies. It is tested and well-documented, with comprehensive documentation and examples provided. Overall, the noble-secp256k1 library is a reliable and convenient tool for working with secp256k1 in JavaScript applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Recovering the public key WITH secp256k1&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Recovering the public key from a signature is an important aspect of public key cryptography. It allows blockchain nodes to identify the user who signed a particular transaction, and to verify the authenticity of the transaction.&lt;/p&gt;

&lt;p&gt;To recover the public key from a signature, you will need to have the signature itself, along with the recovery bit. The recovery bit is a piece of information included with the signature that allows the public key to be recovered. It is a single bit that indicates which of the two possible public keys corresponds to the private key used to generate the signature.&lt;/p&gt;

&lt;p&gt;Once you have the signature and recovery bit, you can use the Elliptic Curve Digital Signature Algorithm (ECDSA) to reverse the process and extract the public key. This involves solving a mathematical problem related to the elliptic curve used in the ECDSA algorithm.&lt;/p&gt;

&lt;p&gt;Here's a code example in JavaScript that demonstrates how to recover the public key from a signature using the noble-secp256k1 library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const secp256k1 = require('noble-secp256k1');

const signature = '...'; // The signature, including the recovery bit
const messageHash = '...'; // The hash of the message that was signed

// Use the recover function to extract the public key from the signature
const publicKey = secp256k1.recover(messageHash, signature);

console.log(publicKey); // Outputs the public key in hexadecimal format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code explanation
&lt;/h3&gt;

&lt;p&gt;This code defines an async function called recoverKey that takes a message, signature, and recovery bit as input, and uses the recover function from the secp256k1 library to extract the public key. The function returns the public key in hexadecimal format.&lt;/p&gt;

&lt;p&gt;The code also includes a test of the function, using sample values for the message, signature, and recovery bit. When the function is called, it returns the public key, which is then logged to the console.&lt;/p&gt;

&lt;p&gt;Keep in mind that this code assumes you have already installed the secp256k1 library and imported it into your project. You can install it using npm by running npm install secp256k1.&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
  </channel>
</rss>
