Spīdums un nabadzība atomu maiņām

Kādas ir atomu maiņu problēmas un kā kanāli var palīdzēt, kas svarīgs notika Constantinople hardforkā un ko darīt, kad nav naudas, lai samaksātu par gāzi.

Galvenā motivācija jebkuram drošības speciālistam ir vēlme izvairīties no atbildības.

Pavadījums bija laipns, es atstāju ICO, negaidot pirmo neatgriezenisko darījumu, bet drīz vien atrados pie kriptovalūtu biržas izstrādes.

Es — noteikti ne Es atdodu visus piekļuves atslēgas un paroli jau ar vienu stingru skatienu. Tāpēc mana galvenā mērķa kā arhitekta bija novietot karsto kritiku virzības analīzē pēc iespējas tālāk no manām mīļajām infrastruktūras daļām.

Ne tavi atslēgas, ne tavi problēmas

Mēs veidojam aktīvu maiņas sistēmu un vēlamies izslēgt to, ka šie aktīvi tiek uzglabāti pie mums, bet mums ir jānodrošina darījumu drošība.

Var darboties kā tiesnesis strīdīgā situācijā un veikt darījumus ar maciņiem, kuriem nepieciešamas divas no trim parakstiem: pircēja, pārdevēja un escrow.

Tomēr, ja dalībnieks veiksmīgi uzbrūk escrow, viņš saņem divus nepieciešamos parakstus.

Atomu maiņa — apmaiņas shēma, kur garantu realizē viedais līgums, kas pieļauj tikai godīgu uzvedību.

Tāpat kā mīklā par vilku, kazu un kāpostu, tu vari rīkoties tikai saskaņā ar vienīgo pareizo scenāriju un ciest zaudējumus, ja no tā atkāpies.

Tikai vietā neizsalkušiem dzīvniekiem kārtību nodrošina hash funkcija, kurā ir tik grūti atrast koliziju, ka to pat nevajadzētu sākt.

Pirmais solis: mīkla

Pieņem, ka Alise kādā jaukā rītā vēlas nodot Bobam Bitcoin pret sauju “kriptovienību”.

  • Viņa nosaka kādu lielu noslēpumu
  • Saņem no viņa hash
  • Nodod Bitcoin uz viedā līguma, no kura naudu var paņemt Bobs, uzrādot noslēpumu (hash no tā ir jāsakrīt ar līgumā norādīto)
  • Ja Bobs neierodas pēc saviem Bitcoin vakarā, Alise var tos atgūt sev.

Otrais solis: vilinājums

Spēlē iesaistās Bobs un pārskaita “kriptovienības” uz savu līgumu, kurš ir uzrakstīts tā, ka:

  • Alise var atgūt “kriptovienības”, uzrādot slepeno numuru
  • Nepārvietojoties uz pusdienām, Bobs, ja Alise neierodas, var atgriezt depozītu

Trešais solis: atminējums vilinājumā

Alise nāk pēc saviem naudas līdzekļiem un paņem naudu no Boba līguma, atklājot savu noslēpumu.

Noslēdzošais solis: mīkla atrisināta

Bobam ir redzama transakcija, un ar ērgļa aci viņš izvelk no tās noslēpumu, ko Alise ir prezentējusi. Šo noslēpumu viņš izmanto, lai paņemtu savus bitkoinus.

Kad kaut kas noiet greizi

Ja Alise pēkšņi izrādās, ka viņa ir mirstīga, Bobam pusdienu laikā jāpaņem savi juani.

Savukārt Alise vakarā atgriež bitkoinus, ja nelabais Bobs nolemj paturēt naudu līdz labākiem laikiem.

Ja dodat priekšroku attēlam pār tekstu, tad Habrā jums ir detalizētāka un vizuālāka atomāro apmaiņu darbības skaidrojums.

