Utreexo: compressing akeh UTXO Bitcoin

Utreexo: compressing akeh UTXO Bitcoin

Hey Habr!

Ing jaringan Bitcoin, kabeh simpul, liwat konsensus, setuju ing pesawat saka UTXOs: carane akeh dhuwit recehan kasedhiya kanggo mbuwang, kanggo sapa persis, lan ing kahanan apa. Set UTXO minangka set data minimal sing dibutuhake kanggo simpul validator, tanpa simpul kasebut ora bakal bisa verifikasi validitas transaksi sing mlebu lan blok sing ngemot.

Ing babagan iki, upaya ditindakake kanthi cara kanggo nyuda perwakilan sing disimpen saka set iki, kanggo ngompres tanpa kelangan jaminan keamanan. Sing luwih cilik volume data sing disimpen, luwih murah syarat ruang disk saka simpul validator, sing nggawe simpul validator murah, ngidini sampeyan nggedhekake jaringan lan kanthi mangkono nambah stabilitas jaringan.

Ing kirim iki kita bakal ngirim prototipe Rust saka proposal anyar saka co-penulis Kertas Jaringan Kilat, Thaddeus Dryja - Utreexo: akumulator basis hash dinamis sing dioptimalake kanggo set Bitcoin UTXO, sing ngidini ngurangi syarat spasi disk kanggo simpul validator.

Apa masalahe?

Salah sawijining masalah perennial Bitcoin yaiku skalabilitas. Gagasan "bank sampeyan dhewe" mbutuhake peserta jaringan kanggo nyimpen cathetan kabeh dana sing kasedhiya kanggo digunakake. Ing Bitcoin, dana sing kasedhiya dituduhake minangka sakumpulan output sing ora digunakake - UTXO-set. Sanajan iki dudu perwakilan sing intuisi, nanging migunani babagan kinerja implementasine tinimbang perwakilan sing saben "dompet" duwe "keseimbangan" minangka entri sing kapisah, lan uga nambah privasi (contone. CoinJoin).

Penting kanggo mbedakake antarane riwayat transaksi (sing diarani blockchain) lan kahanan sistem saiki. Sajarah transaksi Bitcoin saiki manggoni babagan 200 GB ruang disk, lan terus berkembang. Nanging, negara sistem luwih cilik, ing urutan 4 GB, lan mung njupuk menyang akun kasunyatan sing wong saiki duwe dhuwit recehan. Volume data iki uga mundhak saka wektu, nanging ing tingkat luwih alon lan kadhangkala malah cenderung kanggo ngurangi (ndeleng CDPV).

klien cahya (SPVs) njamin keamanan perdagangan kanggo kemampuan kanggo nyimpen ora negara minimal (UTXO-set) liyane saka tombol pribadi.

UTXO lan UTXO-set

UTXO (Output Transaksi Unspent) punika output transaksi unspent, titik pungkasan lelampahan saben Satoshi ditransfer ing transaksi. Output unspent dadi input saka transaksi anyar lan kanthi mangkono ngginakaken (nglampahi) lan dibusak saka UTXO-set.

UTXOs anyar tansah digawe dening transaksi:

  • transaksi coinbase tanpa input: nggawe UTXOs anyar nalika miners ngetokake dhuwit recehan
  • transaksi biasa: nggawe UTXOs anyar nalika mbuwang pesawat tartamtu saka UTXOs ana

Proses nggarap UTXO:
Utreexo: compressing akeh UTXO Bitcoin

Dompet ngitung jumlah dhuwit recehan sing kasedhiya kanggo mbuwang (imbangan) adhedhasar jumlah UTXO sing kasedhiya ing dompet iki kanggo mbuwang.

Saben simpul validator, kanggo nyegah dobel nglampahi usaha, kudu ngawasi pesawat всСх UTXO nalika mriksa saben transaksi saben pamblokiran.

Node kudu duwe logika:

  • Tambahan kanggo UTXO-set
  • Pambusakan saka UTXO-set
  • Priksa ananΓ© UTXO siji ing pesawat

Ana cara kanggo nyuda syarat kanggo informasi sing disimpen babagan set, nalika njaga kemampuan kanggo nambah lan mbusak unsur, mriksa lan mbuktekake anane unsur ing set nggunakake akumulator kriptografi.

