Glanz und Armut Atomtausch

Warum Atomswaps schlecht sind und wie die Kanäle ihnen helfen, was in der harten Gabel von Konstantinopel passiert ist und was zu tun ist, wenn für Benzin nichts zu bezahlen ist.

Die Hauptmotivation eines Sicherheitsexperten ist der Wunsch, Verantwortung zu vermeiden.

Die Vorsehung war gnädig, ich verließ das ICO und wartete nicht auf die erste irreversible Transaktion, sondern befand mich bald hinter der Entwicklung eines Kryptowährungsaustauschs.

Ich bin definitiv kein Malchish Kibalchish, und ein strenger Blick genügt mir, um alle Schlüssel und Passwörter zu übergeben. Mein Hauptziel als Architekt war es daher, den glühenden Stich der Kryptoanalyse so weit wie möglich von den für mich wichtigen Infrastrukturelementen zu entfernen.

Nicht deine Schlüssel, nicht deine Probleme


Wir bauen ein System für den Austausch von Vermögenswerten auf und möchten die Zwischenlagerung dieser Vermögenswerte zu Hause ausschließen, müssen jedoch die Sicherheit der Transaktion gewährleisten.

Sie können in einer kontroversen Situation als Richter auftreten und Transaktionen mit Brieftaschen durchführen, für die zwei der drei Unterschriften erforderlich sind: Käufer, Verkäufer und Treuhänder.

Wenn ein Teilnehmer jedoch eine Übertragungsurkunde erfolgreich angreift, erhält er die erforderlichen zwei Signaturen.

Atomic Swap ist ein Tauschprogramm, bei dem ein intelligenter Vertrag als Garant fungiert und nur ehrliches Verhalten zulässt.

Wie in einem Rätsel um Wolfsziege und Kohl kann man nur nach dem einzig richtigen Szenario handeln und Verluste erleiden, wenn man davon zurücktritt.

Nur anstelle von gefräßigen Tieren bietet die Reihenfolge eine Hash-Funktion, bei der es so schwierig ist, eine Kollision zu finden, dass es sich nicht lohnt, damit zu beginnen.

Erster Schritt: Das Rätsel


Angenommen, Alice möchte Bob an einem schönen Morgen Bitcoin für eine Handvoll „Krypto-Yuan“ geben.

  • Sie macht ein großes Geheimnis
  • Erhält einen Hash davon
  • Er überträgt Bitcoins in einen intelligenten Vertrag, von dem Bob Geld durch Vorlage eines Geheimnisses abheben kann (der Hash muss dem im Vertrag angegebenen entsprechen).
  • Für den Fall, dass Bob abends nicht bei seinen Bitcoins ist, kann Alice sie wieder für sich selbst auswählen.

Zweiter Schritt: Köder


Bob betritt das Spiel und überträgt "cryptoeuro" auf seinen Vertrag, der so geschrieben ist, dass:

  • Alice kann Kryptomünzen mit einer Geheimzahl aufheben
  • Spätestens zum Mittagessen kann Bob die Kaution zurückerstatten, falls Alice nicht erscheint

Schritt drei: Die Lösung im Köder


Alice kommt für ihr Geld und nimmt das Geld von Bobs Vertrag, während sie ihr Geheimnis preisgibt.

Der letzte Schritt: Das Rätsel ist gelöst


Bob sieht die Transaktion und isoliert mit seinem Blick das Geheimnis, das Alice dem Vertrag verraten hat. Mit diesem Geheimnis sammelt er seine Bitcoins.

Wenn etwas schief geht


Wenn sich Alice plötzlich als sterblich herausstellt, nimmt Bob seinen Yuan zum Mittagessen.

Am Abend gibt Alice ihrerseits Bitcoin zurück, wenn der verräterische Bob beschließt, das Geld bis zu besseren Zeiten aufzubewahren.

Wenn Sie einem Text ein Bild vorziehen, gibt es auf Habré eine detailliertere und klarere Erklärung für die Arbeit von Atomtauschern .

