Utreexo: compressing loba UTXO Bitcoin

Utreexo: compressing loba UTXO Bitcoin

Héy Habr!

Dina jaringan Bitcoin, sadaya titik, ngaliwatan konsensus, satuju dina susunan UTXOs: sabaraha koin sadia pikeun belanja, ka saha persis, sarta dina kaayaan naon. The UTXO set teh set minimum data diperlukeun pikeun titik validator, tanpa nu titik moal bisa pariksa validitas transaksi asup jeung blok ngandung aranjeunna.

Dina hal ieu, usaha keur dilakukeun dina sagala cara mungkin pikeun ngurangan representasi disimpen tina set ieu, pikeun niiskeun eta tanpa kaleungitan jaminan kaamanan. Nu leuwih leutik volume data disimpen, nu handap sarat spasi disk tina titik validator, nu ngajadikeun launching titik validator mirah, ngidinan Anjeun pikeun dilegakeun jaringan jeung kukituna ngaronjatkeun stabilitas jaringan.

Dina pos ieu kami bakal masangkeun prototipe Rust tina proposal panganyarna ti ko-panulis Kertas Jaringan kilat, Thaddeus Dryja - Utreexo: a accumulator basis hash dinamis dioptimalkeun pikeun set Bitcoin UTXO, nu ngidinan ngurangan syarat spasi disk pikeun titik validator.

Naon masalahna?

Salah sahiji masalah perennial Bitcoin nyaéta skalabilitas na. Gagasan "bank anjeun sorangan" ngabutuhkeun pamilon jaringan pikeun nyimpen rékaman sadaya dana anu sayogi dianggo. Dina Bitcoin, dana sadia dinyatakeun salaku susunan kaluaran unspent - a UTXO-set. Sanaos ieu sanés perwakilan anu intuitif, éta mangpaat dina hal kinerja palaksanaan pikeun perwakilan dimana unggal "dompét" ngagaduhan "kasaimbangan" salaku éntri anu misah, sareng ogé nambihan privasi (contona. CoinJoin).

Penting pikeun ngabédakeun antara sajarah transaksi (anu disebut blockchain) sareng kaayaan sistem ayeuna. sajarah transaksi Bitcoin ayeuna nyokot ngeunaan 200 GB spasi disk, sarta terus tumuwuh. Sanajan kitu, kaayaan sistem leuwih leutik, dina urutan 4 GB, sarta ngan nyokot kana akun kanyataan yén batur ayeuna owns koin. Volume data ieu ogé naek kana waktu, tapi dina laju teuing laun malah sakapeung condong ngurangan (tingali CDPV).

klien lampu (SPVs) jaminan kaamanan dagang pikeun kamampuhan pikeun nyimpen euweuh kaayaan minimum (UTXO-set) lian ti kenop swasta.

UTXO jeung UTXO-set

UTXO (Kaluaran Transaksi Unspent) nyaéta kaluaran urus unspent, titik ahir perjalanan unggal Satoshi ditransfer dina transaksi. Outputs unspent jadi inputs tina transaksi anyar sahingga spent (ngabahekeun) sarta dikaluarkeun tina UTXO-set.

UTXOs anyar sok dijieun ku transaksi:

  • transaksi coinbase tanpa inputs: nyieun UTXOs anyar nalika panambang ngaluarkeun koin
  • transaksi biasa: nyieun UTXOs anyar bari méakkeun set tangtu UTXOs aya

Prosés gawé bareng UTXO:
Utreexo: compressing loba UTXO Bitcoin

Dompét cacah jumlah koin sadia pikeun belanja (kasaimbangan) dumasar kana jumlah UTXO sadia pikeun dompét ieu belanja.

Unggal titik validator, pikeun nyegah usaha méakkeun ganda, kudu ngawas susunan всех UTXO nalika mariksa masing-masing transaksi masing-masing Blok.

Node kedah gaduh logika:

  • Tambahan pikeun UTXO-set
  • Hapusan tina UTXO-set
  • Mariksa ayana UTXO tunggal dina susunan

Aya cara pikeun ngurangan sarat pikeun informasi disimpen ngeunaan hiji set, bari ngajaga kamampuhan pikeun nambahkeun jeung miceun elemen, pariksa jeung ngabuktikeun ayana unsur dina susunan ngagunakeun accumulators cryptographic.

