-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
535130a
commit e1e5c2a
Showing
1 changed file
with
45 additions
and
168 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,210 +1,87 @@ | ||
// const fs = require('fs'); | ||
// const crypto = require('crypto'); | ||
// const EC = require('elliptic').ec; | ||
// const ec = new EC('secp256k1'); | ||
|
||
// // Read unspent transactions (simulation) | ||
// function getUnspentTransactions() { | ||
// // This should be implemented based on the actual data storage and transaction format | ||
// return []; // Placeholder | ||
// } | ||
|
||
// // Create a message from transaction data | ||
// function createMessage(transaction, unspent) { | ||
// return crypto.createHash('sha256').update(JSON.stringify(transaction) + JSON.stringify(unspent)).digest('hex'); | ||
// } | ||
|
||
// // Verify the signature of a transaction | ||
// function verifySignature(signature, publicKey, message) { | ||
// const key = ec.keyFromPublic(publicKey, 'hex'); | ||
// return key.verify(message, Buffer.from(signature, 'hex')); | ||
// } | ||
|
||
// // Validate a single transaction | ||
// function validateTransaction(transaction) { | ||
// const unspent = getUnspentTransactions(); | ||
// return transaction.inputs.every(input => { | ||
// const details = unspent.find(tx => tx.id === input.id); | ||
// if (!details) return false; | ||
// const message = createMessage(transaction, details); | ||
// return verifySignature(input.signature, details.publicKey, message); | ||
// }); | ||
// } | ||
|
||
// // Read transactions from the mempool and validate them | ||
// // function readTransactions(mempool) { | ||
// // return fs.readdirSync(mempool).map(filename => { | ||
// // const path = `${mempool}`; | ||
// // const data = fs.readFileSync(path, 'utf8'); | ||
// // const transaction = JSON.parse(data); | ||
// // return validateTransaction(transaction) ? transaction : null; | ||
// // }).filter(tx => tx != null); | ||
// // } | ||
// function readTransactions(mempoolDirectory) { | ||
// const files = fs.readdirSync(mempoolDirectory); | ||
// const transactions = []; | ||
|
||
// files.forEach(filename => { | ||
// const path = `${mempoolDirectory}/${filename}`; | ||
// const data = fs.readFileSync(path, 'utf8'); | ||
// transactions.push(data); // Assuming data is already serialized | ||
// }); | ||
|
||
// return transactions; | ||
// } | ||
|
||
|
||
|
||
// // Create a simple coinbase transaction | ||
// function createCoinbaseTransaction(value, recipient) { | ||
// return { | ||
// inputs: [], | ||
// outputs: [{ value, address: recipient }] | ||
// }; | ||
// } | ||
|
||
// // Serialize transactions | ||
|
||
|
||
// // Compute a Merkle Root (placeholder for a real function) | ||
// function computeMerkleRoot(transactions) { | ||
// return crypto.createHash('sha256').update(transactions.join('')).digest('hex'); | ||
// } | ||
|
||
// // Mining a block satisfying the difficulty target | ||
// function mineBlock(transactions, previousHash, difficulty) { | ||
// let nonce = 0; | ||
// const target = BigInt('0x' + difficulty); | ||
|
||
// while (true) { | ||
// const timestamp = Date.now(); | ||
// const merkleRoot = computeMerkleRoot(transactions); | ||
// const blockHeader = `0001|${previousHash}|${merkleRoot}|${timestamp}|${difficulty}|${nonce}`; | ||
// const blockContent = `${blockHeader}\n${transactions.join('\n')}`; | ||
// const hash = crypto.createHash('sha256').update(blockContent).digest('hex'); | ||
|
||
// if (BigInt('0x' + hash) < target) { | ||
// return { nonce, hash, blockHeader, blockContent }; | ||
// } | ||
|
||
// nonce++; | ||
// } | ||
// } | ||
|
||
// // Main entry point | ||
// async function main() { | ||
// const transactionData = readTransactions('./mempool'); | ||
// const coinbase = createCoinbaseTransaction(50, '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'); | ||
// transactionData.unshift(coinbase); | ||
|
||
|
||
// const previousHash = '0000000000000000000000000000000000000000000000000000000000000000'; | ||
// const difficulty = '0000ffff00000000000000000000000000000000000000000000000000000000'; | ||
// const block = mineBlock(serializedTransactions, previousHash, difficulty); | ||
|
||
// fs.writeFileSync('output.txt', `${block.blockHeader}\n${serializedTransactions.join('\n')}`); | ||
// console.log(`Block mined! Nonce: ${block.nonce}, Hash: ${block.hash}`); | ||
// } | ||
|
||
// main().catch(console.error); | ||
const fs = require('fs'); | ||
const crypto = require('crypto'); | ||
const EC = require('elliptic').ec; | ||
const ec = new EC('secp256k1'); | ||
|
||
// Read unspent transactions (simulation) | ||
function getUnspentTransactions() { | ||
// This should be implemented based on the actual data storage and transaction format | ||
return []; // Placeholder | ||
// Implementation might fetch real data from a JSON file or database | ||
return JSON.parse(fs.readFileSync('./unspent.json', 'utf8')); | ||
} | ||
|
||
function serializeTransaction(transaction) { | ||
const inputs = transaction.vin.map(vin => `${vin.txid}:${vin.vout}:${vin.scriptSig}`); | ||
const outputs = transaction.vout.map(vout => `${vout.value}:${vout.scriptpubkey}`); | ||
return `${transaction.version}:${inputs.join(',')}:${outputs.join(',')}:${transaction.locktime}`; | ||
} | ||
|
||
// Create a message from transaction data | ||
function createMessage(transaction, unspent) { | ||
return crypto.createHash('sha256').update(JSON.stringify(transaction) + JSON.stringify(unspent)).digest('hex'); | ||
function createMessage(transaction) { | ||
return crypto.createHash('sha256').update(serializeTransaction(transaction)).digest('hex'); | ||
} | ||
|
||
// Verify the signature of a transaction | ||
function verifySignature(signature, publicKey, message) { | ||
const key = ec.keyFromPublic(publicKey, 'hex'); | ||
return key.verify(message, Buffer.from(signature, 'hex')); | ||
return key.verify(message, signature); | ||
} | ||
|
||
// Validate a single transaction | ||
function validateTransaction(transaction) { | ||
const unspent = getUnspentTransactions(); | ||
return transaction.inputs.every(input => { | ||
const details = unspent.find(tx => tx.id === input.id); | ||
if (!details) return false; | ||
const message = createMessage(transaction, details); | ||
return verifySignature(input.signature, details.publicKey, message); | ||
function validateTransaction(transaction, unspent) { | ||
return transaction.vin.every(input => { | ||
const utxo = unspent.find(utxo => utxo.txid === input.txid && utxo.index === input.vout); | ||
if (!utxo) return false; | ||
const msg = createMessage(transaction); | ||
return verifySignature(input.scriptSig, utxo.pubKey, msg); | ||
}); | ||
} | ||
|
||
// Read transactions from the mempool and validate them | ||
function readTransactions(mempoolDirectory) { | ||
const files = fs.readdirSync(mempoolDirectory); | ||
const transactions = []; | ||
|
||
files.forEach(filename => { | ||
const path = `${mempoolDirectory}/${filename}`; | ||
const data = fs.readFileSync(path, 'utf8'); | ||
transactions.push(data); // Assuming data is already serialized | ||
}); | ||
|
||
return transactions; | ||
return fs.readdirSync(mempoolDirectory).map(filename => { | ||
return JSON.parse(fs.readFileSync(`${mempoolDirectory}/${filename}`, 'utf8')); | ||
}).filter(tx => validateTransaction(tx, getUnspentTransactions())); | ||
} | ||
|
||
// Create a simple coinbase transaction | ||
function createCoinbaseTransaction(value, recipient) { | ||
return { | ||
inputs: [], | ||
outputs: [{ value, address: recipient }] | ||
version: 1, | ||
vin: [{ txid: '', vout: 0, scriptSig: '', pubKey: '' }], // Coinbase has no input | ||
vout: [{ value: value, scriptpubkey: recipient }], | ||
locktime: 0 | ||
}; | ||
} | ||
|
||
// Serialize transactions | ||
function serializeTransactions(transactions) { | ||
return transactions.map(tx => JSON.parse(tx)); // Parse each serialized transaction | ||
} | ||
|
||
// Compute a Merkle Root (placeholder for a real function) | ||
function computeMerkleRoot(transactions) { | ||
return crypto.createHash('sha256').update(transactions.join('')).digest('hex'); | ||
let txids = transactions.map(tx => crypto.createHash('sha256').update(serializeTransaction(tx)).digest('hex')); | ||
while (txids.length > 1) { | ||
txids = txids.reduce((acc, _, i, arr) => i % 2 ? acc : [...acc, crypto.createHash('sha256').update(arr[i] + (arr[i + 1] || '')).digest('hex')], []); | ||
} | ||
return txids[0]; | ||
} | ||
|
||
// Mining a block satisfying the difficulty target | ||
function mineBlock(transactions, previousHash, difficulty) { | ||
let nonce = 0; | ||
const target = BigInt('0x' + difficulty); | ||
const serializedTransactions = transactions.map(tx => JSON.stringify(tx)); // Serialize transactions | ||
|
||
while (true) { | ||
const timestamp = Date.now(); | ||
const merkleRoot = computeMerkleRoot(serializedTransactions); | ||
const blockHeader = `0001|${previousHash}|${merkleRoot}|${timestamp}|${difficulty}|${nonce}`; | ||
const blockContent = `${blockHeader}\n${serializedTransactions.join('\n')}`; | ||
const hash = crypto.createHash('sha256').update(blockContent).digest('hex'); | ||
|
||
if (BigInt('0x' + hash) < target) { | ||
return { nonce, hash, blockHeader, blockContent }; | ||
} | ||
let hash, header; | ||
|
||
// Loop until the hash meets the target | ||
do { | ||
nonce++; | ||
} | ||
} | ||
const merkleRoot = computeMerkleRoot(transactions); | ||
header = `${previousHash}${merkleRoot}${nonce}`; | ||
hash = crypto.createHash('sha256').update(header).digest('hex'); | ||
} while (BigInt('0x' + hash) >= target); | ||
|
||
// Main entry point | ||
return { nonce, hash, header, transactions }; | ||
} | ||
async function main() { | ||
const transactionData = readTransactions('./mempool'); | ||
const transactions = readTransactions('./mempool'); | ||
const coinbase = createCoinbaseTransaction(50, '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'); | ||
transactionData.unshift(coinbase); | ||
transactions.unshift(coinbase); | ||
|
||
const previousHash = '0000000000000000000000000000000000000000000000000000000000000000'; | ||
const difficulty = '0000ffff00000000000000000000000000000000000000000000000000000000'; | ||
const block = mineBlock(transactionData, previousHash, difficulty); // Pass transactionData instead of serializedTransactions | ||
const block = mineBlock(transactions, previousHash, difficulty); | ||
|
||
const blockData = `Block Header: ${block.hash}\nCoinbase Transaction: ${serializeTransaction(coinbase)}\nTransactions:\n${block.transactions.map(tx => serializeTransaction(tx)).join('\n')}`; | ||
|
||
fs.writeFileSync('output.txt', `${block.blockHeader}\n${block.blockContent}`); // Write blockContent instead of serializedTransactions | ||
console.log(`Block mined! Nonce: ${block.nonce}, Hash: ${block.hash}`); | ||
fs.writeFileSync('output.txt', blockData); | ||
} | ||
|
||
main().catch(console.error); | ||
main(); |