De pracht en praal van atomaire swaps

Waarom atomic swaps slecht zijn en hoe channels hierbij kunnen helpen, welke belangrijke dingen er gebeurden bij de hard fork in Constantinopel en wat je moet doen als je niets hebt om voor gas te betalen.

De belangrijkste motivatie van elke veiligheidsprofessional is de wens om verantwoordelijkheid te ontlopen.

De voorzienigheid was vriendelijk: ik verliet de ICO vóórdat ik de eerste onomkeerbare transactie kon uitvoeren, maar al snel begon ik een cryptobeurs op te zetten.

Ik ben absoluut niet Malchish Kibalchish en één strenge blik is genoeg om mij alle sleutels en wachtwoorden te laten afgeven. Mijn voornaamste doel als architect was dan ook om de gloeiendhete angel van de cryptoanalyse zo ver mogelijk weg te houden van de infrastructuurelementen die mij dierbaar waren.

Niet uw sleutels, niet uw problemen

Wij zijn bezig met het opzetten van een systeem voor de uitwisseling van activa en willen de tussenopslag van deze activa elimineren, maar we moeten de veiligheid van de transactie wel garanderen.

U kunt optreden als rechter in een geschilsituatie en transacties uitvoeren met wallets waarvoor twee van de drie handtekeningen nodig zijn: de koper, de verkoper en de escrow.

Wanneer de deelnemer echter succesvol de escrow aanvalt, ontvangt hij de twee gewenste handtekeningen.

Een atomic swap is een ruilsysteem waarbij de garant een slim contract is dat alleen eerlijk gedrag toestaat.

Net als bij het raadsel van de wolf, de geit en de kool kun je maar op één juist scenario afgaan en verlies lijden als je daarvan afwijkt.

Alleen wordt de orde in plaats van vraatzuchtige dieren bepaald door een hashfunctie waarin het zo moeilijk is om een ​​botsing te vinden dat het niet eens de moeite waard is om eraan te beginnen.

Stap één: raadsel

Stel je voor dat Alice op een mooie ochtend wat Bitcoin naar Bob wil overmaken voor een handvol "cryptoyuan".

  • Ze vertelt een groot geheim.
  • Krijgt een hasj van hem
  • Bitcoins overmaken naar een slim contract, waaruit Bob geld kan opnemen door een geheim te presenteren (de hash ervan moet gelijk zijn aan de hash die in het contract is gespecificeerd)
  • Als Bob de avond ervoor nog niet komt opdagen om zijn bitcoins op te halen, kan Alice ze terugnemen.

Stap twee: aas

Bob stapt in het spel en zet de “crypto-euro” op zijn contract, dat als volgt is opgesteld:

  • Alice kan haar ‘cryptocoins’ claimen door een geheim nummer in te voeren
  • Bob kan de borg uiterlijk vóór de lunch terugbetalen als Alice niet komt opdagen.

Stap drie: de aanwijzing zit in het aas

Alice komt haar geld halen en neemt het geld uit Bobs contract, waarbij ze haar geheim onthult.

De laatste stap: het mysterie is opgelost

Bob ziet de transactie en ontrafelt met een scherp oog het geheim dat Alice aan het contract heeft toegevoegd. Hij gebruikt dit geheim om zijn bitcoins terug te krijgen.

Als dingen fout gaan

Als Alice plotseling sterfelijk blijkt te zijn, krijgt Bob zijn yuan bij de lunch.

Alice geeft de bitcoin tegen de avond terug als de verraderlijke Bob besluit het geld vast te houden tot betere tijden.

Als u liever afbeeldingen dan tekst ziet, heeft Habr een meer gedetailleerde en visuele versie voor u. uitleg over hoe atomaire swaps werken.

Het verschil tussen de time-outs is bedoeld om ons te beschermen tegen een kwaadaardige Alice die op het allerlaatste moment Bobs geld aanneemt, en de time-out verloopt terwijl hij met trillende vingers hex-codes in de transactie typt.

Deelnemers kunnen hun geld niet verliezen, hooguit moeten ze wachten op een terugbetaling.

Blockchain-ondersteuningHet is een heel eenvoudig plan dat heel weinig van de interacterende blockchains vergt:

  • Ondersteuning voor slimme contracten met minimaal één vestiging
  • Beide blockchains moeten dezelfde hash-algoritmen ondersteunen (vergeet niet de geheime lengte te controleren)
  • Tijdsloten.

Op het eerste gezicht zou je tegen de uitwisseling kunnen zeggen: “Dag, onze ontmoeting was een vergissing”, maar dat was niet zo.

Ondanks al hun voordelen zijn atomaire swapoplossingen niet erg liquide. Dit komt grotendeels doordat in het populairste valutapaar BTC-USD het fiatgedeelte niet volledig is getokeniseerd.
Het succes van USDT heeft een golf aan ERC20-stablecoins opgeleverd voor elke smaak, van de bewarende USDC tot de algoritmische DAI.

