当前位置: 首页 > 编程日记 > 正文

【区块链Go语言实现】区块链基本原型

链客,专为开发者而生,有问必答!

此文章来自区块链技术社区,未经允许拒绝转载。

在这里插入图片描述

0x00 介绍
区块链(Blockchain)是21世纪最具革命性的技术之一,目前它仍处于逐渐成熟阶段,且其发展潜力尚未被完全意识到。从本质上讲,区块链只是一种记录的分布式数据库。但它之所以独特,是因为它并不是一个私有的数据库,而是一个公共数据库,也就是说,每个使用它的人都有一份完整或部分的数据副本。并且,只有在数据库的其他持有者同意的情况下,才可以向区块链中添加新的记录。此外,正是区块链使得加密货币和智能合约成为可能。

在本系列文章中,我们将基于区块链构建一种简单的加密货币。

0x01 区块
首先,我们从“区块链”中的“区块”介绍开始。在区块链中,区块是存储有价值信息的块。例如,比特币区块用于存储交易,这是任何一种加密货币的本质。除此之外,区块还包含一些技术信息,比如它的版本、当前时间戳和前一区块的散列值(哈希值)。

在本文中,我们不打算实现区块链或比特币规范中描述的那种区块,而是使用它的简化版本,即我们将要实现的区块结构中只包含重要的信息。下面代码中为我们的区块结构:

type Block struct {
Timestamp int64
Data []byte
PrevBlockHash []byte
Hash []byte
}
Timestamp(时间戳)是区块创建时刻的时间戳,Data是包含在区块中的实际有价值的信息,PrevBlockHas存储前一区块的散列值,而Hash是当前区块的散列值。在比特币规范中,Timestamp、PrevBlockHash和Hash是区块头,它们组成了一个单独的数据结构,而交易(在我们的例子中是Data)也是一个单独的数据结构。为了简单起见,我们此处将它们混合在一起。

那么如何计算散列值呢?散列值的计算方式是区块链的一个十分重要的特性,正是该特性使得区块链变得安全。计算一个区块的散列值是一种计算上十分困难的操作,即使在快速计算机上也需要一些时间(这就是人们会购买强大的GPU来挖比特币的原因)。这是一种有意的架构设计,它使得添加新的区块变得很困难,因此可以防止对已有区块的篡改。我们将在以后的文章中讨论并实现这种机制。

现在,我们仅仅使用区块字段,连接它们,并在连接的组合上计算一个SHA-256散列值。下面,我们使用SetHash方法来实现这一操作:

func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)

b.Hash = hash[:]

}
接下来,依照Golang惯例,我们将实现一个函数来简化区块的创建:

func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}
block.SetHash()
return block
}
这样,我们就准备好了区块的工作!

0x02 区块链
现在,我们来实现一个区块链。实质上,区块链只是一个包含某些特定结构的数据库:它是一种有序的反向链接列表。这意味着区块以插入顺序进行存储,并每个区块会链接到前一区块。这个结构能够保证快速获得一个区块链中最新的区块,并能够通过区块散列值高效地获取到该区块。

在Golang中,可以使用一个数组和一个map来实现这种结构:数组用于保存有序的散列(在Go中数组是有序的),而map用于保存散列->区块对(map是无序的)。然而,对于我们的区块链原型来说,我们仅仅使用一个数组,因为现在我们不需要通过区块的散列来获得对应的区块。

type Blockchain struct {
blocks []*Block
}
这是我们的第一个区块链,我从未想过它会这么容易。

现在我们实现添加区块的功能:

func (bc *Blockchain) AddBlock(data string) {
prevBlock := bc.blocks[len(bc.blocks)-1]
newBlock := NewBlock(data, prevBlock.Hash)
bc.blocks = append(bc.blocks, newBlock)
}
这样就完了么?No!

为了向区块链中添加一个新区块,我们需要确保已经存在了一个区块,但是目前我们的区块链中并未存在任何区块。所以,在任何区块链中,都必须存在至少一个区块,区块链中的首个区块称为创世区块。下面,我们实现一个方法来创建创世区块:

func NewGenesisBlock() *Block {
return NewBlock(“Genesis Block”, []byte{})
}
现在,我们可以实现一个函数来使用创世区块创建一个区块链:

func NewBlockchain() *Blockchain {
return &Blockchain{[]*Block{NewGenesisBlock()}}
}
下面,我们来检查一下我们的区块链是否能够正常工作:

func main() {
bc := NewBlockchain()

bc.AddBlock("Send 1 BTC to Ivan")
bc.AddBlock("Send 2 more BTC to Ivan")for _, block := range bc.blocks {fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)fmt.Printf("Data: %s\n", block.Data)fmt.Printf("Hash: %x\n", block.Hash)fmt.Println()
}

}
输出结果如下:

复制代码
Prev. hash:
Data: Genesis Block
Hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168

Prev. hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168
Data: Send 1 BTC to Ivan
Hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1

Prev. hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1
Data: Send 2 more BTC to Ivan
Hash: 561237522bb7fcfbccbc6fe0e98bbbde7427ffe01c6fb223f7562288ca2295d1
通过上面的结果,我们可以确定该区块链可以正常工作。

0x03 结论
本文中,我们创建了一个非常简单的区块链原型:它仅仅是一个区块数组,其中每个区块都有一个链接到前一区块,不过实际的区块链要比这复杂得多。在我们的区块链中,添加新的区块简单快速,但在实际的区块链中添加新区块则需要做一些工作:在获取添加区块的权限之前,区块添加者(或者说节点)必须执行一些繁重的计算(这种机制称为工作证明,Proof-of-Work,POW)。此外,区块链是一种分布式数据库,所以并没有一个唯一的决策者。因此,一个新的区块必须由网络中的其他参与者确认和批准(这种机制称为共识机制)。最后,目前我们的区块链中还没有交易!在后续的文章中我们将逐步讨论这些功能和特点。

相关文章:

python2和python3 在windows下公用 导致python2 pip无法使用 报ssl的错误

在查找资料的过程中,网上的信息说。高版本的pip是默认使用ssl,而python2的pip是不使用ssl; 本机的环境,是将python2的pip和python3的 pip做过处理的 最后会有一个叫pip2和pip3环境 有可能是我的操作失误,导致直接使用的…

阻塞队列与非阻塞队列

阻塞队列 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场…

python unicodedecodeerror utf8_python-pip install和UnicodeDecodeError:’utf-8’编...

尝试安装:pip install python-binance结果:Exception:Traceback (most recent call last):File "c:\users\анна\appdata\local\programs\python\python36\lib\site-packages\pip\compat\__init__.py", line 73, in console_to_strreturn s…

Go语言指针详解

链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 不像 Java 和 .NET,Go语言为程序员提供了控制数据结构的指针的能力;但是,并不能进行指针运算。通过给予程序员基…

java基础--日期--练习集锦