Baterei kanggo UTXO

Gagasan nggunakake baterei kanggo nyimpen pirang-pirang UTXO rembugan sadurunge.

UTXO-set dibangun ing fly ing, sak download pemblokiran dhisikan (IBD), disimpen ing lengkap lan permanen, nalika isi ngganti sawise Processing transaksi saka saben pemblokiran anyar lan bener saka jaringan. Proses iki mbutuhake ndownload kira-kira 200 GB data pamblokiran lan verifikasi atusan yuta tandha digital. Sawise proses IBD rampung, ing ngisor iki UTXO-set bakal Occupy bab 4 GB.

Nanging, kanthi akumulator, aturan konsensus kanggo dana dikurangi dadi verifikasi lan generasi bukti kriptografi, lan beban nelusuri dana sing kasedhiya dipindhah menyang pemilik dana kasebut, sing menehi bukti babagan eksistensi lan kepemilikan.

Akumulator bisa kasebut minangka perwakilan kompak saka sawijining set. Ukuran perwakilan sing disimpen kudu tetep Utreexo: compressing akeh UTXO Bitcoin, utawa nambah sublinearly babagan kardinalitas set lan ukuran unsur kasebut, contone. Utreexo: compressing akeh UTXO Bitcoin, ngendi n punika cardinality saka pesawat disimpen.

Ing kasus iki, accumulator kudu ngidini ngasilaken bukti Gawan saka unsur ing pesawat (bukti inklusi) lan nggawe iku bisa kanggo èfèktif verifikasi bukti iki.

Baterei diarani dinamis yen ngijini sampeyan kanggo nambah unsur lan mbusak unsur saka pesawat.

Conto saka baterei kuwi bakal Akumulator RSA diusulake dening Boneh, Bunz, Fisch ing Desember 2018. Akumulator kasebut nduweni ukuran sing tetep saka perwakilan sing disimpen, nanging mbutuhake kehadiran rahasia bareng (persiyapan dipercaya). Requirement iki negates applicability saka accumulator kuwi kanggo jaringan trustless kaya Bitcoin, wiwit bocor data sak generasi rahasia bisa ngidini panyerang kanggo nggawe bukti palsu saka orane UTXO a, ngapusi kelenjar karo UTXO-set adhedhasar accumulator kuwi.

Utreexo

Desain Utreexo ngajokaken dening Thaddeus Dryja ndadekake iku bisa kanggo nggawe dinamis аккумулятор tanpa persiyapan dipercaya.

Utreexo minangka alas binar sampurna Wit Merkle lan minangka pangembangan gagasan sing disedhiyakake ing Akumulator asinkron sing efisien kanggo pki sing disebarake, nambah kemampuan kanggo mbusak unsur saka pesawat.

Baterei Struktur Logis

Sèl baterei disusun ing alas wit binar sing becik. Wit diurutake miturut dhuwur. Perwakilan iki dipilih minangka sing paling visual lan ngidini sampeyan nggambarake panggabungan wit sajrone operasi ing baterei.

Penulis nyathet yen kabeh wit ing alas iku becik, dhuwure dituduhake minangka kekuwatan loro, kayadene nomer alami sing bisa diwakili minangka jumlah kekuwatan loro. Dadi, godhong apa wae bisa dikelompokake dadi wit binar, lan ing kabeh kasus, nambah unsur anyar mbutuhake kawruh. mung babagan simpul oyod saka wit sing disimpen.

Mangkono, perwakilan sing disimpen saka accumulator Utreexo minangka dhaptar node root (root Merkle), lan ora kabeh alas wit.

Ayo dadi makili dhaftar unsur ROOT minangka Vec<Option<Hash>>. Tipe opsional Option<Hash> nuduhake yen unsur ROOT bisa ilang, kang tegese ora ana wit karo dhuwur cocok ing accumulator.

/// 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],
        }
    }
}

Nambah unsur

Pisanan, ayo nerangake fungsi kasebut parent(), sing ngenali simpul induk kanggo rong unsur sing diwenehake.

fungsi parent().

Amarga kita nggunakake wit Merkle, wong tuwa saben rong simpul kasebut minangka salah sawijining simpul sing nyimpen hash saka concatenation saka hash saka simpul 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[..])
}

