Sjaj i bijeda atomske zamjene

Zašto su atomske zamjene loše i kako će im kanali pomoći, koje su se važne stvari dogodile u Constantinople hard forku i što učiniti kada nemate čime platiti plin.

Glavna motivacija svakog stručnjaka za sigurnost je želja za izbjegavanjem odgovornosti.

Providnost je bila milostiva, napustio sam ICO ne čekajući prvu nepovratnu transakciju, ali sam ubrzo počeo razvijati kripto razmjenu.

Ja definitivno nisam Malchish Kibalchish i dovoljan mi je jedan strog pogled da predam sve ključeve i lozinke. Stoga je moj glavni cilj kao arhitekta bio smjestiti užarenu žaoku kriptoanalize što dalje od meni dragih infrastrukturnih elemenata.

Ne tvoji ključevi, ne tvoji problemi

Gradimo sustav razmjene imovine i želimo eliminirati posredno skladištenje te imovine, ali moramo osigurati sigurnost transakcije.

Možete djelovati kao sudac u kontroverznoj situaciji i provoditi transakcije novčanicima za koje su potrebna dva od tri potpisa: kupac, prodavatelj i escrow.

Međutim, ako sudionik uspješno napadne escrow, tada dobiva potrebna dva potpisa.

Atomic swap je shema razmjene gdje je jamac pametni ugovor koji dopušta samo pošteno ponašanje.

Kao u zagonetki o vuku, kozi i kupusu, možete se ponašati samo prema jedinom ispravnom scenariju i pretrpjeti gubitke ako od njega odstupite.

Samo umjesto proždrljivih životinja, red daje hash funkcija u kojoj je toliko teško pronaći koliziju da se ne isplati ni pokretati.

Prvi korak: zagonetka

Pretpostavimo da Alice jednog lijepog jutra želi dati Bobu bitcoin za šaku "crypto-yuana".

  • Krije veliku tajnu
  • Dobiva hash od toga
  • Prebacuje bitcoine u pametni ugovor, iz kojeg Bob može povući novac prezentirajući tajnu (njen hash mora biti jednak onom navedenom u ugovoru)
  • Ako se Bob navečer ne pojavi po svoje bitcoine, Alice ih može uzeti natrag sebi.

Drugi korak: mamac

Bob ulazi u igru ​​i upisuje “kripto-eure” u svoj ugovor koji je napisan na način da:

  • Alice može oduzeti "kripto-jene" predstavljanjem tajnog broja
  • Ne prije ručka, Bob može vratiti polog ako se Alice ne pojavi.

Treći korak: odgovor je u mamcu

Alice dolazi po svoj novac i uzima novac iz Bobova ugovora, otkrivajući pritom svoju tajnu.

Završni korak: zagonetka je riješena

Bob vidi transakciju i svojim orlovskim okom iz nje izvlači tajnu koju je Alice predstavila ugovoru. On koristi ovu tajnu kako bi vratio svoje bitcoine.

Kad stvari krenu po zlu

Ako se Alice iznenada pokaže smrtnom, Bob uzima svoj juan za ručak.

Zauzvrat, Alice vraća bitcoin navečer ako podmukli Bob odluči zadržati novac do boljih vremena.

Ako više volite sliku nego tekst, Habré za vas ima detaljniju i vizualniju. objašnjenje kako funkcioniraju atomske zamjene.

Razlika između timeouta osmišljena je kako bi nas osigurala od zlonamjerne Alice, koja uzima Bobov novac u zadnjem trenutku, a timeout istječe dok on drhtavim prstima unese heks u transakciju.

Sudionici ne mogu izgubiti svoj novac; najviše će morati pričekati povrat novca.

Podrška za blockchainOvo je jednostavna shema koja ne zahtijeva ništa od interakcijskih lanaca blokova:

  • Podrška za pametne ugovore s najmanje jednom podružnicom
  • Oba lanca blokova moraju podržavati iste algoritme raspršivanja (ne zaboravite provjeriti duljinu tajne)
  • Vremenske brave.

Burzi se već na prvi pogled može reći “zbogom, naš sastanak je bio pogreška”, ali nije bilo tako.

Unatoč svim svojim prednostima, atomic swap rješenja ne oduševljavaju svojom likvidnošću. Uglavnom zato što u najpopularnijem paru BTC-USD fiat dio nije u potpunosti tokeniziran.
Uspjeh USDT-a doveo je do čitavog vala stabilnih kovanica u formatu ERC20 za svačiji ukus, od USDC-a s najviše skrbništva do DAI-ja s najviše algoritama.

