使用 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);