摘要:介紹了一些關(guān)于比特幣的概念與機制,為了加深理解,本文基于來實現(xiàn)一個簡單的區(qū)塊鏈原型,后續(xù)再對其進行不斷豐富。概述如前所述區(qū)塊鏈模型的組成部分,包括區(qū)塊,區(qū)塊構(gòu)成的區(qū)塊鏈,以及保存區(qū)塊鏈的數(shù)據(jù)持久層等。
介紹了一些關(guān)于比特幣的概念與機制,為了加深理解,本文基于JavaScript來實現(xiàn)一個簡單的區(qū)塊鏈原型,后續(xù)再對其進行不斷豐富。1. 概述
如前所述區(qū)塊鏈模型的組成部分,包括區(qū)塊,區(qū)塊構(gòu)成的區(qū)塊鏈,以及保存區(qū)塊鏈的數(shù)據(jù)持久層等。一個超簡單的UML類圖如下:
由于我是前端的,業(yè)余看了這么久區(qū)塊鏈的理論,還是手癢癢謝謝代碼,把這個類用JavaScript實現(xiàn)一下。寫完之后發(fā)現(xiàn)目前階段,對于區(qū)塊鏈原型來說還是太過簡單,不過如果說用來做前端面試題,考察下面向?qū)ο蠛蚉romise等知識點倒是挺接洽。
摘取比特幣區(qū)塊的詳情進行修改,去除所有多余信息,只留下能描述區(qū)塊最基本的信息,聲明區(qū)塊類如下:
class Block { constructor(data) { // 區(qū)塊的屬性值 this.hash = ""; this.height = 0; this.body = data; this.time = 0; this.previousBlockHash = ""; } } module.exports.Block = Block;3. 數(shù)據(jù)持久層
其實用數(shù)組實現(xiàn)區(qū)塊鏈是最簡單的原型方案,但每次重啟數(shù)組都會被清空,數(shù)據(jù)并不持久。所以這里引入levelDB數(shù)據(jù)庫作為持久層來保存數(shù)據(jù),相關(guān)操作可參考level。由于直接調(diào)用API,對于應(yīng)用層來說過于麻煩,所以在此聲明一個數(shù)據(jù)操作類LevelSandbox,該類不像傳統(tǒng)的關(guān)系型數(shù)據(jù)庫具有增、刪、改、查等全部功能,由于區(qū)塊鏈上數(shù)據(jù)的不可更改性,此類只包含增和查的操作。
3.1 根據(jù)key從數(shù)據(jù)庫中獲取數(shù)據(jù)本文如下相關(guān)異步實現(xiàn),都采用Promise的方式而非回調(diào),其中好處作為前端工程師此處就不多介紹了,有需要了解的可異步Promise介紹,自行擴展閱讀。
getLevelDBData(key) { let self = this; return new Promise(function(resolve, reject) { self.db.get(key) .then(value => { console.log("Value = " + value); resolve(value) }) .catch(err => { console.log("Not found!"); reject(err) }) }); }3.2 將key/value數(shù)據(jù)插入數(shù)據(jù)庫中
以key/value的方式在數(shù)據(jù)庫中存儲,其key值得選取,這里考慮使用區(qū)塊類中聲明的height字段,該字段標識一個區(qū)塊在鏈中的位序,同時也具有唯一性,非常合適。
addLevelDBData(key, value) { let self = this; return new Promise(function(resolve, reject) { self.db.put(key, value) .then(() => resolve()) .catch((err) => { console.log("Block " + key + " submission failed"); reject(err) }) }); }3.3 獲取數(shù)據(jù)庫中區(qū)塊總數(shù)
createReadStream()方法創(chuàng)建一個讀取數(shù)據(jù)庫的流,這里的作用是為了遍歷整庫以獲取存儲的區(qū)塊總數(shù),另外此方法還可通過傳參,設(shè)置遍歷次序,詳情可參閱文檔。
getBlocksCount() { let self = this; return new Promise(function(resolve, reject){ let height = 0; self.db.createReadStream() .on("data", function () { height++; }) .on("error", function (error) { reject("Unable to read data stream!", error); }) .on("close", function () { resolve(height); }); }); }4. 區(qū)塊鏈類
該類主要負責將新創(chuàng)建的區(qū)塊添加進區(qū)塊鏈,并驗證鏈中各個區(qū)塊的數(shù)據(jù)完整性。這個過程中少不了對區(qū)塊數(shù)據(jù)的哈希處理,為方便起見,采用第三方庫crypto-js實現(xiàn)的SHA256方法。
構(gòu)想該類中的主要方法包括:
createGenesisBlock():生成起始區(qū)塊
getBlockHeight():獲取區(qū)塊鏈長度
getBlock(height):獲取指定區(qū)塊
addBlock(block):將一個新區(qū)塊加入?yún)^(qū)塊鏈中
validateBlock(block):驗證某個區(qū)塊
validateChain():驗證區(qū)塊鏈
如下便實現(xiàn)其中主要的幾個方法:
4.1 增加新區(qū)塊各個區(qū)塊通過previousBlockHash屬性,依次指向前一個區(qū)塊來連接成鏈的,除首區(qū)塊該屬性為空外。
addBlock(block) { return this.getBlockHeight() .then(height => { 區(qū)塊高度 block.height = height; // UTC 時間戳 block.time = new Date().getTime().toString().slice(0, -3); if (height > 0) { this.getBlock(height - 1) .then(preBlock => { // 前一個區(qū)塊的哈希值 block.previousBlockHash = preBlock.hash; // 對區(qū)塊進行哈希處理 block.hash = SHA256(JSON.stringify(block)).toString(); // 將新區(qū)快存入庫中 this.bd.addLevelDBData(height, JSON.stringify(block)); }) .catch(error => console.log(error)); } else { block.hash = SHA256(JSON.stringify(block)).toString(); this.bd.addLevelDBData(height, JSON.stringify(block)); } }) .catch( error => console.log(error)); }4.2 驗證單個區(qū)塊完整性
驗證方法就是應(yīng)用了hash算法的性質(zhì):相同的數(shù)據(jù)經(jīng)過hash后會生成相同的hash值。
validateBlock(height) { // 獲取區(qū)塊的值 return this.getBlock(height) .then(block => { const objBlock = JSON.parse(block); let blockHash = objBlock.hash; objBlock.hash = ""; // 重新生成區(qū)塊的哈希值 let validBlockHash = SHA256(JSON.stringify(objBlock)).toString(); objBlock.hash = blockHash; // 比較以驗證完整性 if (blockHash === validBlockHash) { return Promise.resolve({isValidBlock: true, block: objBlock}); } else { console.log("Block #"+blockHeight+" invalid hash: "+blockHash+"<>"+validBlockHash); return Promise.resolve({isValidBlock: false, block: objBlock}); } }) }4.3 驗證整個區(qū)塊鏈
通過依次校驗每個區(qū)塊以驗證整條鏈的完整性。
validateChain() { let errorLog = []; let previousHash = ""; this.getBlockHeight() .then(height => { for (let i = 0; i < height; i++) { this.getBlock(i) .then(block => this.validateBlock(block.height)) .then(({isValidBlock, block}) => { if (!isValidBlock) errorLog.push(i); if (block.previousBlockHash !== previousHash) errorLog.push(i); previousHash = block.hash; if (i === height - 1) { if (errorLog.length > 0) { console.log(`Block errors = ${errorLog.length}`) console.log(`Blocks: ${errorLog}`) } else { console.log("No errors detected") } } }) } }) }5. 生成測試數(shù)據(jù)
(function theLoop (i) { setTimeout(function () { let blockTest = new Block.Block("Test Block - " + (i + 1)); myBlockChain.addBlock(blockTest).then((result) => { console.log(result); i++; if (i < 10) theLoop(i); }); }, 10000); })(0);
作為一個區(qū)塊鏈原型的樣子算是初見端倪,但就目前的功能來說還非常簡陋,說是原型都算抬舉了,不過后面慢慢再豐富吧。這里也只算是對之前的一個實踐性的小節(jié)。
文中以列出主要代碼片段,整體實現(xiàn)其實不難,沒貼出所有代碼主要是為了表述思路更清晰些,若有朋友實現(xiàn)過程中有問題,可文下留言交流。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/24691.html
摘要:介紹了一些關(guān)于比特幣的概念與機制,為了加深理解,本文基于來實現(xiàn)一個簡單的區(qū)塊鏈原型,后續(xù)再對其進行不斷豐富。概述如前所述區(qū)塊鏈模型的組成部分,包括區(qū)塊,區(qū)塊構(gòu)成的區(qū)塊鏈,以及保存區(qū)塊鏈的數(shù)據(jù)持久層等。 介紹了一些關(guān)于比特幣的概念與機制,為了加深理解,本文基于JavaScript來實現(xiàn)一個簡單的區(qū)塊鏈原型,后續(xù)再對其進行不斷豐富。 1. 概述 如前所述區(qū)塊鏈模型的組成部分,包括區(qū)塊,區(qū)塊...
摘要:合約編寫可以看出合約需要實現(xiàn)用戶投注生成隨機數(shù)發(fā)放獎勵獎池余額查詢的功能,接下來編寫我們的合約代碼??偨Y(jié)當前隨機數(shù)的實現(xiàn)通過鏈上信息生成,這種生成隨機數(shù)的方式容易受到不誠實的節(jié)點攻擊。 導(dǎo)讀:本文旨在引導(dǎo)對 DApp 開發(fā)感興趣的開發(fā)者,構(gòu)建一個基于以太坊去中心化應(yīng)用,通過開發(fā)一款功能完備的競猜游戲,邁出 DApp 開發(fā)的第一步,通過實例講解 Solidity 語言的常用語法,以及前端...
摘要:我的這篇文章沒有任何高大上的術(shù)語,就是行代碼,實現(xiàn)一個最簡單的區(qū)塊鏈原型。檢查該區(qū)塊鏈是否有效。而通過在循環(huán)里不斷嘗試最終得到一個合法的哈希值的這一過程,就是區(qū)塊鏈圈內(nèi)俗稱的挖礦。 不知從什么時候起,區(qū)塊鏈在網(wǎng)上一下子就火了。 showImg(https://segmentfault.com/img/remote/1460000014744826); 這里Jerry就不班門弄斧了,網(wǎng)上...
摘要:我的這篇文章沒有任何高大上的術(shù)語,就是行代碼,實現(xiàn)一個最簡單的區(qū)塊鏈原型。檢查該區(qū)塊鏈是否有效。而通過在循環(huán)里不斷嘗試最終得到一個合法的哈希值的這一過程,就是區(qū)塊鏈圈內(nèi)俗稱的挖礦。 不知從什么時候起,區(qū)塊鏈在網(wǎng)上一下子就火了。 showImg(https://segmentfault.com/img/remote/1460000014744826); 這里Jerry就不班門弄斧了,網(wǎng)上...
摘要:本文將基于語言構(gòu)建簡化版的,來實現(xiàn)數(shù)字貨幣。值用于確保的安全。計算是計算敏感的操作,即使在高性能電腦也需要花費一段時間來完成計算這也就是為什么人們購買高性能進行比特幣挖礦的原因。資料源代碼精通比特幣第二版 showImg(https://segmentfault.com/img/remote/1460000013923206?w=1600&h=900); 最終內(nèi)容請以原文為準:http...
閱讀 2764·2021-09-24 09:47
閱讀 4382·2021-08-27 13:10
閱讀 3036·2019-08-30 15:44
閱讀 1303·2019-08-29 12:56
閱讀 2607·2019-08-28 18:07
閱讀 2627·2019-08-26 14:05
閱讀 2593·2019-08-26 13:41
閱讀 1278·2019-08-26 13:33