Как DApp может обнаружить реорганизацию fork или chain с помощью web3.js или дополнительных библиотек?

Возьмем пример голосования DApp. Пользователь нажимает кнопку голосования, а затем за кулисами транзакция добывается на блочной цепочке, и, наконец, DApp сообщает пользователю о своем голосовании.

Теперь по какой-то причине существует реорганизация сети (возможно, узел пользователя потерял и восстановил сетевое подключение).

Как DAPP может использовать web3.js для обнаружения этого, чтобы он мог проверить, отменена ли транзакция пользователя, и если пользователь должен снова отправить свой голос? Запускает ли web3.js событие для уведомления DApp? Есть ли фрагменты кода, например, какое событие прослушивать и как? Или есть библиотеки с примерами их использования?

19 голосов | спросил eth 9 FebruaryEurope/MoscowbTue, 09 Feb 2016 10:16:03 +0300000000amTue, 09 Feb 2016 10:16:03 +030016 2016, 10:16:03

4 ответа


14

Вот код, который ждет указанного количества блоков и проверяет, что квитанция транзакции остается действительной. Если возникает вилка, и повтор не выполняется, проверка чека должна завершиться неудачно, и обратный вызов вызовет с установкой ошибки.

Я тестировал это только для неудач с успехом и таймаутом, я не тестировал его на фактической вилке блочной цепи, потому что я не понял, как надежно заставить это произойти еще в тестовой среде. Оцените любые подсказки о том, как это сделать.

В вопросе он использует только вызовы web3.js и библиотеки. Я должен сказать вам, что использование обратных вызовов вместо обещаний очень болезненно для меня; -P

Я не реализовал проверку транзакций несколькими узлами RPC, но есть примечание в коде о том, где это сделать. Вероятно, вы захотите использовать как минимум Async.join, что будет внешней библиотекой.

 //
 // @method awaitBlockConsensus
 // @param web3s[0] is the node you submitted the transaction to,  the other web3s 
 //    are for cross verification, because you shouldn't trust one node.
 // @param txhash is the transaction hash from when you submitted the transaction
 // @param blockCount is the number of blocks to wait for.
 // @param timout in seconds 
 // @param callback - callback(error, transaction_receipt) 
 //
 exports.awaitBlockConsensus = function(web3s, txhash, blockCount, timeout, callback) {
   var txWeb3 = web3s[0];
   var startBlock = Number.MAX_SAFE_INTEGER;
   var interval;
   var stateEnum = { start: 1, mined: 2, awaited: 3, confirmed: 4, unconfirmed: 5 };
   var savedTxInfo;
   var attempts = 0;

   var pollState = stateEnum.start;

   var poll = function() {
     if (pollState === stateEnum.start) {
       txWeb3.eth.getTransaction(txhash, function(e, txInfo) {
         if (e || txInfo == null) {
           return; // XXX silently drop errors
         }
         if (txInfo.blockHash != null) {
           startBlock = txInfo.blockNumber;
           savedTxInfo = txInfo;
           console.log("mined");
           pollState = stateEnum.mined;
         }
       });
     }
     else if (pollState == stateEnum.mined) {
         txWeb3.eth.getBlockNumber(function (e, blockNum) {
           if (e) {
             return; // XXX silently drop errors
           }
           console.log("blockNum: ", blockNum);
           if (blockNum >= (blockCount + startBlock)) {
             pollState = stateEnum.awaited;
           }
         });
     }
    else if (pollState == stateEnum.awaited) {
         txWeb3.eth.getTransactionReceipt(txhash, function(e, receipt) {
           if (e || receipt == null) {
             return; // XXX silently drop errors.  TBD callback error?
           }
           // confirm we didn't run out of gas
           // XXX this is where we should be checking a plurality of nodes.  TBD
           clearInterval(interval);
           if (receipt.gasUsed >= savedTxInfo.gas) {
             pollState = stateEnum.unconfirmed;
             callback(new Error("we ran out of gas, not confirmed!"), null);
           } else {
             pollState = stateEnum.confirmed;
             callback(null, receipt);
           }
       });
     } else {
       throw(new Error("We should never get here, illegal state: " + pollState));
     }

     // note assuming poll interval is 1 second
     attempts++;
     if (attempts > timeout) {
       clearInterval(interval);
       pollState = stateEnum.unconfirmed;
       callback(new Error("Timed out, not confirmed"), null);
     }
   };

   interval = setInterval(poll, 1000);
   poll();
 };

[EDIT 1] - из газа больше или равно, не больше ...

ответил Paul S 10 AMpSun, 10 Apr 2016 02:04:26 +030004Sunday 2016, 02:04:26
4

Я не могу прокомментировать, существует или нет функция для этого в web3. Я знаю, что у Geth and Mist есть транзакция. Это означает, что в случае реорганизации он будет обрабатывать транзакции, которые были «потеряны» во время реорганизации, поэтому теоретически состояние должно быть одинаковым.

ответил Maran 9 FebruaryEurope/MoscowbTue, 09 Feb 2016 10:54:59 +0300000000amTue, 09 Feb 2016 10:54:59 +030016 2016, 10:54:59
3

В настоящее время я не думаю, что есть способ сделать это. В настоящее время документы говорят, что просто подождите 12 блоков, чтобы убедиться, что жесткая вилка не произошла и использовать getCode (). https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcontract

ответил VoR0220 9 AMpSat, 09 Apr 2016 00:10:20 +030010Saturday 2016, 00:10:20
1

В API веб-интерфейса, события контрактов раздела , он что объект, заданный обратному вызову, имеет поле removed. Если вы слушаете свое событие и происходит реорганизация, вы должны получать уведомление о событии, в котором removed установлен в true.

Я никогда не пробовал этого, но если правильно понимать документ, он должен работать.

ответил nbremond 29 AMpSat, 29 Apr 2017 11:15:29 +030015Saturday 2017, 11:15:29

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132