Utreexo: daudzu UTXO Bitcoin saspieŔana

Utreexo: daudzu UTXO Bitcoin saspieŔana

Čau Habr!

Bitcoin tÄ«klā visi mezgli vienprātÄ«gi vienojas par UTXO komplektu: cik monētu ir pieejams tēriņiem, kam tieÅ”i un ar kādiem nosacÄ«jumiem. UTXO kopa ir minimālā datu kopa, kas nepiecieÅ”ama validatora mezglam, bez kuras mezgls nevarēs pārbaudÄ«t ienākoÅ”o transakciju un tos saturoÅ”o bloku derÄ«gumu.

Å ajā sakarā visos iespējamos veidos tiek mēģināts samazināt Ŕīs kopas saglabāto attēlojumu, saspiest to, nezaudējot droŔības garantijas. Jo mazāks ir saglabāto datu apjoms, jo zemākas ir diska vietas prasÄ«bas validatora mezglam, kas padara validatora mezgla palaiÅ”anu lētu, ļauj paplaÅ”ināt tÄ«klu un tādējādi palielināt tÄ«kla stabilitāti.

Å ajā ziņā mēs ievietosim Rust prototipu nesenam lÄ«dzautora priekÅ”likumam Zibens tÄ«kla papÄ«rs, Tadejs Dryja Sākot no Utreexo: dinamisks uz hash balstÄ«ts akumulators, kas optimizēts Bitcoin UTXO komplektam, kas ļauj samazināt diska vietas prasÄ«bas validatora mezgliem.

Kāda ir problēma?

Viena no Bitcoin daudzgadÄ«gajām problēmām ir tā mērogojamÄ«ba. Ideja par ā€œsavu bankuā€ pieprasa tÄ«kla dalÄ«bniekiem veikt visu lietoÅ”anai pieejamo lÄ«dzekļu uzskaiti. Bitcoin pieejamie lÄ«dzekļi tiek izteikti kā neiztērēto rezultātu kopums - UTXO komplekts. Lai gan tas nav Ä«paÅ”i intuitÄ«vs attēlojums, tas ir izdevÄ«gāks ievieÅ”anas veiktspējas ziņā, salÄ«dzinot ar attēlojumu, kurā katram "makam" ir "lÄ«dzsvars" kā atseviŔķs ieraksts, un tas arÄ« palielina privātumu (piem., MonētaPievienoties).

Ir svarÄ«gi atŔķirt darÄ«jumu vēsturi (to sauc par blokķēdi) no sistēmas paÅ”reizējā stāvokļa. Bitcoin darÄ«jumu vēsture Å”obrÄ«d aizņem aptuveni 200 GB diska vietas un turpina augt. Tomēr sistēmas stāvoklis ir daudz mazāks, apmēram 4 GB, un ņem vērā tikai to, ka kādam paÅ”laik pieder monētas. ArÄ« Å”o datu apjoms laika gaitā palielinās, taču daudz lēnāk un dažkārt pat mēdz samazināties (sk. CDPV).

Vieglie klienti (SPV) tirgo droŔības garantijas spējai saglabāt tikai privātās atslēgas minimālo stāvokli (UTXO-set).

UTXO un UTXO komplekts

UTXO (Unspent Transaction Output) ir neiztērētā darījuma izvade, katra darījumos pārsūtītā Satoshi ceļojuma beigu punkts. Neiztērētie rezultāti kļūst par jaunu transakciju ievadi un tādējādi tiek iztērēti (iztērēti) un noņemti no UTXO kopas.

Jauni UTXO vienmēr tiek izveidoti ar transakcijām:

  • monētu bāzes darÄ«jumi bez ievades: izveidojiet jaunus UTXO, kad kalnrači izdod monētas
  • regulāri darÄ«jumi: izveidojiet jaunus UTXO, vienlaikus iztērējot noteiktu esoÅ”o UTXO kopu

