Dapp-Development

DApp 如何使用 web3.js 或其他庫檢測分叉或鏈重組?

  • November 30, 2020

以投票 DApp 為例。使用者點擊投票按鈕,然後在幕後在區塊鏈上探勘交易,最後 DApp 告訴使用者他們的投票已被記錄。

現在由於某種原因,發生了鏈重組(可能使用者的節點失去並重新獲得了網路連接)。

DApp 如何使用 web3.js 來檢測這一點,以便它可以檢查使用者的交易是否已被撤消以及使用者是否需要再次送出投票?web3.js 是否會觸發事件來通知 DApp?是否有任何程式碼片段,例如要監聽什麼事件以及如何監聽?或者有沒有使用範例的庫?

這是等待指定數量的塊並驗證交易收據仍然有效的程式碼。如果發生分叉並且重放失敗,則收據檢查應該失敗,並且回調將呼叫並設置錯誤。

我只測試了它的成功和超時失敗,我沒有在區塊鏈的實際分支上測試它,因為我還沒有弄清楚如何在測試框架中可靠地導致這種情況發生。感謝有關如何做到這一點的任何提示。

根據問題,它只使用 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 $$- 出氣大於等於,不大於…

引用自:https://ethereum.stackexchange.com/questions/1187