Stoga, radi jednostavnosti, dalje tvrdimo da Alice prodaje Bitcoine Bobu za neke ERC20 tokene, i nadamo se sreći stabilizatora, budući da još uvijek imamo mnogo više tehničkih problema.

Ubrzati

Bitcoin i Ethereum pojedinačno nisu baš brzi, ali ovdje moramo čekati prvo na jedan depozit sa svim potvrdama, a zatim na drugi.

To je sve zato što sudionik koji zna tajnu prvi položi novac, a protivnik čeka finale i tek onda prenosi svoj dio.

Osim toga, imamo posla s vrlo promjenjivom imovinom, tako da se tijekom tog vremena stopa može značajno promijeniti, a promjena uvjeta više nije jednostavna.

Povjerljivost

Svaka razmjena ostavlja artefakte na oba blockchaina. Pažljiv promatrač može primijetiti iste hashove u pametnim ugovorima i donijeti logičan zaključak da je transakcija obavljena, iz čega se može izvući puno zaključaka od tečaja do poreza.

Kad burza zna za tvoje poslove, krajnje je neugodno, kad svi znaju za to, dvostruko je neugodnije.

Upotrebljivost

Jaka strana blockchaina općenito, a posebno ethera. Da vidimo koje će geste prodavač i kupac morati učiniti.

Sa stajališta prodavača, sve je relativno jednostavno: samo trebate prenijeti Bitcoin na p2sh adresu. S eterom je sve mnogo složenije.

ugovorPogledajmo prosječni ugovor na Githubu za zamjenu:

contract iERC20 {
    function totalSupply() public view returns (uint256);
    function transfer(address receiver, uint numTokens) public returns (bool);
    function balanceOf(address tokenOwner) public view returns (uint);
    function approve(address delegate, uint numTokens) public returns (bool);
    function allowance(address owner, address delegate) public view returns (uint);
    function transferFrom(address owner, address buyer, uint numTokens) public returns (bool);
}

contract Swapper {

    struct Swap {
        iERC20 token;
        bytes32 hash;
        uint amount;
        uint refundTime;
        bytes32 secret;
    }

    mapping (address => mapping(address => Swap)) swaps;

    function create(iERC20 token, bytes32 hash, address receiver, uint amount, uint refundTime) public {
        require(swaps[msg.sender][receiver].amount == 0); // check is swap with given hash already exists
        require(token.transferFrom(msg.sender, address(this), amount)); // transfer locked tokens to swap contract
        swaps[msg.sender][receiver] = Swap(token, hash, amount, refundTime, 0x00); //create swap
    }
    
    function hashOf(bytes32 secret) public pure returns(bytes32) {
        return sha256(abi.encodePacked(secret));
    }


    function withdraw(address owner, bytes32 secret) public {
        Swap memory swap = swaps[owner][msg.sender];
        require(swap.secret == bytes32(0));
        require(swap.hash == sha256(abi.encodePacked(secret))); // swap exists
        swaps[owner][msg.sender].secret = secret;
        swap.token.transfer(msg.sender, swap.amount);
    }

    function refund(address receiver) public {
        Swap memory swap = swaps[msg.sender][receiver];
        require(now > swap.refundTime);
        delete swaps[msg.sender][receiver];
        swap.token.transfer(msg.sender, swap.amount);
    }
}

Upozorenje! Nemojte koristiti ovaj i druge ugovore iz članka u proizvodnji, oni su napisani samo u svrhu demonstracije. Pogotovo ovaj.

  • Bob mora pozvati metodu ugovora tokena approve, dajući swap ugovoru pristup svojim tokenima
  • Bob stvara zamjenu i ugovor pomoću metode transferFrom preuzima tokene pošiljatelja na vašu adresu
  • Alice unutra withdraw otkriva tajnu i ugovor poziva transfer

Većina novčanika i kripto mjenjačnica ne podržava approve tokena, i to s dobrim razlogom.

Sami korisnici često griješe i jednostavno prenesu tokene na ugovor, nakon čega se tokeni jednostavno izgube. Komentari na Etherscanu puni su jadikovki nesretnika.

A da biste zaključili ugovor, trebate platiti proviziju u ETH-u, što znači da se oba sudionika moraju opskrbiti tim prije pokretanja transakcije, a malo ljudi to želi učiniti.

Držač plina

Dobro mjesto za početak je ukloniti provjeru pošiljatelja gdje god je to moguće i pretpostaviti da imamo nekoga tko pati od viška plina i ugovore za pozive za sve koji dolaze.

Nadograđeni ugovor

contract Swapper {

    struct Swap {
        iERC20 token;
        address receiver;
        uint amount;
        address refundAddress;
        uint refundTime;
    }

    mapping (bytes32 =>  Swap) swaps;

    function create(iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public {
        require(swaps[hash].amount == 0); // use hash once
        require(token.transferFrom(msg.sender, address(this), amount));
        swaps[hash] = Swap(token, receiver, amount, refundAddress, refundTime);
    }


    function withdraw(bytes memory secret) public {
        bytes32 hash = sha256(secret);
        Swap memory swap = swaps[hash];
        require(swap.amount > 0);
        delete swaps[hash];
        swap.token.transfer(swap.receiver, swap.amount);
    }

    function refund(bytes32 hash) public {
        Swap memory swap = swaps[hash];
        require(now > swap.refundTime);
        delete swaps[hash];
        swap.token.transfer(swap.refundAddress, swap.amount);
    }
}

Dualizam ugovornog ključa i EIP 712

Kao što znamo, obraćanje u eteru može biti ugovor, a može biti i predmet, odnosno ključ.
Glavni zadatak ključa je potpisivanje nekih poruka.

Možemo koristiti Bob-ugovor kao pošiljatelja, koji čini sve potrebne prolaze, prethodno provjerivši potpis Bob-ključa.

Sada svatko može sponzorirati proviziju sudionika, ali odlučuje samo onaj tko zna ključ.

Bob-ugovor

library EIP712ProxyLibrary {
    function hashCommand(address sender, iERC20 token, Swapper swapper, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public view returns(bytes32);
}

contract ProxyBob {
    address owner;

    constructor(address _owner) public {
        owner = _owner;
    }

    function createSwap(Swapper swapper, iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime, uint8 v, bytes32 r, bytes32 s) public {
        require(owner == ecrecover(EIP712ProxyLibrary.hashCommand(address(this), token, swapper, hash, receiver, amount, refundAddress, refundTime), v, r, s));
        token.approve(address(swapper), amount);
        swapper.create(token, hash, receiver, amount, refundAddress, refundTime);
    }
}

Ethereum ima standard za rad s potpisima složenih struktura podataka EIP 712, više o tome možete pročitati u Metamask novčanik blog

Podijelite i osvojite

Često scenarij hakiranja Ethereum ugovora izgleda ovako:

  • Sudionik uplaćuje sredstva u ugovor
  • Zatim uzima sredstva
  • Nešto nije u redu
  • Napadač uvijek iznova uzima novac

Ako se vratimo na naš prvi primjer, nešto pođe po zlu ako je zagonetka prazan skup bajtova.

Kako ukrasti milijunStvorite zamjenu s hashom 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Ovo je sha256 od 0x0000000000000000000000000000000000000000000000000000000000000000
Prenosimo tajnu i uzimamo svoje žetone
Ponovno prenosimo i uzimamo tuđe, a sve zato što je 0 = 0

Stvaranjem zasebnog ugovora za svaku trgovinu, možemo izolirati ugovore na EVM razini.

Ali to nije sve: sada svaka transakcija ima svoju adresu na koju možete prenijeti tokene iz bilo kojeg novčanika ili mjenjačnice.

Napušteni ugovori i stvoriti2

Ali sada za svaku transakciju moramo sačiniti ugovor i čekati da kupac tamo prebaci rad na "pronalaženju kripto-aplikacija". U shemi "ugovori ujutro, novac navečer" uvijek postoji opasnost da će kupac otpasti, a eter je već potrošen na stvaranje ugovora.

Može li se napraviti tako da imate novac ujutro, a bajtove navečer?

Programeri u Konstantinopolskom hard forku EIP 1014 dodao je instrukciju create2, koja stvara novi ugovor na determinističkoj adresi

keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]

gdje

  • adresa — adresa tvorničkog ugovora
  • sol - neki broj, čije ćemo značenje naučiti u sljedećoj seriji
  • init_code — bajt kod ugovora i parametri konstruktora.

tvornicaUputa radi samo kroz montažu, tako da tvornica izgleda pomalo zastrašujuće:

contract Factory {
  event Deployed(address addr, uint256 salt);

  function create2(bytes memory code, uint256 salt) public {
    address addr;
    assembly {

      addr := create2(0, add(code, 0x20), mload(code), salt)
    }

    emit Deployed(addr, salt);
  }
}

Vaš kod ugovora možete dobiti koristeći web3:

const MyContract = new web3.eth.Contract(ABI, {})
const сode = MyContract.deploy({
    data: BYTECODE,
    arguments: contructorArgs  
}).encodeABI();
const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress);
tx = factory.methods.create2(сode, salt);