Darba process ar UTXO:
Utreexo: daudzu UTXO Bitcoin saspieŔana

Maki uzskaita tēriņiem pieejamo monētu skaitu (bilance), pamatojoties uz UTXO apjomu, kas pieejams Å”im makam tēriņiem.

Katram validatora mezglam, lai novērstu dubultus tēriņu mēģinājumus, ir jāuzrauga kopa viss UTXO pārbaudot katrs darījumiem no katra bloķēt.

Mezglam ir jābūt loģikai:

  • Papildinājumi UTXO komplektam
  • SvÄ«trojumi no UTXO komplekta
  • Viena UTXO klātbÅ«tnes pārbaude komplektā

Ir veidi, kā samazināt prasības saglabātajai informācijai par kopu, vienlaikus saglabājot iespēju pievienot un noņemt elementus, pārbaudīt un pierādīt elementa esamību komplektā, izmantojot kriptogrāfijas akumulatori.

Baterijas priekÅ” UTXO

Ideja izmantot akumulatorus vairāku UTXO uzglabāŔanai tika apspriests pirms tam.

UTXO komplekts tiek veidots lidojuma laikā, sākotnējās bloka lejupielādes (IBD) laikā, tiek saglabāts pilnÄ«bā un pastāvÄ«gi, savukārt tā saturs mainās pēc transakciju apstrādes no katra jauna un pareiza tÄ«kla bloka. Å im procesam ir nepiecieÅ”ams lejupielādēt aptuveni 200 GB bloku datu un pārbaudÄ«t simtiem miljonu ciparparakstu. Pēc IBD procesa pabeigÅ”anas UTXO komplekts aizņems aptuveni 4 GB.

Tomēr, izmantojot akumulatorus, vienprātÄ«bas noteikumi attiecÄ«bā uz lÄ«dzekļiem tiek samazināti lÄ«dz kriptogrāfisko pierādÄ«jumu pārbaudei un Ä£enerēŔanai, un pieejamo lÄ«dzekļu izsekoÅ”anas slogs tiek pārnests uz Å”o lÄ«dzekļu Ä«paÅ”nieku, kurÅ” sniedz pierādÄ«jumus par to esamÄ«bu un Ä«paÅ”umtiesÄ«bām.

Akumulatoru var saukt par kompaktu kopas attēlojumu. Saglabātā attēla izmēram jābÅ«t nemainÄ«gam Utreexo: daudzu UTXO Bitcoin saspieÅ”ana, vai palielinās sublineāri attiecÄ«bā pret kopas kardinalitāti un paÅ”a elementa izmēru, piemēram, Utreexo: daudzu UTXO Bitcoin saspieÅ”ana, kur n ir saglabātās kopas kardinalitāte.

Šādā gadÄ«jumā akumulatoram ir jāļauj Ä£enerēt pierādÄ«jumu par elementa iekļauÅ”anu komplektā (iekļauÅ”anas pierādÄ«jums) un jārada iespēja efektÄ«vi pārbaudÄ«t Å”o pierādÄ«jumu.

Akumulatoru sauc dinamisks ja ļauj pievienot elementus un noņemt elementus no kopas.

Šāda akumulatora piemērs varētu bÅ«t RSA akumulators, ko 2018. gada decembrÄ« ierosināja Boneh, Bunz, Fisch. Šādam akumulatoram ir nemainÄ«gs saglabātā attēlojuma lielums, taču tam ir nepiecieÅ”ama klātbÅ«tne kopÄ«gs noslēpums (uzticama iestatīŔana). Å Ä« prasÄ«ba noliedz Ŕāda akumulatora piemērojamÄ«bu neuzticamiem tÄ«kliem, piemēram, Bitcoin, jo datu noplÅ«de slepenās Ä£enerēŔanas laikā var ļaut uzbrucējiem izveidot viltus pierādÄ«jumus par UTXO esamÄ«bu, maldinot mezglus ar UTXO komplektu, kura pamatā ir Ŕāds akumulators.