Penulis nyathet yen kanggo nyegah serangan sing diterangake dening Charles Bouillaguet, Pierre-Alain Fouque, Adi Shamir, lan Sebastien Zimmer ing
Serangan pragambar kaping pindho ing fungsi hash sing didhelikake, Saliyane loro hash, dhuwur ing jero wit uga kudu ditambahake ing concatenation.

Nalika sampeyan nambah unsur kanggo accumulator, sampeyan kudu nglacak kang unsur ROOT diganti. Kanthi ngetutake dalan kanggo ngganti unsur oyod kanggo saben unsur sing ditambahake, sampeyan bisa mengko mbangun bukti ananΓ© unsur kasebut.

Lacak owah-owahan nalika sampeyan nambahake

Kanggo nglacak owah-owahan sing digawe, ayo ngumumake struktur kasebut Update, sing bakal nyimpen data babagan owah-owahan simpul.

#[derive(Debug)]
pub struct Update<'a> {
    pub utreexo: &'a mut Utreexo,
    // ProofStep Ρ…Ρ€Π°Π½ΠΈΡ‚ "сосСда" элСмСнта ΠΈ Π΅Π³ΠΎ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
    pub updated: HashMap<Hash, ProofStep>,
}

Kanggo nambah unsur menyang baterei, sampeyan kudu:

  • Nggawe array saka kranjang saka unsur ROOT new_roots lan selehake unsur oyod sing ana, siji kanggo saben 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);
}

  • Tambahake unsur sing bakal ditambahake (array insertions) menyang cart pisanan new_roots[0]:

Utreexo: compressing akeh UTXO Bitcoin

Kode

new_roots[0].extend_from_slice(insertions);

  • Gabungke item sing ditambahake menyang kranjang pisanan karo liyane:
    • Kanggo kabeh krΓ©ta kanthi luwih saka siji barang:
      1. Njupuk rong unsur saka mburi basket, ngetung tuwane, mbusak loro unsur
      2. Tambah wong tuwa sing diwilang menyang cart sabanjurΓ©

Utreexo: compressing akeh 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 });
    }
}

  • Pindhah unsur ROOT saka tong sampah kanggo asil accumulator array

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]);
    }
}

Nggawe bukti kanggo unsur tambahan

Bukti kalebu sel ing baterei (Proof) bakal dadi Path Merkle, sing dumadi saka rantΓ© ProofStep. Yen dalan ora ana arah, mula buktine ora bener.

/// Π•Π΄ΠΈΠ½ΠΈΡ‡Π½Ρ‹ΠΉ шаг Π½Π° ΠΏΡƒΡ‚ΠΈ ΠΊ элСмСнту Π² Π΄Π΅Ρ€Π΅Π²Π΅ ΠœΠ΅Ρ€ΠΊΠ»Π°.
#[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,
}

Nggunakake informasi sing dipikolehi sadurunge nalika nambah unsur (struktur Update), sampeyan bisa nggawe bukti yen ana unsur wis ditambahake menyang baterei. Kanggo nindakake iki, kita ngliwati tabel owah-owahan sing digawe lan nambah saben langkah menyang dalan Merkle, sing bakal dadi 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
    }
}

Proses nggawe bukti

Utreexo: compressing akeh UTXO Bitcoin

Priksa bukti kanggo unsur

Mriksa bukti inklusi unsur mudhun kanggo ngetutake path Merkle nganti ndadΓ©kakΓ© unsur oyot sing ana:

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
    }
}

Cetha:

Proses mriksa bukti kanggo A

Utreexo: compressing akeh UTXO Bitcoin

Mbusak item

Kanggo mbusak sel saka baterei, sampeyan kudu menehi bukti sing bener yen sel kasebut ana. Nggunakake data saka bukti, sampeyan bisa ngetung unsur oyod anyar saka accumulator sing bukti sing diwenehake ora bakal bener maneh.