Batré pikeun UTXO

Gagasan ngagunakeun batré pikeun nyimpen sababaraha UTXOs ieu dibahas tadi.

UTXO-set ieu diwangun dina laleur nu, salila awal block download (IBD), disimpen dina pinuh sarta permanén, bari eusina robah sanggeus ngolah transaksi ti unggal blok anyar jeung bener jaringan. Prosés ieu ngabutuhkeun unduh kira-kira 200 GB data blok sareng pariksa ratusan juta tanda tangan digital. Saatos prosés IBD réngsé, garis handap nyaéta UTXO-set bakal nempatan ngeunaan 4 GB.

Sanajan kitu, kalawan accumulators, aturan konsensus pikeun dana diréduksi jadi verifikasi sarta generasi proofs cryptographic, sarta beungbeurat tracking dana sadia ieu bergeser ka nu boga dana, anu nyadiakeun bukti ayana sarta kapamilikan maranéhanana.

Accumulator tiasa disebat perwakilan kompak tina set. Ukuran répréséntasi disimpen kudu boh konstan Utreexo: compressing loba UTXO Bitcoin, atawa ningkatkeun sublinearly ngeunaan kardinalitas set jeung ukuran unsur sorangan, contona. Utreexo: compressing loba UTXO Bitcoin, dimana n nyaéta cardinality set disimpen.

Dina hal ieu, accumulator kudu ngidinan generating hiji bukti citakan unsur dina susunan (buktina inklusi) jeung ngamungkinkeun pikeun éféktif pariksa buktina ieu.

Batré disebut dinamis lamun ngidinan Anjeun pikeun nambahkeun elemen jeung cabut elemen ti set a.

Conto batré sapertos kitu RSA accumulator diajukeun ku Boneh, Bunz, Fisch dina bulan Désémber 2018. Accumulator sapertos gaduh ukuran tetep tina perwakilan disimpen, tapi peryogi ayana rusiah dibagikeun (setélan dipercaya). Sarat ieu negates applicability of accumulator misalna pikeun jaringan trustless kawas Bitcoin, saprak leakage data salila generasi rusiah bisa ngidinan lawan nyieun bukti palsu ayana UTXO a, deceiving titik kalawan UTXO-set dumasar kana accumulator misalna hiji.

Utreexo

Desain Utreexo diusulkeun ku Thaddeus Dryja ngamungkinkeun pikeun nyieun dinamis аккумулятор tanpa dipercanten-setup.

Utreexo mangrupakeun leuweung binér sampurna Tangkal Merkle sarta mangrupa ngembangkeun gagasan dibere dina Accumulators Asynchronous efisien pikeun pki disebarkeun, nambahkeun kamampuhan pikeun miceun elemen ti hiji set.

Struktur Logis batré

Sél batré anu disusun dina leuweung tina tangkal binér idéal. Tangkal diurutkeun ku jangkungna. Répréséntasi ieu dipilih salaku paling visual jeung ngidinan Anjeun pikeun visualize merging tangkal salila operasi dina batréna.

Panulis nyatet yén saprak sadaya tangkal di leuweung éta idéal, jangkungna maranéhanana dinyatakeun salaku kakuatan dua, sakumaha wae angka alam bisa digambarkeun salaku jumlah kakuatan dua. Sasuai, sagala set daun bisa dikelompokkeun kana tangkal binér, sarta dina sagala hal, nambahkeun unsur anyar merlukeun pangaweruh. ngan ngeunaan titik akar tangkal disimpen.

Ku kituna, representasi disimpen tina accumulator Utreexo mangrupa daptar titik akar (akar Merkle), teu sakabeh leuweung tangkal.

Hayu urang ngagambarkeun daptar elemen root salaku Vec<Option<Hash>>. Tipe pilihan Option<Hash> nunjukkeun yén unsur akar bisa leungit, nu hartina teu aya tangkal jeung jangkungna luyu dina accumulator nu.

/// SHA-256 хеш
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct Hash(pub [u8; 32]);

#[derive(Debug, Clone)]
pub struct Utreexo {
    pub roots: Vec<Option<Hash>>,
}

impl Utreexo {
    pub fn new(capacity: usize) -> Self {
        Utreexo {
            roots: vec![None; capacity],
        }
    }
}