Die Differenz zwischen Timeouts soll uns vor der böswilligen Alice schützen, die im allerletzten Moment Bobs Geld nimmt, und die Timeout-Zeit läuft ab, während er mit zitternden Fingern das Hex in die Transaktion treibt.

Teilnehmer können ihr Geld nicht verlieren, der Höchstbetrag muss auf eine Rückerstattung warten.

Blockchain-Unterstützung
Dies ist ein einfaches Schema wie Filzstiefel, das nichts von den interagierenden Blockchains erfordert:

  • Unterstützung für intelligente Verträge mit mindestens einer Niederlassung
  • Beide Blockchains müssen die gleichen Hashing-Algorithmen unterstützen (nicht vergessen, die Länge des Geheimnisses zu überprüfen)
  • Zeitschlösser.


Auf den ersten Blick kann man zum Austausch schon sagen, "Auf Wiedersehen, unser Treffen war ein Fehler", aber es war nicht da.

Atomic-Swap-Lösungen sind trotz aller Vorzüge nicht liquiditätswirksam. Vor allem, weil im beliebtesten Paar von BTC-USD der Fiat-Teil nicht vollständig gekennzeichnet war.
Der Erfolg von USDT hat zu einer Welle stabiler Münzen im ERC20-Format für jeden Geschmack geführt, vom USDC für die Verwahrung bis zum algorithmischsten DAI.

Der Einfachheit halber argumentieren wir weiterhin, dass Alice Bobcoins für einige ERC20-Token an Bob verkauft, und wir hoffen auf den Erfolg der Stabilisatoren, da wir viel mehr technische Probleme haben.

Geschwindigkeit


Bitcoin und Ethereum alleine sind nicht zu schnell, aber hier müssen wir erst auf eine Einzahlung mit allen Bestätigungen warten, dann auf die zweite.

Dies ist alles, weil der Teilnehmer, der das Geheimnis zuerst kennt, das Geld verdient und der Gegner auf das Finale wartet und erst dann seinen Teil überträgt.

Darüber hinaus haben wir es mit einem sehr volatilen Vermögenswert zu tun, sodass sich der Kurs in dieser Zeit erheblich ändern kann und es nicht einfach ist, die Bedingungen zu ändern.

Vertraulichkeit


Jeder Austausch hinterlässt Artefakte auf beiden Blockketten. Ein aufmerksamer Beobachter kann die gleichen Hashes in intelligenten Verträgen feststellen und daraus logisch schließen, dass hier ein Geschäft abgeschlossen wurde, aus dem viele Schlussfolgerungen vom Wechselkurs zur Steuer gezogen werden können.

Wenn der Austausch über Ihre Angelegenheiten Bescheid weiß - das ist äußerst unangenehm, wenn jeder davon weiß - ist es doppelt unangenehm.

Benutzerfreundlichkeit


Das Blockchain-Pferd im Allgemeinen und der Äther im Besonderen. Mal sehen, welche Körperbewegungen der Verkäufer und der Käufer machen müssen.

Aus Sicht des Verkäufers ist alles relativ einfach: Sie müssen nur Bitcoin an eine p2sh-Adresse übertragen. Mit Äther ist alles viel schwieriger.

Der Vertrag
Betrachten Sie einen durchschnittlichen Gigab-Swap-Kontrakt:

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

Achtung! Verwenden Sie diesen und andere Verträge aus einem Produktionsartikel nicht, sie werden ausschließlich zu Demonstrationszwecken geschrieben. Besonders dieser .

  • Bob muss die approve für den Token-Vertrag aufrufen und dem Swap-Vertrag Zugriff auf seine Token gewähren
  • Bob erstellt einen Swap und ein Vertrag mit der transferFrom Methode nimmt Absendertoken an seine Adresse
  • Alice im withdraw deckt ein Geheimnis auf und der Vertrag ruft die transfer

Die meisten Brieftaschen und approve unterstützen aus gutem Grund keine approve Token.

Benutzer selbst irren sich oft und übertragen Token einfach in den Vertrag. Danach gehen die Token einfach verloren. Kommentare zu Etherscan sind voll von klagenden Elenden.

Und um einen Vertrag zu kündigen, muss an der ETH eine Provision gezahlt werden. Beide Teilnehmer müssen sich also vor Beginn der Transaktion mit ihnen eindecken, und das wollen nur wenige.

Gasbehälter


Zunächst lohnt es sich, den Scheck des Absenders zu entfernen, wo immer dies möglich ist, und vorauszusetzen, dass jemand unter überschüssigem Benzin leidet und Verträge für alle zustande bringt.

Verbesserter Vertrag
 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 Dualism und EIP 712


Wie wir wissen, kann die Adresse in der Luft ein Vertrag sein, oder es kann ein Thema sein, mit anderen Worten, ein Schlüssel.
Die Hauptbeschäftigung des Schlüssels ist das Signieren von Nachrichten.

Wir können den Bob-Vertrag als Absender verwenden, der alle erforderlichen Ausweise vornimmt, bevor die Signatur des Bob-Schlüssels überprüft wird.

Jetzt kann jeder die Provision eines Mitglieds sponsern, aber nur derjenige, der den Schlüssel kennt, trifft die Entscheidung.

Bob Vertrag
 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 verfügt über einen EIP 712- Standard für die Arbeit mit Signaturen komplexer Datenstrukturen. Weitere Informationen finden Sie im Metamask-Wallet-Blog.

Teilen und erobern


Häufig sieht das Szenario, einen Ethereum-Vertrag zu hacken, so aus:

  • Der Teilnehmer zahlt Geld auf den Vertrag
  • Dann nimmt das Geld
  • Irgendwas läuft schief
  • Ein Angreifer nimmt immer wieder Geld

Wenn wir zu unserem ersten Beispiel zurückkehren, geht etwas schief, wenn das Rätsel eine leere Byte-Menge ist.

Wie man eine Million stiehlt
Erstellen Sie einen Swap mit einem Hash 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Dies ist sha256 von 0x0000000000000000000000000000000000000000000000000000000000000000
Wir geben das Geheimnis weiter und sammeln unsere Token
Wir passieren es noch einmal und nehmen die Fremden, alle weil 0 = 0

Durch das Erstellen eines separaten Vertrags für jede Transaktion können wir Verträge auf EVM-Ebene isolieren.

Das ist aber noch nicht alles: Jetzt hat jede Transaktion ihre eigene Adresse, an die Sie Token von jedem Geldbeutel oder Geldwechsel senden können.

Verlassene Verträge und create2


Aber jetzt müssen wir für jede Transaktion einen Vertrag abschließen und warten, bis der Käufer die Arbeit „cryptofening“ dorthin transferiert. Im Schema „Morgenverträge, Abendgeld“ besteht immer die Gefahr, dass der Käufer abfällt und der Äther bereits für die Vertragserstellung aufgewendet wurde.

Kann man morgens Geld und abends Bytes verdienen?

In der Hard Fork von Konstantinopel haben die EIP 1014- Entwickler eine Anweisung create2 hinzugefügt, mit der ein neuer Vertrag an einer deterministischen Adresse erstellt wird

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

Wo

  • Adresse - Fabrikvertragsadresse
  • Salz - eine Zahl, deren Bedeutung wir in der nächsten Reihe erfahren werden
  • init_code - Vertragsbytecode und Konstruktorparameter.

Die Fabrik
Die Anleitung funktioniert nur durch Montage, daher sieht die Fabrik ein bisschen einschüchternd aus:

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

Ihren Vertragscode erhalten Sie über 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); 

Aufgrund der eingeschränkten Solidität kann es sein, dass das Gas für den Vertrag aufgrund einiger Feinheiten des Äthers nicht korrekt berechnet wird.

Besonders schön ist, dass im Falle eines Gasmangels der Vertrag mit einem internen Fehler abfällt, ohne darauf hinzuweisen, dass erwartungsgemäß nicht genug Gas vorhanden ist.

Jetzt können wir Tokens auf Verträge übertragen, ohne sie im Voraus zu erstellen, und bis wir sie im Netzwerk veröffentlichen, ahnt niemand, was genau der Vertrag bewirkt.

