Loading...
Loading...

Высокая сложность = Дольше создание блокаНизкая сложность = Быстрее создание блокаБольше майнеров = Стабильное время блокаМеньше майнеров = Нестабильное времяСредний размер блока: ~50-100 KBТранзакций в блоке: 100-300Максимальный размер: ~1 MBБлоков в день: ~7,200Блоков в год: ~2,628,000// Пример хешированияconst blockData = { number: 18500000, transactions: [...], timestamp: 1699123456, // ... другие данные};
const blockHash = keccak256(JSON.stringify(blockData));// Результат: "0xabcd1234efgh5678ijkl9012mnop3456qrst7890uvwx..."Блок #1 ← Блок #2 ← Блок #3 ← Блок #4 ↑ ↑ ↑ ↑Hash_1 Hash_2 Hash_3 Hash_4// Проверка связи блоковfunction validateBlockchain(blocks) { for (let i = 1; i < blocks.length; i++) { const currentBlock = blocks[i]; const previousBlock = blocks[i - 1];
// Проверяем, что текущий блок ссылается на предыдущий if (currentBlock.parentHash !== previousBlock.hash) { return false; // Цепь нарушена! }
// Проверяем правильность хеша текущего блока if (currentBlock.hash !== calculateHash(currentBlock)) { return false; // Блок поврежден! } } return true; // Цепь целая!}// Блок содержит массив транзакций{ number: 18500000, transactions: [ { hash: "0x1234...", from: "0xabcd...", to: "0xefgh...", value: "1000000000000000000", // 1 ETH gas: 21000, gasPrice: "20000000000" }, { hash: "0x5678...", from: "0xijkl...", to: "0xmnop...", value: "500000000000000000", // 0.5 ETH gas: 21000, gasPrice: "25000000000" }, // ... еще 148 транзакций ]}Приоритет транзакций:1. Gas Price: 100 gwei → Первая в блоке2. Gas Price: 50 gwei → Вторая в блоке3. Gas Price: 20 gwei → Третья в блоке... Root Hash / \ Hash(A+B) Hash(C+D) / \ / \ Hash(A) Hash(B) Hash(C) Hash(D) | | | | Tx A Tx B Tx C Tx D// Проверка наличия транзакции в блокеfunction verifyTransaction(txHash, merkleProof, rootHash) { let currentHash = txHash;
for (const proof of merkleProof) { if (proof.position === 'left') { currentHash = keccak256(proof.hash + currentHash); } else { currentHash = keccak256(currentHash + proof.hash); } }
return currentHash === rootHash;}// Майнер собирает транзакции из мемпулаconst mempool = getMempool(); // Получаем неподтвержденные транзакцииconst selectedTxs = mempool .sort((a, b) => b.gasPrice - a.gasPrice) // Сортируем по цене газа .slice(0, 200); // Берем первые 200 транзакцийconst blockHeader = { number: previousBlock.number + 1, timestamp: Date.now(), parentHash: previousBlock.hash, transactionsRoot: calculateMerkleRoot(selectedTxs), miner: minerAddress, gasLimit: 30000000, gasUsed: calculateGasUsed(selectedTxs),};let currentState = previousBlock.state;
for (const tx of selectedTxs) { try { const result = executeTransaction(tx, currentState); currentState = result.newState; receipts.push(result.receipt); } catch (error) { // Транзакция провалилась, но газ все равно списывается receipts.push({ status: 'failed', gasUsed: tx.gasLimit }); }}const finalBlock = { header: { ...blockHeader, stateRoot: calculateStateRoot(currentState), receiptsRoot: calculateMerkleRoot(receipts), }, transactions: selectedTxs, receipts: receipts,};
finalBlock.header.hash = calculateHash(finalBlock.header);function validateBlock(block, previousBlock) { // Проверка связи с предыдущим блоком if (block.header.parentHash !== previousBlock.hash) { return false; }
// Проверка номера блока if (block.header.number !== previousBlock.number + 1) { return false; }
// Проверка временной метки if (block.header.timestamp <= previousBlock.timestamp) { return false; }
// Проверка всех транзакций for (const tx of block.transactions) { if (!validateTransaction(tx)) { return false; } }
return true;}Block Height: 18,500,000Timestamp: Nov-04-2023 02:30:45 PM +UTCTransactions: 187 transactionsMiner: 0x742d35Cc6634C0532925a3b8D4C9db96590c6C87Block Reward: 2.1 ETHDifficulty: 58,750,003,716,598,352,816,469Total Difficulty: 58,750,003,716,598,352,816,469Size: 85,432 bytesGas Used: 29,970,123 (99.9%)Gas Limit: 30,000,000Gas Utilization: 99.9% (почти полный блок)Average Gas Price: 25 gweiTotal Transaction Fees: 0.749 ETHBlock Reward + Fees: 2.849 ETHБлоков в день: ~7,200Транзакций в день: ~1,200,000Средний размер блока: 75 KBСредняя цена газа: 20-50 gweiВремя между блоками: 12.1 секунды2015 (запуск): 1-5 транзакций в блоке2017 (ICO бум): 50-100 транзакций в блоке2020 (DeFi лето): 150-200 транзакций в блоке2023 (сейчас): 200-300 транзакций в блокеconst Web3 = require('web3');const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_PROJECT_ID');
// Получение последнего блокаasync function getLatestBlock() { const block = await web3.eth.getBlock('latest'); console.log('Последний блок:', block.number); console.log('Транзакций в блоке:', block.transactions.length); console.log('Время создания:', new Date(block.timestamp * 1000)); return block;}
// Получение конкретного блокаasync function getBlockByNumber(blockNumber) { const block = await web3.eth.getBlock(blockNumber, true); // true = включить транзакции return block;}async function analyzeBlock(blockNumber) { const block = await web3.eth.getBlock(blockNumber, true);
console.log(`=== Анализ блока ${blockNumber} ===`); console.log(`Время: ${new Date(block.timestamp * 1000)}`); console.log(`Майнер: ${block.miner}`); console.log(`Транзакций: ${block.transactions.length}`); console.log(`Использовано газа: ${block.gasUsed} / ${block.gasLimit}`); console.log(`Размер: ${block.size} байт`);
// Анализ транзакций let totalValue = 0; let totalFees = 0;
for (const tx of block.transactions) { totalValue += parseFloat(web3.utils.fromWei(tx.value, 'ether')); totalFees += parseFloat( web3.utils.fromWei((tx.gasPrice * tx.gas).toString(), 'ether'), ); }
console.log(`Общая сумма переводов: ${totalValue.toFixed(2)} ETH`); console.log(`Общие комиссии: ${totalFees.toFixed(4)} ETH`);}// Подписка на новые блокиasync function monitorNewBlocks() { console.log('Начинаем мониторинг новых блоков...');
const subscription = web3.eth.subscribe('newBlockHeaders');
subscription.on('data', async (blockHeader) => { console.log(`🆕 Новый блок: ${blockHeader.number}`); console.log(`⏰ Время: ${new Date(blockHeader.timestamp * 1000)}`); console.log(`⛏️ Майнер: ${blockHeader.miner}`); console.log(`⛽ Газ: ${blockHeader.gasUsed}/${blockHeader.gasLimit}`); console.log('---');
// Получаем полную информацию о блоке const fullBlock = await web3.eth.getBlock(blockHeader.number); console.log(`📦 Транзакций в блоке: ${fullBlock.transactions.length}`); });
subscription.on('error', console.error);}// Поиск всех транзакций конкретного адреса в диапазоне блоковasync function findTransactionsByAddress(address, fromBlock, toBlock) { const transactions = [];
for (let blockNum = fromBlock; blockNum <= toBlock; blockNum++) { const block = await web3.eth.getBlock(blockNum, true);
for (const tx of block.transactions) { if ( tx.from.toLowerCase() === address.toLowerCase() || tx.to?.toLowerCase() === address.toLowerCase() ) { transactions.push({ blockNumber: blockNum, transactionHash: tx.hash, from: tx.from, to: tx.to, value: web3.utils.fromWei(tx.value, 'ether'), }); } }
// Показываем прогресс if (blockNum % 100 === 0) { console.log(`Обработано блоков: ${blockNum - fromBlock + 1}`); } }
return transactions;} Block A ← Block B ← Block C (основная цепь) ↗Genesis ↘ Block A' (uncle block, отброшен) Block A ← Block B ← Block C (старая версия) ↗Genesis ↘ Block A' ← Block B' ← Block C' (новая версия)// Обработка реорганизацииweb3.eth.subscribe('newBlockHeaders').on('data', async (blockHeader) => { const currentBlock = await web3.eth.getBlock(blockHeader.number); const previousBlock = await web3.eth.getBlock(blockHeader.number - 1);
// Проверяем, есть ли реорганизация if (currentBlock.parentHash !== previousBlock.hash) { console.log('🔄 Обнаружена реорганизация блоков!'); console.log( `Блок ${blockHeader.number} не следует за блоком ${blockHeader.number - 1}`, );
// Нужно пересканировать последние блоки await handleReorganization(blockHeader.number); }});Ethereum:- Лимит газа: ~30M gas- Размер блока: ~100 KB- Транзакций в секунду: ~15 TPS
Bitcoin:- Размер блока: 1 MB- Транзакций в секунду: ~7 TPS// Пример работы с Layer 2 (Polygon)const polygonWeb3 = new Web3('https://polygon-rpc.com');
// Блоки в Polygon создаются быстрееconst polygonBlock = await polygonWeb3.eth.getBlock('latest');console.log('Время блока Polygon:', polygonBlock.timestamp);console.log('Транзакций:', polygonBlock.transactions.length);// Демонстрация чувствительности хешаconst crypto = require('crypto');
const data1 = 'Block data version 1';const data2 = 'Block data version 2'; // Изменили только одну цифру
const hash1 = crypto.createHash('sha256').update(data1).digest('hex');const hash2 = crypto.createHash('sha256').update(data2).digest('hex');
console.log('Hash 1:', hash1);console.log('Hash 2:', hash2);console.log('Полностью разные хеши!');// Проверка целостности цепи блоковfunction validateBlockchain(blocks) { for (let i = 1; i < blocks.length; i++) { const current = blocks[i]; const previous = blocks[i - 1];
// Проверяем связь if (current.parentHash !== previous.hash) { throw new Error(`Блок ${i} не связан с предыдущим!`); }
// Проверяем хеш if (current.hash !== calculateBlockHash(current)) { throw new Error(`Блок ${i} поврежден!`); } }
console.log('✅ Блокчейн целый и невредимый!');}// Симуляция попытки атакиfunction simulate51PercentAttack() { console.log('🚨 Симуляция 51% атаки');
const networkHashrate = 1000; // TH/s const attackerHashrate = 510; // 51%
if (attackerHashrate > networkHashrate / 2) { console.log('⚠️ Атакующий может переписать блоки!'); console.log('💰 Стоимость атаки: миллиарды долларов'); console.log('⏰ Время на подготовку: месяцы'); } else { console.log('✅ Сеть защищена от атаки'); }}// Проверка разумности временных метокfunction validateTimestamp(block, previousBlock) { const maxDrift = 15 * 60; // 15 минут const currentTime = Math.floor(Date.now() / 1000);
// Блок не может быть из будущего if (block.timestamp > currentTime + maxDrift) { throw new Error('Блок из будущего!'); }
// Блок должен быть после предыдущего if (block.timestamp <= previousBlock.timestamp) { throw new Error('Блок старше предыдущего!'); }
return true;}