Nambahan elemen

Kahiji, hayu urang ngajelaskeun fungsi parent(), nu ngakuan titik indungna pikeun dua elemen dibikeun.

fungsi indungna ().

Kusabab kami nganggo tangkal Merkle, indungna unggal dua titik nyaéta hiji titik anu nyimpen hash tina concatenation tina hashes tina titik anak:

fn hash(bytes: &[u8]) -> Hash {
    let mut sha = Sha256::new();
    sha.input(bytes);
    let res = sha.result();
    let mut res_bytes = [0u8; 32];
    res_bytes.copy_from_slice(res.as_slice());

    Hash(res_bytes)
}

fn parent(left: &Hash, right: &Hash) -> Hash {
    let concat = left
        .0
        .into_iter()
        .chain(right.0.into_iter())
        .map(|b| *b)
        .collect::<Vec<_>>();

    hash(&concat[..])
}

Panulis nyatet yén pikeun nyegah serangan anu dijelaskeun ku Charles Bouillaguet, Pierre-Alain Fouque, Adi Shamir, sareng Sebastien Zimmer dina
Serangan preimage kadua dina fungsi hash dithered, sajaba dua hashes, jangkungna jero tangkal ogé kudu ditambahkeun kana concatenation nu.

Nalika anjeun nambihan elemen kana accumulator, anjeun kedah ngalacak mana elemen akar anu dirobih. Ku nuturkeun jalur ngarobah elemen root pikeun tiap elemen Anjeun nambahkeun, Anjeun engké bisa ngawangun hiji bukti ayana elemen ieu.

Lacak parobahan nalika anjeun nambihanana

Pikeun ngalacak parobahan anu dilakukeun, hayu urang nyatakeun strukturna Update, nu bakal nyimpen data ngeunaan parobahan titik.

#[derive(Debug)]
pub struct Update<'a> {
    pub utreexo: &'a mut Utreexo,
    // ProofStep хранит "соседа" элемента и его положение
    pub updated: HashMap<Hash, ProofStep>,
}

Pikeun nambahkeun unsur kana batré, anjeun peryogi:

  • Jieun Asép Sunandar Sunarya ti baskets elemen root new_roots sareng tempatkeun elemen akar anu tos aya, hiji pikeun unggal ember:

kode

let mut new_roots = Vec::new();

for root in self.roots.iter() {
    let mut vec = Vec::<Hash>::new();
    if let Some(hash) = root {
        vec.push(*hash);
    }

    new_roots.push(vec);
}

  • Tambihkeun elemen anu bakal ditambihan (array insertions) kana karanjang munggaran new_roots[0]:

Utreexo: compressing loba UTXO Bitcoin

kode

new_roots[0].extend_from_slice(insertions);

  • Coalesce item nu ditambahkeun kana karanjang kahiji jeung sésana:
    • Pikeun sakabéh karanjang nu mibanda leuwih ti hiji item:
      1. Candak dua elemen ti tungtung karinjang, ngitung indungna maranéhanana, piceun duanana elemen
      2. Tambahkeun indungna diitung kana karanjang salajengna

Utreexo: compressing loba UTXO Bitcoin

kode

for i in 0..new_roots.len() {
    while new_roots[i].len() > 1 {
        // Объединяем два элемента в один и удаляем их
        let a = new_roots[i][new_roots[i].len() - 2];
        let b = new_roots[i][new_roots[i].len() - 1];
        new_roots[i].pop();
        new_roots[i].pop();
        let hash = self.parent(&a, &b);

        // Наращиваем количество корзин если требуется
        if new_roots.len() <= i + 1 {
            new_roots.push(vec![]);
        }

        // Помещаем элемент в следующую корзину
        new_roots[i + 1].push(hash);

        // Не забываем отслеживать изменения;
        // это пригодится для генерации доказательства добавления элементов
        updated.insert(a, ProofStep { hash: b, is_left: false });
        updated.insert(b, ProofStep {hash: a, is_left: true });
    }
}

  • Mindahkeun elemen akar tina bins ka Asép Sunandar Sunarya accumulator

kode

for (i, bucket) in new_roots.into_iter().enumerate() {
    // Наращиваем аккумулятор если требуется
    if self.roots.len() <= i {
        self.roots.push(None);
    }

    if bucket.is_empty() {
        self.roots[i] = None;
    } else {
        self.roots[i] = Some(bucket[0]);
    }
}