Der Rabe pickt die Krähe nicht aus


Es ist klar, dass die Tricks eines solchen Kindes einen echten Analytiker nicht aufhalten werden, insbesondere einen, der gute Investitionen in die Bekämpfung der Feinde des Geldwäscheregimes erhalten hat, und nach Abschluss des Vertrags wird er immer noch einen Haschisch sehen.

Wie kann man sicherstellen, dass der Hash nicht aufleuchtet?

Wir übertragen den Swap selbst an die Kette: Die Teilnehmer tauschen ihre Unterschriften aus, um sie auf einen Swap-Vertrag zu übertragen, und dann wird das Geheimnis privat gelüftet.

Schritt für Schritt
Es werden zwei "Multisig" erstellt, von denen Sie Geld abheben können, wenn Sie die Unterschriften von Alice und Bob haben.

Damit einer der Teilnehmer nicht zur Tragödie wurde, fügen wir die gute alte Auszeit hinzu.

Alice und Bob tätigen parallel Einzahlungen

  • Alice macht ein Geheimnis und gibt Bob den Hash des Geheimnisses und die Signatur der Transaktion, die die Bitcoins an die Swap-Adresse überträgt
  • Bob gibt Alice eine Unterschrift über die Entnahme von Token für einen Swap-Vertrag mit einem versteckten Hash.
  • Alice erzählt Bob das Geheimnis.


In diesem Moment entsteht Harmonie: Sowohl Alice als auch Bob können den Deal jederzeit abschließen. In einer so freundlichen Umgebung können sie Unterschriften austauschen, um Geld an ihre endgültige Adresse abzuheben.

Für einen externen Beobachter sieht es so aus, als ob das Geld einen Vertrag mit einer Mehrfachunterschrift 2 von 2 durchlaufen hat.

Und auch ein solches Schema ermöglicht es beiden Parteien, gleichzeitig eine Einzahlung zu tätigen, da das Geheimnis nach allen Bestätigungen bereits erfunden ist.

Stufe 2


Da wir Geld an eine Adresse abheben können und keine Zwischentransaktion veröffentlichen, hindert uns nichts daran, Geld an mehrere Adressen abzuheben und eine unbegrenzte Anzahl von Zwischentransaktionen durchzuführen. Nicht, dass dies ein notwendiges Set für einen Tausch gewesen wäre, aber wenn Sie mit dem Sammeln eines Swaps begonnen haben, ist es schwer aufzuhören.

Jetzt können sich Alice und Bob mit aller Kraft umdrehen. Berechnen Sie zum Beispiel automatisch den Durchschnittspreis, indem Sie Satoshi pro Sekunde tauschen, oder verbinden Sie einfach den Market Maker und den Liquiditätsempfänger direkt.

Schritt für Schritt
  • Der Verkäufer macht ein Geheimnis und gibt dem Käufer einen Hash der Geheim- und Transaktionsunterschrift, wobei ein Teil des Geldes an die p2sh-Swap-Adresse überwiesen wird und der Rest an die Adresse des Verkäufers zurückgeschickt wird
  • Der Käufer übermittelt eine Unterschrift, mit der er die Token für den Tausch und die Lieferung an die Adresse des Empfängers abheben kann.
  • Der Verkäufer verrät ein Geheimnis
  • Die Geschichte wird mit einem neuen Geheimnis wiederholt, während dem Tausch und der Übergabe die Ausgabe hinzugefügt wird, die zuvor an die Adresse des Käufers gekauft und bereits an die Adresse des Verkäufers bezahlt wurde


Jetzt haben wir Zugang zum Hochgeschwindigkeits-P2P-Handel. Die Hauptsache ist, die Zeit zu überwachen und den Deal vor dem Timeout abzuschließen.

Wenn wir jedoch unsere Verträge leicht angepasst haben, können wir unseren Kanälen Unsterblichkeit verleihen, was die Schaffung eines Netzwerks für uns erheblich vereinfacht.

Aber darüber werden wir in der nächsten Serie sprechen.

Source: https://habr.com/ru/post/de483828/


All Articles