Algoritme kaya ing ngisor iki:

  1. Kajaba iku, kita ngatur set kranjang kosong sing cocog karo wit Merkle kanthi dhuwur sing padha karo kekuwatan loro saka indeks basket.
  2. Kita nglebokake unsur saka langkah-langkah dalan Merkle menyang kranjang; indeks basket padha karo nomer langkah saiki
  3. Kita mbusak unsur ROOT sing path saka bukti ndadΓ©kakΓ©
  4. Minangka nambah, kita ngetung unsur oyod anyar kanthi nggabungake unsur saka kranjang kanthi pasangan lan mindhah asil serikat menyang basket sabanjure

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;
    }
}

Proses mbusak unsur "A":
Utreexo: compressing akeh UTXO Bitcoin

Integrasi menyang jaringan sing wis ana

Nggunakake accumulator ngajokaken, kelenjar bisa supaya nggunakake DB kanggo nyimpen kabeh UTXOs nalika isih bisa ngganti UTXO-set. Nanging, masalah nggarap bukti muncul.

Ayo nelpon simpul validator sing nggunakake accumulator UTXO kompak (simpul negara kompak), lan validator tanpa akumulator yaiku ngrampungake (node ​​lengkap). Orane rong kelas kelenjar nggawe masalah kanggo nggabungake menyang jaringan siji, amarga kelenjar kompak mbutuhake bukti ananΓ© UTXOs, kang ngginakaken ing transaksi, nalika kelenjar lengkap ora. Yen kabeh simpul jaringan ora bebarengan lan kanthi cara sing terkoordinasi ngalih menyang nggunakake Utreexo, banjur simpul kompak bakal ditinggalake lan ora bisa digunakake ing jaringan Bitcoin.

Kanggo ngatasi masalah nggabungake node kompak menyang jaringan, diusulake kanggo ngenalake kelas simpul tambahan - kreteg. A simpul jembatan minangka simpul lengkap sing uga nyimpen baterei Utreexo lan bukti daya kanggo всСх UTXO saka UTXO-set. Bridges ngetung hash anyar lan nganyari accumulator lan bukti nalika pamblokiran anyar transaksi teka. Njaga lan nganyari accumulator lan bukti ora nemtokke beban komputasi tambahan ing kelenjar kuwi. Bridges kurban papan disk: kudu supaya iku diatur Utreexo: compressing akeh UTXO Bitcoin hashes, dibandhingake karo Utreexo: compressing akeh UTXO Bitcoin hash kanggo kelenjar kompak, ngendi n iku daya saka pesawat UTXO.

Arsitektur jaringan

Utreexo: compressing akeh UTXO Bitcoin

Bridges ndadekake iku bisa kanggo mboko sithik nambah simpul kompak menyang jaringan tanpa ngganti piranti lunak saka kelenjar ana. Node lengkap beroperasi kaya sadurunge, nyebarake transaksi lan pamblokiran ing antarane. Node Bridge minangka simpul lengkap sing uga nyimpen data baterei Utreexo lan sakumpulan bukti inklusi всСх UTXO saiki. Simpul jembatan ora ngiklanake awake dhewe kaya ngono, pura-pura dadi simpul lengkap kanggo kabeh simpul lengkap lan simpul kompak kanggo kabeh sing kompak. Senajan kreteg nyambungake loro jaringan bebarengan, padha mung perlu kanggo nyambung menyang siji arah: saka simpul lengkap ana kanggo simpul kompak. Iki bisa amarga format transaksi ora perlu diganti, lan bukti UTXO kanggo simpul kompak bisa dibuwak, supaya sembarang simpul kompak uga bisa siaran transaksi kanggo kabeh peserta jaringan tanpa partisipasi simpul jembatan.

kesimpulan

Kita ndeleng baterei Utreexo lan ngetrapake prototipe ing Rust. Kita nyawang arsitektur jaringan sing bakal ngidini integrasi simpul basis baterei. Kauntungan saka nyekel kompak yaiku ukuran data sing disimpen, sing gumantung sacara logaritmik ing kekuwatan set UTXOs, sing nyuda syarat kanggo papan disk lan kinerja panyimpenan kanggo kelenjar kasebut. Kerugian kasebut yaiku lalu lintas simpul tambahan kanggo ngirim bukti, nanging teknik agregasi bukti (nalika siji bukti mbuktekake ana sawetara unsur) lan caching bisa mbantu njaga lalu lintas ing watesan sing bisa ditampa.

referensi:

Source: www.habr.com

Add a comment