Per què els intercanvis atòmics són dolents i com els ajudaran els canals, quines coses importants van passar a la bifurcació dura de Constantinoble i què fer quan no teniu res a pagar per la gasolina.
La principal motivació de qualsevol especialista en seguretat és el desig d'evitar responsabilitats.
Providence va ser misericordiosa, vaig deixar l'ICO sense esperar la primera transacció irreversible, però aviat em vaig trobar desenvolupant un intercanvi criptogràfic.
Definitivament no sóc Malquish Kibalchish, i amb una mirada severa n'hi ha prou per lliurar-me totes les claus i contrasenyes. Per tant, el meu principal objectiu com a arquitecte va ser situar el punt al vermell de la criptoanàlisi el més lluny possible dels elements d'infraestructura estimats per mi.
Ni les teves claus, ni els teus problemes
Estem construint un sistema d'intercanvi d'actius i volem eliminar l'emmagatzematge intermedi d'aquests actius, però hem de garantir la seguretat de la transacció.
Podeu actuar com a jutge en una situació controvertida i realitzar transaccions amb carteres que requereixin dues de les tres signatures: comprador, venedor i depòsit.
Tanmateix, si el participant ataca amb èxit l'escrow, rebrà les dues signatures necessàries.
L'intercanvi atòmic és un esquema d'intercanvi on el garant és un contracte intel·ligent que només permet un comportament honest.
Com si en un endevinalla sobre un llop, una cabra i una col, només es pot actuar segons l'únic escenari correcte i patir pèrdues si se'n desvia.
Només en comptes d'animals voraços, l'ordre ve donat per una funció hash en la qual és tan difícil trobar una col·lisió que no val la pena començar.
Primer pas: endevinalla
Suposem que l'Alice un bon matí vol donar a Bob un bitcoin per un grapat de "cripto-yuan".
- Ella està fent un gran secret
- En treu un hash
- Transfereix bitcoins a un contracte intel·ligent, del qual Bob pot retirar diners presentant un secret (el hash del mateix ha de ser igual a l'especificat al contracte)
- Si Bob no es presenta als seus bitcoins al vespre, l'Alice els pot tornar a ella mateixa.
Segon pas: esquer
Bob entra en joc i transfereix "cripto-euro" al seu contracte, que està escrit de tal manera que:
- L'Alice pot treure "cripto-yens" presentant un número secret
- No abans del dinar, Bob pot tornar el dipòsit si l'Alice no es presenta.
Tercer pas: la resposta està en l'esquer
L'Alice ve a buscar els seus diners i agafa els diners del contracte d'en Bob, revelant el seu secret en el procés.
Pas final: l'enigma està resolt
Bob veu la transacció, i amb el seu ull d'àguila n'extreu el secret que l'Alícia va presentar al contracte. Utilitza aquest secret per recuperar els seus bitcoins.
Quan les coses van malament
Si l'Alice de sobte resulta ser mortal, en Bob agafa el seu iuan al dinar.
Al seu torn, l'Alice torna el bitcoin al vespre si el traïdor Bob decideix retenir els diners fins a temps millors.
Si prefereixes una imatge al text, Habré en té una de més detallada i visual. .
La diferència entre els temps d'espera està dissenyada per assegurar-nos contra la maliciosa Alice, que agafa els diners d'en Bob a l'últim moment, i el temps d'espera caduca mentre entra a l'hexagonal a la transacció amb els dits tremolosos.
Els participants no poden perdre els seus diners; com a màxim, hauran d'esperar a rebre un reemborsament.
Suport a BlockchainAquest és un esquema senzill que no requereix res de les cadenes de blocs interactuant:
- Suport per a contractes intel·ligents amb almenys una sucursal
- Les dues cadenes de blocs han de suportar els mateixos algorismes de hash (recordeu comprovar la longitud del secret)
- Blocs de temps.
A primera vista, ja és possible dir a la borsa “adéu, la nostra trobada va ser un error”, però no va ser així.
Malgrat tots els seus avantatges, les solucions d'intercanvi atòmic no impressionen per la seva liquiditat. En gran part perquè en el parell BTC-USD més popular, la part fiat no estava completament tokenitzada.
L'èxit de l'USDT ha donat lloc a tota una onada de monedes estables en el format ERC20 per a tots els gustos, des de l'USDC més custodiat fins al DAI més algorítmic.
Per tant, per senzillesa, argumentem a més que l'Alice ven Bitcoins a Bob per unes fitxes ERC20, i esperem la sort dels estabilitzadors, ja que encara tenim molts més problemes tècnics.
Accelerar
Bitcoin i Ethereum no són molt ràpids individualment, però aquí hem d'esperar primer un dipòsit amb totes les confirmacions i després el segon.
Tot això és perquè el participant que coneix el secret primer diposita els diners, i l'oponent espera la finalitat i només després transfereix la seva part.
A més, estem davant d'un actiu molt volàtil, de manera que durant aquest temps la taxa pot canviar de manera força important, i canviar les condicions ja no és fàcil.
Confidencialitat
Qualsevol intercanvi deixa artefactes en ambdues cadenes de blocs. Un observador atent pot notar els mateixos hash en els contractes intel·ligents i arribar a una conclusió lògica que s'ha completat una transacció, de la qual es poden extreure moltes conclusions des del tipus de canvi fins a l'impost.
Quan la borsa coneix els teus assumptes, és extremadament desagradable; quan tothom ho sap, és doblement desagradable.
Usabilitat
El punt fort de la cadena de blocs en general i de l'èter en particular. A veure quins gestos hauran de fer el venedor i el comprador.
Des del punt de vista del venedor, tot és relativament senzill: només cal transferir Bitcoin a una adreça p2sh. Amb l'èter, tot és molt més complicat.
ContracteVegem la mitjana del contracte a Github per a un intercanvi:
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);
}
}
Atenció! No utilitzeu aquest i altres contractes de l'article en producció, només estan escrits amb finalitats demostratives. Sobretot aquest.
- Bob ha d'anomenar el mètode del contracte de testimoni
approve, donant accés al contracte d'intercanvi als seus testimonis - Bob crea l'intercanvi i el contracte mitjançant el mètode
transferFromporta els testimonis del remitent a la vostra adreça - Alícia entra
withdrawrevela el secret i el contracte cridatransfer
La majoria de carteres i intercanvis criptogràfics no admeten approve fitxes, i per una bona raó.
Els mateixos usuaris solen cometre errors i simplement transfereixen fitxes al contracte, després de la qual cosa simplement es perden. Els comentaris a Etherscan estan plens de laments dels desgraciats.
I per trucar a un contracte, cal pagar una comissió en ETH, la qual cosa significa que els dos participants s'han d'aprovisionar abans d'iniciar la transacció, i poca gent vol fer-ho.
Porta gas
Un bon lloc per començar és eliminar el xec del remitent sempre que sigui possible i suposar que tenim algú que pateix un excés de contractes de trucades de gas per a tots els que vinguin.
Contracte actualitzat
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);
}
}
Dualisme de claus de contracte i EIP 712
Com sabem, una adreça en antena pot ser un contracte, o pot ser un tema, és a dir, una clau.
La funció principal de la clau és signar alguns missatges.
Podem utilitzar el Bob-contract com a remitent, que fa totes les passades necessàries, després d'haver comprovat primer la signatura de Bob-key.
Ara, qualsevol pot patrocinar la comissió d'un participant, però només qui en coneix la clau pren la decisió.
Bob-contracte
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 té un estàndard per treballar amb signatures d'estructures de dades complexes , podeu llegir-ne més informació a
Divideix i conquista
Sovint, l'escenari per piratejar un contracte Ethereum és el següent:
- El participant diposita fons al contracte
- Llavors agafa els fons
- Alguna cosa va malament
- L'atacant agafa els diners una i altra vegada
Si tornem al nostre primer exemple, alguna cosa va malament si l'enigma és un conjunt buit de bytes.
Com robar un milióCreeu un intercanvi amb un hash 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Això és sha256 de 0x0000000000000000000000000000000000000000000000000000000000000000
Transferim el secret i agafem les nostres fitxes
Tornem a transmetre i agafem la d'una altra persona, tot perquè 0 = 0
En crear un contracte independent per a cada comerç, podem aïllar els contractes a nivell d'EVM.
Però això no és tot: ara cada transacció té la seva pròpia adreça, a la qual podeu transferir fitxes des de qualsevol cartera o intercanvi.
Contractes abandonats i crear2
Però ara per a cada transacció hem de crear un contracte i esperar que el comprador hi transfereixi la "criptografia" de mà d'obra. En l'esquema "contractes al matí, diners al vespre", sempre hi ha el perill que el comprador caigui i l'èter ja s'ha gastat en crear el contracte.
És possible fer-ho perquè tingueu diners al matí i bytes al vespre?
Desenvolupadors a la bifurcació dura de Constantinoble va afegir la instrucció create2, que crea un nou contracte en una adreça determinista
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]
On
- adreça — adreça del contracte de fàbrica
- sal - algun nombre, el significat del qual aprendrem a la propera sèrie
- init_code — codi de bytes del contracte i paràmetres del constructor.
FàbricaLa instrucció només funciona mitjançant el muntatge, de manera que la fàbrica sembla una mica espantosa:
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);
}
}
El vostre codi de contracte es pot obtenir mitjançant 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);
A causa del suport limitat en la solidesa, el gas per a un contracte es pot calcular incorrectament a causa d'algunes subtileses de l'èter.
És especialment agradable que en cas d'escassetat de gas, el contracte s'enfonsi amb un error intern, sense informar que no hi havia prou gas, com era d'esperar.
Ara podem transferir fitxes als contractes sense crear-los per endavant, i fins que no els publiquem a la xarxa, ningú endevinarà què fa exactament el contracte.
Un corb no picotejarà un ull de corb
És evident que un autèntic analista, sobretot aquell que ha rebut bones inversions en la lluita contra els enemics del règim amb el blanqueig de diners, no es veurà aturat per trucs tan infantils, i després de crear el contracte encara veurà el hash.
Com evitar que es mostri el hash?
Transferim l'intercanvi en si mateix a l'offchain: els participants intercanvien signatures per transferir-los a un contracte d'intercanvi, i després el secret es revela de manera privada.
Pas a pasEs creen dos "multisigs" dels quals es poden retirar fons si Alice i Bob tenen signatures.
Per evitar que qualsevol dels participants es converteixi en una tragèdia sense connexió, afegirem un bon temps d'espera.
L'Alice i el Bob fan dipòsits en paral·lel
- L'Alice endevina un secret i li dóna a Bob un hash del secret i una signatura de transacció que transfereix els bitcoins a l'adreça d'intercanvi.
- Bob dóna a l'Alice una signatura per retirar fitxes d'un contracte d'intercanvi amb un hash ocult.
- L'Alice li diu a Bob un secret.
En aquest moment, arriba l'harmonia: tant l'Alice com el Bob poden completar l'acord en qualsevol moment. En un entorn tan amigable, poden intercanviar signatures per retirar diners a les adreces finals.
Per a un observador extern, sembla que els diners van passar per un contracte múltiple de 2 de 2.
Aquest esquema també permet que ambdues parts facin un dipòsit al mateix temps, ja que el secret es revela després de totes les confirmacions.
nivell 2
Com que podem retirar diners a una adreça i no publicar una transacció intermèdia, res no ens impedeix retirar diners a diverses adreces i fer un nombre il·limitat de transaccions intermèdies. No és que aquest sigui un conjunt necessari per a un intercanvi, però un cop comenceu a recollir un intercanvi, és difícil aturar-lo.
Ara l'Alice i el Bob podran girar-se amb totes les seves forces. Per exemple, calculeu automàticament el preu mitjà intercanviant satoshi per segon o simplement connecteu directament el creador de mercat i el destinatari de la liquiditat.
Pas a pas
- El venedor fa un secret i dóna al comprador un hash del secret i una signatura de transacció on part dels fons es transfereixen a l'adreça d'intercanvi p2sh i la resta es retorna a l'adreça del venedor.
- El comprador envia una signatura que permet que les fitxes d'intercanvi i el canvi s'enviïn a l'adreça del destinatari.
- El venedor revela el secret
- La història es repeteix amb un nou secret i, a més de l'intercanvi i el canvi, s'afegeix la retirada del que s'ha comprat anteriorment a l'adreça del comprador i ja pagat a l'adreça del venedor.
Ara tenim accés al comerç p2p d'alta velocitat, el més important és fer un seguiment del temps i tancar l'acord abans del temps d'espera.
Tanmateix, ajustant una mica els nostres contractes, podem donar immortalitat als nostres canals, cosa que ens facilitarà molt la construcció d'una xarxa.
Però d'això en parlarem en el proper episodi.
Font: www.habr.com