Utreekso

Thaddeus Dryja piedāvātais Utreexo dizains ļauj radīt dinamisks akumulators bez uzticama iestatīŔana.

Utreexo ir perfekta bināra mežs Merkles koki un ir ideju attīstība, kas tika prezentēta Efektīvi asinhronie akumulatori izplatītajiem pki, pievienojot iespēju noņemt elementus no komplekta.

Akumulatora loģiskā struktūra

Akumulatora Ŕūnas ir izvietotas ideālu bināro koku mežā. Koki ir sakārtoti pēc augstuma. Å is attēlojums tika izvēlēts kā vizuālākais un ļauj vizualizēt koku saplūŔanu darbÄ«bas laikā ar akumulatoru.

Autore atzÄ«mē, ka, tā kā visi mežā esoÅ”ie koki ir ideāli, to augstums tiek izteikts kā pakāpē divi, tāpat kā jebkuru naturālu skaitli var attēlot kā divu pakāpju summu. AttiecÄ«gi jebkuru lapu kopu var grupēt bināros kokos, un visos gadÄ«jumos jauna elementa pievienoÅ”ana prasa zināŔanas tikai par glabājamo koku sakņu mezgliem.

Tādējādi saglabātais Utreexo akumulatora attēlojums ir saknes mezglu saraksts (Merkle sakne), un ne viss koku mežs.

Saknes elementu sarakstu attēlosim kā Vec<Option<Hash>>. Izvēles veids Option<Hash> norāda, ka var trÅ«kt saknes elementa, kas nozÄ«mē, ka akumulatorā nav koka ar atbilstoÅ”u augstumu.

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

Elementu pievienoŔana

Vispirms aprakstīsim funkciju parent(), kas atpazīst divu norādīto elementu vecāku mezglu.

vecāku() funkcija

Tā kā mēs izmantojam Merkles kokus, katra no diviem mezgliem vecāks ir viens mezgls, kas glabā pakārtoto mezglu jaucējvārdu sajaukÅ”anu:

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[..])
}

Autors atzīmē, ka, lai novērstu uzbrukumus, kurus aprakstīja Čārlzs Buljē, Pjērs Alēns Fouque, Adi Šamirs un Sebastjens Cimmers
Otrais priekÅ”attēla uzbrukums sajauktajām jaucējfunkcijām, papildus divām jaukÅ”anām, savienojumam jāpievieno arÄ« augstums koka iekÅ”pusē.

Pievienojot elementus akumulatoram, jums ir jāseko lÄ«dzi, kuri saknes elementi tiek mainÄ«ti. Sekojot katra pievienotā elementa saknes elementu maiņas ceļam, vēlāk varat izveidot pierādÄ«jumu par Å”o elementu klātbÅ«tni.

Izsekojiet izmaiņām, kad tās pievienojat

Lai izsekotu veiktajām izmaiņām, deklarēsim struktūru Update, kurā tiks saglabāti dati par mezglu izmaiņām.

#[derive(Debug)]
pub struct Update<'a> {
    pub utreexo: &'a mut Utreexo,
    // ProofStep хранит "сосеГа" ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š° Šø его положение
    pub updated: HashMap<Hash, ProofStep>,
}

Lai akumulatoram pievienotu elementu, jums ir nepiecieŔams:

  • Izveidojiet sakņu elementu grozu masÄ«vu new_roots un ievietojiet tur esoÅ”os saknes elementus, pa vienam katram spainim:

Kods

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

  • Pievienojiet pievienojamos elementus (masÄ«vs insertions) uz pirmo grozu new_roots[0]:

Utreexo: daudzu UTXO Bitcoin saspieŔana

Kods