Atšķirība starp laika ierobežojumiem ir paredzēta, lai pasargātu mūs no ļaunprātīgas Alises, kura pēdējā brīdī paņem Boba naudu, un laika ierobežojums izbeidzas, kamēr viņš ar trīcošām rokām ievada hex transakcijā.

Dalībnieki nevar zaudēt savus līdzekļus, maksimums, būs jāpagaida atgriešana.

Atbalsts blokķēdēsTā ir vienkārša, kā apavu zole, shēma, kas prasa no mijiedarbības bloku ķēdēm visu ko:

  • Atbalsts viedajiem līgumiem ar vismaz vienu zaru
  • Abām blokķēdēm jāatbalsta vienādi hash algoritmi (neaizmirstiet pārbaudīt noslēpuma garumu)
  • Laika ierobežojumi.

Uz pirmo acu uzmetienu, jau varētu teikt biržai "uz redzēšanos, mūsu tikšanās bija kļūda", bet ne jau tā.

Neskatoties uz visām savām priekšrocībām, risinājumi, kas balstīti uz atomāro apmaiņu, nepārsteidz ar likviditāti. Lielākoties tāpēc, ka vispopulārākajā BTC-USD pārī fiat naudas daļa nebija pilnībā tokenizēta.
USDT panākumi radīja veselu vilni stabilu monētu formātā ERC20 pēc izvēles, sākot no konservatīvāka USDC līdz algoritmiskākām DAI.

Tāpēc, lai atvieglotu, mēs turpmāk spriežam par to, ka Alise pārdod Bobam bitkoinus par kādiem ERC20 tokeniem, un ceram uz stabilizatoru veiksmi, jo mums vēl ir daudz tehnisku problēmu.

Ātrums

Bitkoini un Ethereum paši par sevi nav īpaši ātri, un tagad mums vispirms ir jāgaida viens depozīts ar visām apstiprinājumiem, tad otrais.

Tas viss ir tāpēc, ka vispirms naudu iemaksā dalībnieks, kuram ir zināms noslēpums, bet pretinieks gaida gala rezultātu, un tikai tad pārvieto savu daļu.

Turklāt mēs strādājam ar ļoti svārstīgu aktīvu, tāpēc šajā laikā kurss var ievērojami mainīties, un ir grūti mainīt nosacījumus.

Konfidencialitāte

Jebkura apmaiņa atstāj artefaktus abos blokķēdēs. Uzmanīgs novērotājs var pamanīt vienādus hash kodus viedo līgumu ietvaros un izdarīt loģisku secinājumu, ka šeit notikusi darījums, no kā var izdarīt daudz secinājumu, sākot no kursu līdz nodokļu jautājumiem.

Kad par taviem darījumiem zina birža — tas ir ļoti nepatīkami, kad par to zina ikviens — tas ir divreiz nepatīkami.

Lietojamība

Blokķēdes stiprā puse vispār un Ētera īpaši. Apskatīsim, kādas darbības jāveic pārdevējam un pircējam.

No pārdevēja skatpunkta viss ir salīdzinoši vienkārši: vienkārši jāpārskaita bitkoini uz p2sh adresi. Ar Ēteru viss ir daudz sarežģītāk.

LīgumsApskatīsim vidējo līgumu, kas pieejams GitHub, maiņas veikšanai:

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

Uzmanību! Nelietojiet šo un citus līgumus no raksta ražošanā, tie ir rakstīti vienīgi demonstrēšanai. Īpaši šis.

  • Bobs jāizsauc līguma metode approve, dodot maiņas līgumam piekļuvi viņa tokeniem
  • Bobs izveido maiņu un līgumu, izmantojot metodi transferFrom pārvācot uz savu adresi sūtītāja tokenus
  • Alise withdraw atklāj noslēpumu un līgums izsauc pārsūtīt

Lielākā daļa seifu un kriptobiržu neatbalsta approve tokenus, un tam nav pārsteiguma.

