İnce İstemciler

Bu istemci, tüm blok zincirindeki tüm bloklar için başlıkların tam bir kopyasını indirir. Bu, indirme ve depolama gereksinimlerinin, Bitcoin’in icat edilmesinden bu yana geçen süre ile doğrusal olarak ölçeklendiği anlamına gelir.

bitcore-p2p ile bir merkle bloğu isteyin

Bu örnekte bitcoin ağından merkle blok numarasını 442603 isteyeceğiz.

Bunu yapmak için bir filterload mesajı göndermemiz gerekiyor ve ardından MSG_MERKLEBLOCK envanter tipini kullanarak bir getdata mesajı göndermemiz gerekiyor.

Eşler, istenen blok için bir merkleblock mesajı ve istenen blokta filtreyle eşleşen herhangi bir işlem için bir tx mesajı ile yanıt vermelidir.

bitcore-p2p‘da, almak istediğimiz her mesajın türü için bir olay kaydetmemiz gerekiyor.

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

let network = 'livenet';  // Network can be livenet or testnet
let txs = []; // Here we store the transactions
let filteredBlocks = []; // Here we store the merkleblocks

// Date that we are loocking for
let data = {
  code: '88adcf0215d5fcbca5c6532aaecffb48128cf1a6',  // 1DTh7XPb42PgCFnuMHSitMPWxCfNNFej8n in hex fromat
  format: 'hex',
};

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

// Create a filter and a bitcoin message with the filter
let filter = BloomFilter.create(1000, 0.1).insert(new Buffer(data.code, data.format));
let filterLoad = new Messages({network: NetworksData[network]}).FilterLoad(filter);

// Create a bitcoin message for require a merkleblock
let blockHashRequested = '0000000000000000004f8325a66388e22c10e6de9f0f6e5809eaf1e0393efe02';
let getDataForFilteredBlock = new Messages({network: NetworksData[network]}).GetData.forFilteredBlock(blockHashRequested);

// Transactions and merkleblock are sent in different messages
pool.on('peertx', function(peer, message) {
  txs.push({
    peer: peer,
    message: message,
  });

  console.log('Recived from: ', peer.host);
  console.log('The transaction: ', message.transaction.hash);
});

pool.on('peermerkleblock', function(peer, message) {
  filteredBlocks.push({
    peer: peer,
    message: message,
  });

  console.log('Recived from: ', peer.host);
  console.log('The merkleBlock: ', message.merkleBlock.header.hash);
});

// Wait for pool to connect
setTimeout(function(){
  pool.sendMessage(filterLoad);
  pool.sendMessage(getDataForFilteredBlock);
}, 5000);

//Recived from:  138.68.111.63
//The merkleBlock:  0000000000000000004f8325a66388e22c10e6de9f0f6e5809eaf1e0393efe02
//Recived from:  138.68.111.63
//The transaction:  9aec6cc42ddcf5900d280f3fa598f5cdb101f00614785165f777a6856314f4d9
//Recived from:  103.3.61.48
//The merkleBlock:  0000000000000000004f8325a66388e22c10e6de9f0f6e5809eaf1e0393efe02
//Recived from:  103.3.61.48
//The transaction:  9aec6cc42ddcf5900d280f3fa598f5cdb101f00614785165f777a6856314f4d9

bitcore-p2p ile bir başlık zinciri indirin

ÖNEMLİ Bu sadece örnek bir koddur, üretimde kullanmayınız.

Bir başlık zinciri indirmek için bir getHeaders mesajı göndermemiz gerekiyor.

Bu örnekte, 40000’inci başlıktan sonra mümkün olduğu kadar çok üstbilgiye ihtiyacımız olacak. Eş, 2000 üstbilgi toplu olarak yanıt verecektir, bu nedenle, sonraki 2000 üstbilgiyi gerektirebilmek için son başlık karmasını almamız gerekir.

Bitcore-p2p’nin olay tabanlı bir kitaplık olduğu gerçeğini göz önünde bulundurun, başlık zincirini indirmek için async/await’i kullanmak için en sağlam seçenek ağ arayüzünü vaat edebilir. Burada basitlik adına, ağın asenkron doğasıyla yüzleşmek için bir jeneratör kullanacağız.

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