使用 bitcore-p2p 下載標題鏈

重要事項這只是一個示例程式碼,不要在生產中使用。

為了下載標題鏈,我們必須傳送 getHeaders 訊息

在這個例子中,我們將在第 40000 個之後需要儘可能多的頭。對等體將響應批量的 2000 個頭,因此,我們必須採用最後的頭雜湊才能夠需要下一個 2000 頭。

考慮到 bitcore-p2p 是一個基於事件的庫的事實,最強大的選項可以是網路介面,以便使用 async / await 來下載頭鏈。為簡單起見,我們將使用生成器來面對網路的非同步特性。

let Messages = require('bitcore-p2p').Messages;
let Pool = require('bitcore-p2p').Pool;
let NetworksData = require('bitcore-lib').Networks;

let network = 'livenet';
let headers = [];          // do not do that in production!
let validHeaders = [];     // do not do that in production!
let firsHeader = '000000000000000004ec466ce4732fe6f1ed1cddc2ed4b328fff5224276e3f6f';

// Isatnciate and connect a node Pool
let pool = new Pool({network: NetworksData[network]});
pool.connect();

// we have to reverese the hash becaouse is in the format xxxx0000 instead of 0000xxxx or vice versa
function reverseHash(hash){
  return hash.match(/.{1,2}/g).reverse().join('');
}

// check if the response is the one associate with the last request becaouse could be a response associate to an old request
function isValidResponse(firstHeaderRecived, headerHashRequested){
  // the header hash of the block before the first block header that we get on the response
  let headerHashBeforeFirstHeaderRecived = reverseHash(firstHeaderRecived.prevHash.toString('hex'));
  if (headerHashBeforeFirstHeaderRecived === headerHashRequested){
    return true;
  }
  else{
    return false;
  }
}

pool.on('peerheaders', function(peer, message) {
  let lastHeaderHashRequested;
  if (validHeaders[validHeaders.length -1]) {
    lastHeaderHashRequested = validHeaders[validHeaders.length -1].hash;
  }
  else {
    lastHeaderHashRequested = firsHeader;
  }
  if (isValidResponse(message.headers[0], lastHeaderHashRequested) && headers.length === 0) {
    headers.push({
      peer: peer,
      message: message,
    });

    console.log('Recived from: ', peer.host, message.headers.length, 'headers');
    console.log('The first block hash is', message.headers[0].hash);
    console.log('The last block hash is', message.headers[message.headers.length - 1].hash);

    syncronize.next();
    //console.log(syncronize)
  }
});

function* sync(lastHash) {
  let startHash = new Buffer(lastHash, 'hex');
  let message = new Messages({network: NetworksData[network]}).GetHeaders();
  // require as much as possible headers after startHash
  message.starts.push(startHash);
  pool.sendMessage(message);
  yield;
  validHeaders.push(...headers[0].message.headers);
  headers = [];
  let lastDownloadedHeader = validHeaders[validHeaders.length - 1];
  if (validHeaders.length % 2000 === 0) {
    yield * sync(reverseHash(lastDownloadedHeader.hash));
  }
}

syncronize = sync(reverseHash(firsHeader));

// Wait for pool to connect
setTimeout(function(){
  console.log(pool);
  syncronize.next();
}, 5000);