Paši lietotāji bieži kļūdās un vienkārši pārsūta tokenus uz līgumu, pēc kā tie vienkārši pazūd. Komentāri Etherscan ir piepildīti ar nelaimīgas publikas sūdzībām.

Un, lai izsauktu līgumu, jāmaksā komisija ETH, tas nozīmē, ka abiem dalībniekiem pirms darījuma jābūt tādiem, kas ir sagatavojuši ETH, bet to maz kas vēlas darīt.

Gāzes turētājs

Vispirms vajadzētu noņemt sūtītāja pārbaudi visur, kur vien iespējams, un pieņemt, ka mums ir kāds, kas cieš no gāzes pārpalikuma un zvana uz līgumiem visiem, kas vēlas.

Modernizēts līgums

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

Līguma atslēgu dualitāte un EIP 712

Kā mēs zinām, adrese Ethereum var būt līgums, un var būt arī subjekts, proti, atslēga.
Galvenā atslēgas darbība ir parakstīt jebkādus ziņojumus.

Mēs varam izmantot kā sūtītāju Boba līgumu, kas veic visus nepieciešamos pārsūtījumus, iepriekš pārbaudot Boba atslēgas parakstu.

Tagad ikviens var sponsorēt dalībnieka komisiju, bet lēmumu pieņem tikai tas, kurš zina atslēgu.

Boba līgums

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

Lai strādātu ar parakstiem sarežģītām datu struktūrām Ethereum, pastāv standarts EIP 712, vairāk par to jūs varat izlasīt Metamask maku emuārā

Dalīšana un valdīšana

Bieži vien Ethereum līguma uzlaušanas scenārijs izskatās šādi:

  • Dalībnieks ieliek līgumā līdzekļus
  • Pēc tam izņem līdzekļus
  • Kaut kas noiet greizi
  • Uzbrucējs atkārtoti izņem naudu

Ja mēs atgriezīsimies pie mūsu pirmā piemēra, kaut kas noiet greizi, ja mīkla ir tukšs baitu komplekts.

Kā nozagt miljonuIzveidojam maiņu ar hash 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Tas ir sha256 no 0x0000000000000000000000000000000000000000000000000000000000000000
Pārskaitām noslēpumu un izņemam savus tokenus
Pārskaitām vēlreiz un izņemam svešus, viss dēļ tā, ka 0 = 0

Izveidojot atsevišķu līgumu katrai darījumu, mēs varam izolēt līgumus EVM līmenī.

Bet tas vēl nav viss: tagad katram darījumam ir sava adrese, uz kuru var nosūtīt tokenus no jebkura maka vai biržas.

Atstāto līgumu un create2

Bet tagad katram darījumam mums jāizveido līgums un jāgaida, kamēr pircējs nosūtīs tur savu darbu "kriptofēningu". Shēmā "no rīta līgumi, vakarā nauda" vienmēr pastāv risks, ka pircējs atkāpsies, bet ēters šī līguma izveidei jau ir iztērēts.

Vai nevarētu izdarīt tā, ka no rīta nauda, bet vakarā baiti?

Hardforkā Constantinople izstrādātāji EIP 1014 piekļāva komandu create2, kas izveido jaunu līgumu noteiktā adresē

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

Kur

  • address — rūpnīcas līguma adrese
  • salt — kāds skaitlis, kura jēgu mēs uzzināsim nākamajā sērijā
  • init_code — līguma baitkods un konstruktora parametri.

RūpnīcaInstrukcija darbojas tikai caur assembly, tāpēc rūpnīca izskatās nedaudz biedējoši:

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

Jūsu līguma kodu var iegūt ar 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);

Dēļ ierobežotas atbalsta solidity gāze līgumam var tikt nepareizi aprēķināta dēļ dažām detaļām par ēteru.

Īpaši jauki, ka gadījumā, ja gāzes ir par maz, līgums sabrūk ar iekšēju kļūdu, neziņojot, ka gāzes trūkst, kā to varētu gaidīt.