题目1 --日期 借助随机数,创建一个从1995.1.1 00:00:00 到 1995.12.31 23:59:59 之间的随机日期 package date;import java.util.Date;public class TestDate {public static void main(String[] args) {long second 1000;long minute 60*second;long hour minut…

python多变量非线性拟合_python实现多变量线性回归(Linear Regression with Multiple Variables)...

本文介绍如何使用python实现多变量线性回归,文章参考NG的视频和黄海广博士的笔记现在对房价模型增加更多的特征,例如房间数楼层等,构成一个含有多个变量的模型,模型中的特征为(x1,x2,...,xn)表示为:引入x01&#xff0c…

【bzoj3150】 cqoi2013—新Nim游戏

www.lydsy.com/JudgeOnline/problem.php?id3105 (题目链接) 题意 在第一个回合中,第一个游戏者可以直接拿走若干个整堆的火柴。可以一堆都不拿,但不可以全部拿走。第二回合也一样,第二个游戏者也有这样一次机会。从第三个回合(又…

再见,Python!你好,Go语言

链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 AI 前线导读:Go 语言诞生于谷歌,由计算机领域的三位宗师级大牛 Rob Pike、Ken Thompson 和 Robert Griesemer 写成。由于出身…

tensorflow intel platform 优化

intel平台优化 TensorFlow *是深度学习领域中主要使用的机器学习框架,要求高效利用计算资源。 为了充分利用英特尔架构和提高性能,TensorFlow *库已经使用英特尔MKL-DNN原语进行了优化,该原语是深度学习应用的流行性能库。 已进行优化的平台 …

basePath = request.getScheme()+://+request.getServerName()+:+r

basePath request.getScheme()"://"request.getServerName()":"r (2014-06-30 18:29:54) 转载▼标签: 宠物 分类: JavaString path request.getContextPath();String basePath request.getScheme()"://"request.getSe…

python dump函数_python中实现php的var_dump函数功能

最近在做python的web开发(原谅我的多变,好东西总想都学着。。。node.js也是),不过过程中总遇到些问题,不管是web.py还是django,开发起来确实没用php方便,毕竟存在的时间比较短,很多不完善的地方。比如我在调…

Go语言的Channel文章,整个人都感觉不好了

链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 Go的Channel是一个很强大的并发数据模型,在一个发送者和多个消费者情况下工作得最好,但是如果是多个发送者,那么…

图书管理系统(源码)

本文demo下载地址:http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId1070 实例使用java语言实现了一个网页版的图片管理系统, 系统前端使用bootstrap技术,可以进行浏览器适配, 实现功能: 管理图书管书, 管理图书借还信息&#xff0…

linux 如何禁用账号和解除禁用账号

把账号禁用可以有几个方法&#xff1a;1. # usermod -L <username> # usermod -U <username> // 解除禁用2. 修改/etc/passwd文件&#xff0c;可以有几个地方1&#xff09;把第二个字段中的"x"变成其它的字符&#xff0c;该账号就不能…

maya批量命名插件_教你玩转MAYA的四十二精华造诣(第一期)

最近在整理文档时发现我收藏了一篇关于MAYA应用技巧的文章&#xff0c;突然有兴趣看了看&#xff0c;结果发现老版本MAYA中的某些内容很多已经无法应用于新版本。我又上网查了一下&#xff0c;结果发现网上好多帖子和我收藏的这篇内容基本一致&#xff0c;看来好多都是转载和抄…

Go语言开发常见陷阱,你遇到过几个?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 Go作为一种简便灵巧的语言&#xff0c;深受开发者的喜爱。但对于初学者来说&#xff0c;要想轻松驾驭它&#xff0c;还得做好细节学习工作。 初学者…

sxoi爆炸祭

好吧&#xff0c;纯粹是去玩玩的&#xff0c;我这么一个弱省的蒟蒻&#xff0c;进队纯粹是开玩笑。。。。 Day0 去五中试机&#xff0c;感觉电脑手感不错&#xff0c;打了半个线段树的板子才发现试机要在自己的电脑上试&#xff0c;然后我无奈的搬东西&#xff08;从26号搬到2号…

wiki多个文件一起导入_mac文件信息管理工具EagleFiler for Mac分享给大家

EagleFiler for mac使得管理您的信息方便。它可以让你存档和搜索邮件&#xff0c;网页&#xff0c;PDF文件&#xff0c;字处理文档&#xff0c;图像&#xff0c;等等。使用它可以从不同的来源收集信息。浏览不同类型的文件采用标准的三窗格界面。组织他们到文件夹中&#xff0c…

【bzoj1951】 Sdoi2010—古代猪文

http://www.lydsy.com/JudgeOnline/problem.php?id1951 (题目链接) 题意 废话一堆。。求解&#xff1a;$$g^{\sum_{d|n} C_n^d}~mod~p$$ Solution 真的是数论经典题&#xff0c;什么都用上了。 因为费马小定理&#xff0c;每$p-1$个$g$相乘会得到$1$&#xff0c;那么容易得到&…

区块链之智能合约详解

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 什么是智能合约&#xff1f; 智能合约又称智能合同&#xff0c;是由事件驱动的、具有状态的、获得多方承认的、运行在区块链之上的、且能够根据预设…

子类化内置类型

Python 2.2之后内置类型开始可以子类化了 但是&#xff0c;CPython中的内置类型不会调用用户重写的类的特殊方法。 PyPy的文档中描述了这个问题。subclasses-of-built-in-types 正式情况下&#xff0c;CPython 并没有官方规定内置类型的子类中重写的方法是否会被隐式调用。基本…

网上商城系统源代码_多用户系统商城授权有几种方式?

网上商城系统一般都需要获取正规授权才可以投入商业使用范围&#xff0c;许多系统开发商为了适应不同企业的需求提供了几种不同的授权方式&#xff0c;企业可以选择合适的方式获得系统的使用权。下面HiShop小编就来为大家介绍一下多用户商城系统的授权方式。一、多用户系统商城…

java学习:对synchronized的测试

平时对synchronized这个关键字没有太在意&#xff0c;对它的认识停留在粗略翻了一下百度百科的状态&#xff0c;百度百科对它的解释是&#xff1a; “Java语言的关键字&#xff0c;可用来给对象和方法或者代码块加锁&#xff0c;当它锁定一个方法或者一个代码块的时候&#xff…

Selenium(3)

练习1&#xff1a;Ecshop  录制登录后退出业务  打开系统  存储页面的标题     a.点击"登录"按钮     b.输入用户名&#xff1a;testing      存储输入的用户名     c.输入密码&#xff1a;123456     d.点击"立即登录"按钮 …

php 爬虫_Rad爬虫结合W13Scan扫描器挖掘漏洞

一、背景这几天一直在研究W13Scan漏洞扫描器&#xff0c;因为对Python不是太熟悉&#xff0c;所以进度有点慢&#xff0c;一直没看懂怎么将代理请求的数据转发到扫描队列中去&#xff0c;决定先熟悉熟悉这个功能再说&#xff1b;Rad爬虫最近比较火&#xff0c;于是就是就选择它…

Python 爬取网页HTML代码

#/usr/bin/env python #-*- coding:utf-8 -*-import urllib2 import sys import chardetreq urllib2.Request("http://tycool.top/") content urllib2.urlopen(req).read() typeEncode sys.getfilesystemencoding()##系统默认编码 infoencode chardet.detect(con…

区块链兼容以太坊智能合约

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 引言 随着区块链技术以及应用的普及&#xff0c;越来越多的区块链出现在大众视野中。由于区块链技术的开源特性&#xff0c;任何公司和个人都可以…

Linux常用命令--网终设置

1、把自己&#xff08;sa&#xff09;添加到sudoers配置文件中&#xff0c;以便于获取权限 vim /etc/sudoers 编辑文件&#xff08;部分centOS版本没有vim命令&#xff0c;则用vi即可&#xff09; 找到【root ALL(ALL) ALL】语句&#xff0c;在下面添加&#xff1a; sa ALL…

python示例异常处理与程序调试_笔记:Python异常处理与程序调试

Python异常处理与程序调试Python提供了强大的异常处理机制&#xff0c;通过捕获异常可以提高程序的健壮性。异常处理还具有释放对象&#xff0c;中止循环的运行等作用。在程序运行的过程中&#xff0c;如果发生了错误&#xff0c;可以返回事先约定的一个错误代码。"try...…

js传入参数为字符串问题

示例&#xff1a; var device_mac"11qweq234ert";//第一种方式会报错&#xff1a;Onclick SyntaxError: identifier starts immediately after numeric literal&#xff0c;数字后面紧跟着字符这种写法只有device_mac是数字的时候是正确的。传入的为字符串则应该使用…