Voor de eenvoud blijven we beweren dat Alice bitcoins aan Bob verkoopt voor een aantal ERC20-tokens en hopen we op succes van de stabilisatoren. Gelukkig hebben we nog veel meer technische problemen.

snelheid

Bitcoin en Ethereum zijn los van elkaar niet zo snel. Hierbij moeten we eerst wachten op één storting met alle bevestigingen, en dan op de tweede.

Dit komt allemaal doordat eerst de deelnemer die het geheim kent, geld inlegt, en de tegenstander pas na de finale zijn deel overmaakt.

Bovendien hebben we te maken met een zeer volatiele belegging, waardoor de koers in deze periode flink kan schommelen en het niet langer eenvoudig is om de omstandigheden te veranderen.

Privacy

Elke uitwisseling laat artefacten achter op beide blockchains. Een oplettende waarnemer kan identieke hashes in smart contracts opmerken en daaruit de logische conclusie trekken dat er een deal is gesloten. Hieruit kunnen allerlei conclusies worden getrokken, van wisselkoersen tot belastingen.

Als de beurs op de hoogte is van uw zaken, is dat buitengewoon vervelend; Als iedereen ervan weet, is het dubbel vervelend.

Usability

Het sterke punt van blockchain in het algemeen en ether in het bijzonder. Laten we eens kijken welke stappen de verkoper en de koper moeten maken.

Voor de verkoper is alles relatief eenvoudig: u hoeft alleen maar bitcoins over te maken naar een p2sh-adres. Met ether is alles veel lastiger.

ContractLaten we eens kijken naar het gemiddelde contract voor swap op GitHub:

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

Waarschuwing! Gebruik dit contract of andere contracten uit het artikel niet in de productie, ze zijn alleen bedoeld ter demonstratie. Vooral deze.

  • Bob moet de methode van het tokencontract aanroepen approve, waardoor het swapcontract toegang krijgt tot zijn tokens
  • Bob creëert een swap en een contract met behulp van de methode transferFrom brengt de tokens van de afzender naar zijn adres
  • Alice in withdraw onthult het geheim en het contract wordt genoemd transfer

De meeste wallets en cryptobeurzen ondersteunen dit niet approve tokens, en wel om een ​​goede reden.

Het komt regelmatig voor dat gebruikers zelf de fout in gaan en de tokens simpelweg overzetten naar een contract, waarna de tokens simpelweg verloren gaan. De reacties op Etherscan staan ​​vol met klaagzangen van ongelukkigen.

En om een ​​contract aan te vragen, moet je een commissie betalen in ETH. Dat betekent dat beide deelnemers geld moeten inleggen voordat ze de transactie kunnen starten. En weinig mensen willen dat doen.

Gashouder

De eerste stap is om waar mogelijk het controleren van afzenders te verwijderen en ervan uit te gaan dat er iemand is die lijdt onder overtollig gas en belcontracten voor iedereen.

Gemoderniseerd contract

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

Contract-Key Dualisme en EIP 712

Zoals we weten kan een adres in de lucht een contract zijn, maar ook een onderwerp, dat wil zeggen een sleutel.
Het hoofddoel van de sleutel is het ondertekenen van berichten.

We kunnen Bob-contract als verzender gebruiken, die alle benodigde stappen uitvoert, nadat hij eerst de handtekening van Bob-key heeft geverifieerd.

Tegenwoordig kan iedereen een deelnemerscommissie sponsoren, maar alleen degene die de sleutel kent, neemt de beslissing.

Bob-contract

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

Er is een standaard voor het werken met handtekeningen van complexe datastructuren in Ethereum EIP 712, je kunt er meer over lezen in Metamask wallet-blog

Verdeel en heers

Vaak ziet het scenario voor het hacken van een Ethereum-contract er als volgt uit:

  • De deelnemer steekt geld in het contract
  • Dan neemt hij het geld
  • Er gaat iets mis
  • De oplichter neemt steeds opnieuw het geld

Als we teruggaan naar ons eerste voorbeeld, dan gaat er iets mis als het mysterie een lege set bytes is.

Hoe je een miljoen steeltMaak een swap met een hash 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Dit is sha256 van 0x0000000000000000000000000000000000000000000000000000000000000000
We geven het geheim door en nemen onze tokens
We geven het opnieuw door en nemen het van iemand anders af, allemaal omdat 0 = 0

Door voor elke transactie een apart contract te maken, kunnen we contracten op EVM-niveau isoleren.

Maar dat is nog niet alles: voortaan heeft iedere transactie een eigen adres, waarnaar u tokens kunt overmaken vanaf elke wallet of exchange.

Verlaten contracten en create2

Maar nu moeten we voor elke transactie een contract opstellen en wachten tot de koper de arbeid ‘cryptofening’ daarheen overdraagt. Bij het principe “'s ochtends contracten, 's avonds geld” bestaat altijd het gevaar dat de koper afhaakt en de ether voor het opstellen van het contract al is uitgegeven.

Is het mogelijk om het zo te maken dat er 's ochtends geld is en 's avonds bytes?

In de Constantinople hard fork hebben ontwikkelaars EIP 1014 create2-instructie toegevoegd, die een nieuw contract op een deterministisch adres creëert

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

Где

  • adres — fabriekscontractadres
  • zout - een getal waarvan we de betekenis in de volgende aflevering zullen leren
  • init_code — contractbytecode en constructorparameters.

FabriekDe instructie werkt alleen via assemblage, dus de fabriek ziet er een beetje eng uit:

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

Uw contractcode kunt u verkrijgen via 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);

Vanwege de beperkte ondersteuning in soliditeit kan het zijn dat het gas voor het contract niet correct wordt berekend vanwege enkele subtiliteiten van Ethereum.

Het is vooral fijn dat bij een gastekort het contract door een interne fout mislukt, zonder dat gemeld wordt dat er te weinig gas is, zoals wel verwacht mag worden.

We kunnen nu tokens overdragen naar contracten zonder dat we ze vooraf hoeven aan te maken. En totdat we ze op het netwerk publiceren, zal niemand raden wat het contract precies doet.

Een kraai zal niet het oog van een andere kraai uitpikken

Het is duidelijk dat een echte analist, vooral iemand die goede investeringen heeft gedaan in de strijd tegen de vijanden van het regime door middel van het witwassen van geld, zich niet laat stoppen door zulke kinderachtige trucs en dat hij na het opstellen van het contract nog steeds de hash zal zien.

Hoe zorg je ervoor dat de hash niet zichtbaar is?

We verplaatsen de swap zelf off-chain: deelnemers wisselen handtekeningen uit om de swap-overeenkomst over te dragen, en vervolgens wordt het geheim privé onthuld.

Stap voor stapEr worden twee ‘multi-sigs’ aangemaakt, waarvan geld kan worden opgenomen als Alice en Bob hun handtekeningen hebben.

Om te voorkomen dat het uit de hand loopt als een van de deelnemers offline gaat, voeren we een time-out in.

Alice en Bob doen parallel stortingen

  • Alice verzint een geheim en geeft Bob de hash van het geheim en de handtekening van de transactie waarmee de bitcoins naar het swapadres worden overgemaakt.
  • Bob geeft Alice een handtekening om tokens op te nemen in het swapcontract met de gegeven hash.
  • Alice vertelt Bob een geheim.

Op dit punt ontstaat er harmonie: zowel Alice als Bob kunnen de transactie op elk gewenst moment voltooien. In zo'n vriendelijke omgeving kunnen ze handtekeningen uitwisselen om geld op te nemen naar de eindadressen.

Voor een buitenstaander lijkt het erop dat het geld via een 2-op-2 multi-signature contract is gegaan.

Deze regeling maakt het ook mogelijk dat beide partijen tegelijkertijd een storting doen, aangezien het geheim pas na alle bevestigingen wordt onthuld.

Niveau 2

Omdat we geld naar één adres kunnen opnemen zonder een tussenliggende transactie te publiceren, belet niets ons om geld naar meerdere adressen op te nemen en een onbeperkt aantal tussenliggende transacties uit te voeren. Het is niet zo dat het een noodzakelijke set was voor de ruil, maar als je eenmaal begint met het verzamelen van ruilobjecten, kun je er moeilijk mee stoppen.

Nu kunnen Alice en Bob zich helemaal uitleven. U kunt bijvoorbeeld automatisch de gemiddelde prijs berekenen, satoshi per seconde uitwisselen of de market maker en de ontvanger van liquiditeit rechtstreeks met elkaar verbinden.

Stap voor stap

  • De verkoper maakt een geheim en geeft de koper een hash van het geheim en een handtekening van de transactie waarbij een deel van de fondsen wordt overgemaakt naar het p2sh-swapadres en de rest wordt teruggestuurd naar het adres van de verkoper.
  • De koper geeft een handtekening waarmee hij/zij toestemming geeft om de tokens en het wisselgeld over te maken naar het adres van de ontvanger, waar ze kunnen worden omgeruild.
  • De verkoper onthult het geheim
  • De geschiedenis herhaalt zich met een nieuw geheim, terwijl er naast de ruil en de verandering ook de opname is van het eerder gekochte naar het adres van de koper en het reeds betaalde naar het adres van de verkoper

Nu we toegang hebben tot supersnelle p2p-handel, is het belangrijkste om de tijd in de gaten te houden en de deal te sluiten binnen de gestelde tijd.

Met een kleine aanpassing in onze contracten kunnen we onze kanalen echter onsterfelijkheid geven, waardoor het voor ons veel gemakkelijker wordt om een ​​netwerk op te bouwen.

Maar hierover praten we in de volgende aflevering.

Bron: www.habr.com

Voeg een reactie