new_roots[0].extend_from_slice(insertions);

  • Apvienojiet pirmajam grozam pievienotās preces ar pārējām:
    • Visiem groziem ar vairākām precēm:
      1. Paņemiet divus elementus no groza gala, aprēķiniet to vecākus, noņemiet abus elementus
      2. Pievienojiet aprēķināto vecāku nākamajam grozam

Utreexo: daudzu UTXO Bitcoin saspieŔana

Kods

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

  • Pārvietojiet saknes elementus no tvertnēm uz iegÅ«to akumulatoru masÄ«vu

Kods

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

Pierādījuma izveide pievienotajiem elementiem

PierādÄ«jums par elementa iekļauÅ”anu akumulatorā (Proof) kalpos kā Merkles ceļŔ, kas sastāv no ķēdes ProofStep. Ja ceļŔ nekur neved, tad pierādÄ«jums ir nepareizs.

/// ЕГиничный шаг на ŠæŃƒŃ‚Šø Šŗ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ńƒ в Гереве ŠœŠµŃ€ŠŗŠ»Š°.
#[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,
}

IepriekÅ” iegÅ«tās informācijas izmantoÅ”ana, pievienojot elementu (struktÅ«ru Update), varat izveidot pierādÄ«jumu, ka akumulatoram ir pievienots elements. Lai to izdarÄ«tu, mēs apskatām veikto izmaiņu tabulu un pievienojam Merkles ceļam katru soli, kas vēlāk kalpos kā pierādÄ«jums:

Kods

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

Pierādījuma izveides process

Utreexo: daudzu UTXO Bitcoin saspieŔana

Elementa pierādījuma pārbaude

Elementa iekļauÅ”anas pierādÄ«juma pārbaude nozÄ«mē, ka jāseko Merkles ceļam, lÄ«dz tas noved pie esoÅ”a saknes elementa:

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

Vizuāli:

A pierādījuma pārbaudes process

Utreexo: daudzu UTXO Bitcoin saspieŔana

Vienumu noņemÅ”ana

Lai izņemtu elementu no akumulatora, jums ir jāsniedz derīgs pierādījums tam, ka baterija tur atrodas. Izmantojot pierādījuma datus, var aprēķināt jaunus akumulatora saknes elementus, kuriem dotais pierādījums vairs nebūs patiess.

Algoritms ir Ŕāds:

  1. Tāpat kā papildus, mēs organizējam tukÅ”u grozu komplektu, kas atbilst Merkles kokiem ar augstumu, kas vienāds ar divu jaudu no groza indeksa
  2. Grozās ievietojam elementus no Merkles takas pakāpieniem; groza indekss ir vienāds ar paÅ”reizējā soļa skaitli
  3. Mēs noņemam saknes elementu, uz kuru ved ceļŔ no pierādÄ«juma
  4. Tāpat kā pievienojot, mēs aprēķinām jaunus saknes elementus, apvienojot elementus no groziem pa pāriem un pārvietojot apvienoÅ”anas rezultātu uz nākamo grozu

Kods

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

Elementa "A" noņemÅ”anas process:
Utreexo: daudzu UTXO Bitcoin saspieŔana

Integrācija esoŔajā tīklā

Izmantojot piedāvāto akumulatoru, mezgli var izvairÄ«ties no DB izmantoÅ”anas visu UTXO glabāŔanai, vienlaikus spējot mainÄ«t UTXO kopu. Tomēr rodas problēma darbā ar pierādÄ«jumiem.

Sauksim validatora mezglu, kas izmanto UTXO akumulatoru kompakts (kompaktā stāvokļa mezgls), un validators bez akumulatora ir pabeigts (pilns mezgls). Divu mezglu klaÅ”u esamÄ«ba rada problēmas to integrēŔanai vienā tÄ«klā, jo kompaktiem mezgliem ir nepiecieÅ”ams pierādÄ«jums par UTXO esamÄ«bu, kas tiek iztērēti darÄ«jumos, bet pilnajiem mezgliem nav. Ja visi tÄ«kla mezgli vienlaikus un saskaņoti nepāries uz Utreexo lietoÅ”anu, tad kompaktie mezgli atpaliks un nespēs darboties Bitcoin tÄ«klā.