Nyieun bukti pikeun elemen ditambahkeun

Buktina kaasup sél dina batré (Proof) bakal ngawula ka salaku Path Merkle, diwangun ku ranté ProofStep. Upami jalan nuju ka mana-mana, maka buktina henteu leres.

/// Единичный шаг на пути к элементу в дереве Меркла.
#[derive(Debug, Copy, Clone)]
pub struct ProofStep {
    pub hash: Hash,
    pub is_left: bool,
}

/// Доказательство включения элемента. Содержит сам элемент и путь к нему.
#[derive(Debug, Clone)]
pub struct Proof {
    pub steps: Vec<ProofStep>,
    pub leaf: Hash,
}

Nganggo inpormasi anu dicandak sateuacana nalika nambihan unsur (struktur Update), Anjeun bisa nyieun bukti yen hiji unsur geus ditambahkeun kana batréna. Jang ngalampahkeun ieu, urang ngaliwatan tabel parobahan dijieun tur nambahkeun unggal hambalan ka jalur Merkle urang, nu salajengna bakal ngawula ka salaku bukti:

kode

impl<'a> Update<'a> {
    pub fn prove(&self, leaf: &Hash) -> Proof {
        let mut proof = Proof {
            steps: vec![],
            leaf: *leaf,
        };

        let mut item = *leaf;
        while let Some(s) = self.updated.get(&item) {
            proof.steps.push(*s);
            item = parent(&item, &s);
        }

        proof
    }
}

Prosés nyieun bukti

Utreexo: compressing loba UTXO Bitcoin

Mariksa buktina pikeun unsur

Mariksa bukti inklusi unsur nuju ka nuturkeun jalur Merkle dugi ka ngakibatkeun unsur akar anu aya:

pub fn verify(&self, proof: &Proof) -> bool {
    let n = proof.steps.len();
    if n >= self.roots.len() {
        return false;
    }

    let expected = self.roots[n];
    if let Some(expected) = expected {
        let mut current_parent = proof.leaf;
        for s in proof.steps.iter() {
            current_parent = if s.is_left {
                parent(&s.hash, &current_parent)
            } else {
                parent(&current_parent, &s.hash)
            };
        }

        current_parent == expected
    } else {
        false
    }
}

Sacara visual:

Prosés mariksa bukti pikeun A

Utreexo: compressing loba UTXO Bitcoin

Nyoplokkeun barang

Pikeun nyabut sél tina batré, anjeun kudu nyadiakeun bukti valid yen sél aya. Ngagunakeun data tina buktina, kasebut nyaéta dimungkinkeun pikeun ngitung elemen akar anyar accumulator nu bukti dibikeun moal deui leres.

Algoritme na sapertos kieu:

  1. Salaku tambahan, urang ngatur sakumpulan karanjang kosong anu cocog sareng tangkal Merkle kalayan jangkungna sami sareng kakuatan dua tina indéks karinjang.
  2. Urang nyelapkeun elemen ti léngkah tina jalur Merkle kana baskets; indéks karinjang sarua jeung jumlah hambalan ayeuna
  3. Urang miceun unsur akar anu jalur tina buktina nuju
  4. Salaku kalawan nambahkeun, urang ngitung elemen root anyar ku ngagabungkeun elemen ti baskets di pasang sarta mindahkeun hasil union ka karinjang salajengna.

kode

fn delete(&self, proof: &Proof, new_roots: &mut Vec<Vec<Hash>>) -> Result<(), ()> {
    if self.roots.len() < proof.steps.len() || self.roots.get(proof.steps.len()).is_none() {
        return Err(());
    }

    let mut height = 0;
    let mut hash = proof.leaf;
    let mut s;

    loop {
        if height < new_roots.len() {
            let (index, ok) = self.find_root(&hash, &new_roots[height]);
            if ok {
                // Remove hash from new_roots
                new_roots[height].remove(index);

                loop {
                    if height >= proof.steps.len() {
                        if !self.roots[height]
                            .and_then(|h| Some(h == hash))
                            .unwrap_or(false)
                        {
                            return Err(());
                        }

                        return Ok(());
                    }

                    s = proof.steps[height];
                    hash = self.parent(&hash, &s);
                    height += 1;
                }
            }
        }

        if height >= proof.steps.len() {
            return Err(());
        }

        while height > new_roots.len() {
            new_roots.push(vec![]);
        }

        s = proof.steps[height];
        new_roots[height].push(s.hash);
        hash = self.parent(&hash, &s);
        height += 1;
    }
}