Zbog ograničene podrške u čvrstoći, plin za ugovor može biti pogrešno izračunat zbog nekih suptilnosti etera.

Posebno je zgodno što se u slučaju nestašice plina ugovor ruši s internom greškom, bez javljanja da nema dovoljno plina, kako biste očekivali.

Sada možemo prenijeti tokene na ugovore bez da ih unaprijed kreiramo, a dok ih ne objavimo na mreži, nitko neće pogoditi što točno ugovor radi.

Neće gavran vrani oko izbljuvati

Jasno je da pravog analitičara, pogotovo onog koji je dobro uložio u borbu protiv neprijatelja režima pranjem novca, takve djetinjaste smicalice neće zaustaviti, a nakon sklapanja ugovora još će vidjeti haš.

Kako spriječiti da se hash prikazuje?

Sam swap prenosimo u offchain: sudionici razmjenjuju potpise za prijenos na swap ugovor, a zatim se tajna otkriva privatno.

Korak po korakStvaraju se dva "multisiga" iz kojih se mogu povući sredstva ako Alice i Bob imaju potpise.

Kako bi spriječili da bilo koji od sudionika odlazak izvan mreže postane tragedija, dodat ćemo dobri stari timeout.

Alice i Bob paralelno polažu depozite

  • Alice pogađa tajnu i daje Bobu hash tajne i potpis transakcije koji prenosi bitcoine na swap adresu.
  • Bob daje Alice potpis za povlačenje tokena na swap ugovor sa skrivenim hashom.
  • Alice govori Bobu tajnu.

U ovom trenutku dolazi harmonija: i Alice i Bob mogu dovršiti posao u bilo kojem trenutku. U takvom prijateljskom okruženju mogu razmjenjivati ​​potpise za podizanje novca na krajnje adrese.

Promatraču izvana, izgleda kao da je novac prošao kroz 2-od-2 multisig ugovor.

Ova shema također omogućuje da obje strane uplate depozit u isto vrijeme, budući da se tajna otkriva nakon svih potvrda.

Razina 2

Budući da možemo povući novac na jednu adresu i ne objaviti međutransakciju, ništa nas ne sprječava da podižemo novac na više adresa i napravimo neograničen broj međutransakcija. Nije da je ovo neophodan set za razmjenu, ali kada jednom počnete skupljati swap, teško je prestati.

Sada će se Alice i Bob moći okrenuti svom snagom. Na primjer, automatski izračunajte prosječnu cijenu razmjenom satoshija po sekundi ili jednostavno izravno povežite market makera i primatelja likvidnosti.

Korak po korak

  • Prodavatelj pravi tajnu i daje kupcu hash tajne i potpis transakcije gdje se dio sredstava prebacuje na p2sh swap adresu, a ostatak se vraća na adresu prodavatelja
  • Kupac podnosi potpis kojim dopušta slanje swap tokena i kusur na adresu primatelja.
  • Prodavač otkriva tajnu
  • Povijest se ponavlja s novom tajnom, a uz zamjenu i promjenu dodaje se i isplata prethodno kupljenog na adresu kupca i već plaćenog na adresu prodavatelja

Sada imamo pristup brzom p2p trgovanju, glavna stvar je pratiti vrijeme i zaključiti posao prije isteka vremena.

Međutim, malim podešavanjem naših ugovora možemo našim kanalima dati besmrtnost, što će nam znatno olakšati izgradnju mreže.

Ali o tome ćemo u sljedećoj epizodi.

Izvor: www.habr.com

Kupite pouzdan hosting za stranice s DDoS zaštitom, VPS VDS poslužiteljima 🔥 Kupite pouzdan web hosting sa DDoS zaštitom, VPS VDS servere | ProHoster