[译]200行代码就能写出区块链

从本质上看,区块链远没有你想象的那么难!

区块链的基本概念是非常简单的:一个维护不断增长的有序数据的分布式数据库。然而当我们讨论使用区块链解决具体问题的时候,很容易把他们混为一体,比如当前非常有名的比特币和以太坊,它们往往和交易、智能合约、加密货币等概念绑在一起。

这让理解区块链变成了非常困难的事情,但区块链本质上没有这么复杂。Lauri Hartikka使用200行js代码实现一个简单的区块链,称为NaiveChain

区块结构

第一个逻辑步骤就是定义区块结构。为了让这个区块链尽可能的简单,在这个区块链中只包含一些必需元素,包括:区块索引、时间戳、区块数据、当前区块Hash、上一个区块的Hash
block
class Block {
    constructor(index, previousHash, timestamp, data, hash) {
        this.index = index;
        this.previousHash = previousHash.toString();
        this.timestamp = timestamp;
        this.data = data;
        this.hash = hash.toString();
    }
}

区块Hash

区块Hash是为了保持区块数据的完整性,这里使用的是SHA-256算法。需要注意的是这里的hash和挖矿没有关系,因为这里没有工作量证明的问题需要解决。

var calculateHash = (index, previousHash, timestamp, data) => {
    return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();
};

生成区块

为了打包一个区块,除了知道上一个区块的hash值以外,还需要得到当前区块的索引、hash、数据,以及当前的时间戳。区块数据有使用者提供。

var generateNextBlock = (blockData) => {
    var previousBlock = getLatestBlock();
    var nextIndex = previousBlock.index + 1;
    var nextTimestamp = new Date().getTime() / 1000;
    var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData);
    return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);
};

存储区块

在这里使用js的数组将区块存储在内存中。第一个区块通过硬编码完成,通常被称为创始区块。

var getGenesisBlock = () => {
    return new Block(0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");
};

var blockchain = [getGenesisBlock()];

验证区块

任何时候要具备验证一个区块或者区块链完整性的能力。尤其在从其他节点接收到一个新区块之后,当前节点必需验证该接收区块的有效性以判断是否接受。

var isValidNewBlock = (newBlock, previousBlock) => {
    if (previousBlock.index + 1 !== newBlock.index) {
        console.log('invalid index');
        return false;
    } else if (previousBlock.hash !== newBlock.previousHash) {
        console.log('invalid previoushash');
        return false;
    } else if (calculateHashForBlock(newBlock) !== newBlock.hash) {
        console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash);
        return false;
    }
    return true;
};

选择最长链

在任何一个时间点上,区块链应该是一个确定区块的集合。但是当区块存在冲突的时候(比如两个节点都生成了高度为72的区块),那么当前节点会选择最长链。
longest chain
var replaceChain = (newBlocks) => {
    if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) {
        console.log('Received blockchain is valid. Replacing current blockchain with received blockchain');
        blockchain = newBlocks;
        broadcast(responseLatestMsg());
    } else {
        console.log('Received blockchain invalid');
    }
};

节点通信

一个区块的必要模块就是同其他节点分享和同步区块链。为了保持区块链在网络中的同步,节点需要遵守以下规则:

  • 当一个节点完成打包一个区块之后,要广播到网络

  • 当一个节点连接到另一个节点之后,需要查询最新区块

  • 当一个节点接收到一个大于当前区块索引的区块之后,需要将这个区块添加到当前区块之后,或者查询整个区块链


    sync

    这里没有节点发现的功能,需要手动添加节点地址

节点管理

通过搭建一个Http服务,用户可以管理当前节点

var initHttpServer = () => {
    var app = express();
    app.use(bodyParser.json());

    app.get('/blocks', (req, res) => res.send(JSON.stringify(blockchain)));
    app.post('/mineBlock', (req, res) => {
        var newBlock = generateNextBlock(req.body.data);
        addBlock(newBlock);
        broadcast(responseLatestMsg());
        console.log('block added: ' + JSON.stringify(newBlock));
        res.send();
    });
    app.get('/peers', (req, res) => {
        res.send(sockets.map(s => s._socket.remoteAddress + ':' + s._socket.remotePort));
    });
    app.post('/addPeer', (req, res) => {
        connectToPeers([req.body.peer]);
        res.send();
    });
    app.listen(http_port, () => console.log('Listening http on port: ' + http_port));
};

用户可以通过以下方式同节点进行交互:

  • 获取区块列表
  • 创建新区快
  • 添加和查看节点

然而,管理节点的最直接方式就是通过curl命令: curl http://localhost:3001/blocks

架构

需要注意的是节点暴露了两个web服务器:一个用户管理当前节点,一个用于区块之间的p2p通信(Websocket HTTP server)

Architecture

总结

这个区块链(NaiveChain)是为了演示和学习区块链。它不能在实践中的使用,因为他没有PoS或PoW挖矿算法,然而它实现了区块链的基本特性。你可以通过 Github 仓库获取更多的技术细节。

你可以通过a tutorial for building a cryptocurrency深入理解区块链,在那里你会获得关于工作量证明、交易、钱包等相关知识。

引用

原文链接: https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54


本文由 Copernicus团队 戚帅翻译,转载无需授权。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 一、快速术语检索 比特币地址:(例如:1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV)由一串...
    不如假如阅读 15,770评论 4 88
  • 落落门前立,拨弦伴鼓鸣。 高歌如浪涌,浅唱似云行。 老叟躬身看,顽童闭口听。 当街天作幕,忘我最深情。
    尘寞阅读 212评论 15 19
  • 执着过了头就是执念,执念过了头就是禁锢,该放下时学会放下,这样才能腾出双手,抓住真正属于自己的幸福。----方莹 ...
    榴莲干阅读 1,537评论 0 7