Tagad mēs varam pārvērst tokenus līgumos, nemaz neizveidojot tos iepriekš, un līdz brīdim, kad mēs tos publicēsim tīklā, neviens nezinās, ko tieši dara līgums.

Vārds vārdam aci neizsist.

Ir skaidrs, ka īstu analītiķi, īpaši tos, kas saņēmuši labus ieguldījumus cīņā pret režīma ienaidniekiem ar naudas atmazgāšanu, šādas bērnišķīgas trikus neapturēs, un pēc līguma izveides viņš tomēr redzēs hešu.

Kā panākt, lai hešs neiznāk?

Pašu swapu mēs pārejam off-chain: dalībnieki apmainās ar parakstiem, lai pārceltos uz swap-līgumu, bet tad noslēpums tiek atklāts privāti.

Solis pa solim.Tiek izveidoti divi "multisig", no kuriem var paņemt līdzekļus, ja ir Alises un Boba paraksti.

Lai kāda dalībnieka iziešana no tiešsaistes dzīves nesanāktu par traģēdiju, pievienosim veco labā laika ierobežojumu.

Alise un Bob jau vienlaikus veic depozītus.

  • Alise nosaka noslēpumu un nodod Bobam hešu noslēpuma un darījuma parakstu, kurā bitcoin tiek pārvietots uz swap adresi.
  • Bob nodod Alisei parakstu par tokenu izņemšanu uz swap līgumu ar nosvērto hešu.
  • Alise informē Bobu par noslēpumu.

Šajā brīdī iestājas harmonija: gan Alise, gan Bobs var jebkurā brīdī noslēgt darījumu. Šādā draudzīgā vidē viņi var apmainīties ar parakstiem, lai izņemtu naudu uz galīgajām adresēm.

Ārējā novērotāja acīm tas izskatās, it kā nauda būtu pārgājusi caur līgumu ar multiparaksta 2 no 2.

Un šāda shēma ļauj abām pusēm vienlaikus veikt depozītu, jo noslēpums tiek izvēlēts jau pēc visiem apstiprinājumiem.

Līmenis 2.

Tā kā mēs varam izņemt naudu uz vienu adresi un nepubliskot starpposma darījumu, nekas nepārtrauc mūs izņemt naudu uz vairākiem adresēm un veikt neierobežotu skaitu starpposma darījumu. Nevis tas, ka tas būtu obligāts komplekts apmaiņai, bet, ja esi sācis veidot swapu, grūti apstāties.

Tagad Alise un Bobs varēs pilnībā izpausties. Piemēram, automātiski aprēķināt vidējo cenu, apmainoties pa satoshi sekundē, vai vienkārši tieši savienot tirgus veidotāju ar likviditātes saņēmēju.

Solis pa solim.

  • Pārdevējs nosaka noslēpumu un nodod pircējam hešu noslēpuma un darījuma parakstu, kurā daļa līdzekļu tiek pārvietota uz p2sh adresi swapam, bet atlikums tiek atgriezts pārdevēja adresē.
  • Pircējs nodod parakstu, kas ļauj pārsūtīt uz swap tokenus un atlikumu uz saņēmēja adresi.
  • Pārdevējs atklāj noslēpumu
  • Vēsture atkārtojas ar jaunu noslēpumu, pie tam swapam un atlikumam tiek pievienots arī iepriekš iegādātā un uz pārdevēja adresi jau samaksātā pārskaitījuma izpilde uz pircēja adresi.

Tagad mums ir pieejama augstas veiktspējas p2p tirdzniecība, galvenais ir sekot līdzi laikam un noslēgt darījumu pirms termiņa beigām.

Tomēr, nedaudz pielāgojot mūsu līgumus, mēs varam dāvāt mūsu kanāliem nemirstību, kas ievērojami atvieglos tīkla veidošanu.

Bet par to mēs runāsim nākamajā sērijā.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster