主要功能
區(qū)塊鏈js實現(xiàn)
鏈條防篡改
交易簽名
挖礦
const sha256 = require('crypto-js/sha256')
const EClib = require('elliptic').ec
const ec = new EClib('secp256k1') // curve name
class Transaction {
constructor (from, to, amount) {
this.from = from
this.to = to
this.amount = amount
}
computeHash () {
return sha256(
this.from + this.to + this.amount
).toString()
}
sign (key) { // 私鑰
this.signature = key.sign(this.computeHash(), 'base64').toDER('hex')
}
isValid () { // 公鑰
if (this.from === '') {
return true
}
const keyObj = ec.keyFromPublic(this.from, 'hex')
return keyObj.verify(this.computeHash(), this.signature)
}
}
class Block {
constructor (transaction, previousHash) {
this.transaction = transaction
this.nonce = 1
this.timesramp = Date.now()
this.previousHash = previousHash
this.hash = this.computeHash()
}
computeHash () {
return sha256(JSON.stringify(this.transaction) + this.previousHash + this.nonce + this.timesramp).toString()
}
static getAnswer (difficulty) {
let answer = ''
for (let i = 0; i < difficulty; i++) {
answer += '0'
}
return answer
}
mine (difficulty) {
this.validateBlockTransactions()
while (true) {
this.hash = this.computeHash()
if (this.hash.substring(0, difficulty) !== Block.getAnswer(difficulty)) {
this.nonce += 1
this.hash = this.computeHash()
} else {
break
}
}
return this.hash
}
validateBlockTransactions () {
for (let transaction of this.transaction) {
if (!transaction.isValid()) {
console.log('驗證失敗')
return false
}
}
return true
}
}
class Chain {
constructor (difficulty = 2, minerReward = 50) {
this.chain = [Chain.bigBang()]
this.transactionPool = []
this.minerReward = minerReward
this.difficulty = difficulty
}
static bigBang () {
return new Block('Genesis Block', '')
}
getLastBlockPreviousHash () {
return this.chain[this.chain.length - 1].hash
}
addTransactionToPool (transaction) {
if (!transaction.isValid()) {
console.log('驗證簽名失敗')
return
}
this.transactionPool.push(transaction)
}
addBlockToChain (newBlock) {
if (this.verifyPreviousHash()) {
newBlock.previousHash = this.getLastBlockPreviousHash()
// newBlock.hash = newBlock.mine(this.difficulty)
this.chain.push(newBlock)
}
}
mineTransactionPool (minerRewardAddress) {
const minerRewardTransaction = new Transaction(
'',
minerRewardAddress,
this.minerReward
)
this.transactionPool.push(minerRewardTransaction)
const newBlock = new Block(
this.transactionPool,
this.getLastBlockPreviousHash()
)
newBlock.mine(this.difficulty)
this.addBlockToChain(newBlock)
this.transactionPool = []
}
verifyPreviousHash () {
for (let i = 0; i < this.chain.length; i++) {
const nowStock = this.chain[i]
if (i === 0) {
if (nowStock.hash !== nowStock.computeHash()) {
console.log('第一個數(shù)據(jù)被篡改')
return false
}
} else {
const previousStock = this.chain[i - 1]
if (nowStock.hash !== nowStock.computeHash() || nowStock.previousHash !== previousStock.hash) {
console.log('后面的數(shù)據(jù)被篡改')
return false
}
}
}
return true
}
}
const chain = new Chain()
const keyPairSender = ec.genKeyPair()
const privateKeySender = keyPairSender.getPublic('hex')
const publickKeySender = keyPairSender.getPublic('hex')
const keyPairReceiver = ec.genKeyPair()
const privateKeyReceiver = keyPairSender.getPublic('hex')
const publickKeyReceiver = keyPairSender.getPublic('hex')
const t1 = new Transaction(keyPairSender, keyPairReceiver, 10)
t1.sign(keyPairSender)
console.log(t1)
console.log(t1.isValid())
// const t2 = new Transaction(keyPairSender, keyPairReceiver, 50)
chain.addTransactionToPool(t1)
// chain.addTransactionToPool(t2)
chain.mineTransactionPool(keyPairSender)
console.log(chain.chain[1].transaction)
console.log(chain)