Lai atrisinātu kompakto mezglu integrēŔanas tÄ«klā problēmu, tiek ierosināts ieviest papildu mezglu klasi - tilti. Tilta mezgls ir pilnÄ«gs mezgls, kurā glabājas arÄ« Utreexo akumulators un ieslēgÅ”anas apliecinājums viss UTXO no UTXO komplekta. Tilti aprēķina jaunus jaucējus un atjaunina akumulatoru un pierādÄ«jumus, kad tiek saņemti jauni darÄ«jumu bloki. Akumulatora un pierādÄ«jumu uzturēŔana un atjaunināŔana Ŕādiem mezgliem neuzliek papildu skaitļoÅ”anas slodzi. Tilti upurē vietu diskā: nepiecieÅ”ams sakārtot lietas Utreexo: daudzu UTXO Bitcoin saspieÅ”ana hashes, salÄ«dzinot ar Utreexo: daudzu UTXO Bitcoin saspieÅ”ana jaucējvērtÄ«bas kompaktajiem mezgliem, kur n ir UTXO kopas jauda.

Tīkla arhitektūra

Utreexo: daudzu UTXO Bitcoin saspieŔana

Tilti ļauj pakāpeniski pievienot tÄ«klam kompaktus mezglus, nemainot esoÅ”o mezglu programmatÅ«ru. Pilni mezgli darbojas tāpat kā iepriekÅ”, sadalot darÄ«jumus un blokus savā starpā. Tilta mezgli ir pilni mezgli, kas papildus saglabā Utreexo akumulatora datus un iekļauÅ”anas pierādÄ«jumu kopu viss Pagaidām UTXO. Tilta mezgls sevi kā tādu nereklamē, izliekoties par pilnu mezglu visiem pilnajiem mezgliem un par kompakto mezglu visiem kompaktajiem. Lai gan tilti savieno abus tÄ«klus kopā, tie faktiski ir jāsavieno tikai vienā virzienā: no esoÅ”ajiem pilnajiem mezgliem lÄ«dz kompaktajiem mezgliem. Tas ir iespējams, jo transakcijas formāts nav jāmaina, un UTXO apliecinājumus kompaktajiem mezgliem var izmest, tāpēc jebkurÅ” kompaktais mezgls var lÄ«dzÄ«gi pārraidÄ«t transakcijas visiem tÄ«kla dalÄ«bniekiem bez tilta mezglu lÄ«dzdalÄ«bas.

Secinājums

Mēs apskatÄ«jām Utreexo akumulatoru un ieviesām tā prototipu Rustā. Mēs apskatÄ«jām tÄ«kla arhitektÅ«ru, kas ļaus integrēt uz akumulatoru balstÄ«tus mezglus. Kompakto nozveju priekÅ”rocÄ«ba ir saglabāto datu lielums, kas logaritmiski ir atkarÄ«gs no UTXO kopas jaudas, kas ievērojami samazina diska vietas un uzglabāŔanas veiktspējas prasÄ«bas Ŕādiem mezgliem. TrÅ«kums ir papildu mezglu trafika pierādÄ«jumu pārsÅ«tīŔanai, taču pierādÄ«jumu apkopoÅ”anas metodes (kad viens pierādÄ«jums pierāda vairāku elementu esamÄ«bu) un keÅ”atmiņa var palÄ«dzēt saglabāt trafiku pieņemamās robežās.

atsauces:

Avots: www.habr.com

Iegādājieties uzticamu mitināŔanu vietnēm ar DDoS aizsardzÄ«bu, VPS VDS serveriem šŸ”„ Iegādājieties uzticamu tÄ«mekļa vietņu mitināŔanu ar DDoS aizsardzÄ«bu, VPS VDS serveriem | ProHoster