Prosés miceun unsur "A":
Utreexo: compressing loba UTXO Bitcoin

Integrasi kana jaringan anu tos aya

Ngagunakeun accumulator diusulkeun, titik bisa nyingkahan ngagunakeun DB pikeun nyimpen sakabeh UTXOs bari masih bisa ngarobah UTXO-set. Tapi, masalah gawé bareng bukti timbul.

Hayu urang nelepon titik validator nu ngagunakeun accumulator UTXO kompak (titik kompak-kaayaan), sarta validator tanpa accumulator nyaeta lengkep (titik pinuh). Ayana dua kelas titik nyiptakeun masalah pikeun ngahijikeun kana jaringan tunggal, saprak titik kompak merlukeun bukti ayana UTXOs, nu spent dina transaksi, bari titik pinuh henteu. Upami sadaya titik jaringan henteu sakaligus sareng sacara terkoordinasi ngalih kana ngagunakeun Utreexo, maka titik kompak bakal tinggaleun sareng moal tiasa beroperasi dina jaringan Bitcoin.

Pikeun ngajawab masalah ngahijikeun titik kompak kana jaringan, diusulkeun pikeun ngenalkeun kelas tambahan tina titik - sasak. Titik sasak mangrupikeun titik lengkep anu ogé nyimpen batré Utreexo sareng buktina kakuatan-on всех UTXO ti UTXO-set. Bridges ngitung hashes anyar sareng ngapdet accumulator sareng bukti nalika blok transaksi anyar sumping. Ngajaga sareng ngapdet accumulator sareng buktina henteu maksakeun beban komputasi tambahan dina titik-titik sapertos kitu. Sasak kurban spasi disk: kudu ngajaga hal diatur Utreexo: compressing loba UTXO Bitcoin hashes, dibandingkeun jeung Utreexo: compressing loba UTXO Bitcoin hashes pikeun titik kompak, dimana n nyaéta kakuatan set UTXO.

Arsitéktur jaringan

Utreexo: compressing loba UTXO Bitcoin

Sasak ngamungkinkeun pikeun laun-laun nambihan titik kompak kana jaringan tanpa ngarobih parangkat lunak titik anu tos aya. Node pinuh beroperasi sakumaha saméméhna, ngadistribusikaeun transaksi jeung blok diantara sorangan. Titik sasak mangrupakeun titik pinuh nu Sajaba nyimpen data batré Utreexo sarta susunan proofs inklusi pikeun всех UTXO ayeuna. Titik sasak henteu ngiklankeun dirina sapertos kitu, pura-pura janten titik pinuh pikeun sadaya titik pinuh sareng titik kompak pikeun sadaya titik kompak. Sanajan sasak nyambungkeun duanana jaringan babarengan, aranjeunna sabenerna ngan perlu nyambungkeun aranjeunna dina hiji arah: ti titik pinuh aya kana titik kompak. Ieu mungkin sabab format urus teu perlu dirobah, sarta UTXO proofs pikeun titik kompak bisa dipiceun, jadi sagala titik kompak bisa ogé disiarkeun transaksi ka sadaya pamilon jaringan tanpa partisipasi titik sasak.

kacindekan

Kami ningali batré Utreexo sareng ngalaksanakeun prototipe na dina Rust. Urang nempo arsitektur jaringan anu bakal ngidinan integrasi titik basis batré. Kauntungannana nyekel kompak nyaéta ukuran data disimpen, nu gumantung logaritmik dina kakuatan susunan UTXOs, nu greatly ngurangan sarat pikeun spasi disk jeung kinerja gudang pikeun titik misalna. Nu disadvantage nyaeta lalulintas titik tambahan pikeun ngirimkeun proofs, tapi téhnik aggregation bukti (lamun hiji bukti ngabuktikeun ayana sababaraha elemen) jeung cache bisa mantuan ngajaga lalulintas dina wates ditarima.

rujukan:

sumber: www.habr.com

Tambahkeun komentar