主页 > 华为手机如何下载imtoken钱包 > 6个重要模块,带你写一个基于Golang的区块链公链demo! | 精选博客文章
6个重要模块,带你写一个基于Golang的区块链公链demo! | 精选博客文章
出品 | 区块链训练营(blockchain_camp)
好久没和大家一起练习了。 不知道你是不是也很痒?
今天给大家带来的是一个基于Golang编写的区块链公链demo,即模仿比特币功能编写的区块链公链demo。 主要应用于密码学、共识算法、点对点网络、区块链防篡改结构等相关知识,并结合各种知识点,编写一个简单完美的可运行公链demo。
话不多说,一起来试试吧!
节目特色
主模块
命令调度模块
程序启动后,控制台捕获用户输入的信息,通过用户的输入解析出命令和命令后面的值。 根据不同的命令对程序进行相关操作。
UTXO交易生成模块
交易转账模块基于UTXO模型,但没有引入比特币脚本,直接将脚本替换为经过数字签名的字节数组。 当用户A向用户B转账时,用户A需要使用私钥对“输入”(包括“输出”的交易哈希、索引等用户A拥有的信息)进行数字签名,生成交易并发送给其他节点。 该节点使用用户 A 的公钥来验证其签名。
由于UTXO的特殊结构比特币如何验证余额,自然避免了重放攻击,也不需要像以太坊账户系统那样添加nonce值。 但是为了避免UTXO的重复计算问题,不支持直到最后一笔转账没有打包进块。 重新转移到同一地址
支持一笔交易多次转账,为了优化转账查询速度,创建了一个UTXO数据表,用于存储所有区块链中未花费的输出。
密码学加解密模块
1.单向哈希函数:sha256 ripemd-160
主要用于将整个区块通过计算转换为定长字符串,方便数据校验
2.编解码算法:base58
由于私钥原始长度过长,不利于记忆,所以使用base58编码对私钥和地址进行可视化编码
3、非对称加密:椭圆曲线算法(crypto/elliptic p256)
从助记词文本中提取7对中文单词作为种子比特币如何验证余额,利用椭圆曲线算法生成公私钥对。 私钥用于对交易数据进行数字签名,公钥用于验证签名以确保发起者的身份。
公钥通过一系列操作生成一个地址,该地址用于查询余额和接收转账Token
地址生成规则如下:
曾经有一个疑问,为比特币生成地址为什么这么麻烦? 既然非对称加密只有公钥,私钥不可逆,那为什么不直接用公钥作为地址,而是将公钥多次哈希得到地址,最近看了一篇文章才明白. 文章提到,量子计算机可以破解椭圆曲线加密,通过公钥可以快速找到私钥信息。 但是量子计算机很难逆向Hash算法(或者破解Hash需要步数的2的80次方),所以你的比特币放在一个未支付的地址(根据UTXO交易模型,输出为公钥Hash而不是公钥,这也解释了为什么UTXO输入存储公钥,输出存储公钥Hash)是相当安全的。 也就是说,已经花费过的地址在量子计算机面前是不安全的,而没有花费过的地址具有很强的量子抗性。
区块生成、验证
基于POW共识算法生成区块,首先根据难度值(可以在配置文件中定义)定义挖矿难度(一串大数),通过调用go自带的随机数包不断改变随机数nonce crypto/rand(之前的版本使用的是自己累加nonce值的方式,但是分叉概率太高),不断对区块本身进行哈希运算,使得最终计算出的区块本身的哈希值小于当前定义的挖矿困难,然后块将产生正确。
出块节点可以获得奖励代币并拥有记账权,并在出块后向全网广播。 其他P2P节点收到区块后,首先验证区块本身的哈希,然后检查区块中的prehash是否与本地pre-block hash一致,最后存储到本地数据库中。
数据持久化模块
持久层在KV数据库blot的基础上封装了一个额外的层,主要接口有put、view、delete。 每次调用接口时,数据库句柄会分别打开和关闭,不会被其他线程占用。 数据库建立了三张表BlockBucket(存放区块的详细信息)、AddrBucket(存放本地钱包数据)、UTXOBucket(存放未消费的UTXO数据)
P2P网络通信模块
使用适合局域网寻址的mdns技术,因为使用的包有windows下找不到网络的bug,所以本程序推荐在linux/mac下运行。
节点启动后,会自动搜索局域网中的其他对等节点,发现后会存入节点池(存储在内存中)。 节点间通信的前12个字节的数据默认为命令,根据不同的命令而定。 本地区块链相关信息反馈
主要工作原理是分发区块并接收交易后进行挖矿:
获取区块流程:
相互比较区块高度
获取丢失的块哈希
通过块哈希接收丢失的整个块
区块验证,存入数据库
挖矿过程:
通过节点向全网节点发送交易数据
节点接收交易,签署并验证交易,并验证余额
验证通过后存入交易池,满足交易池大小后开始挖矿
挖矿成功,区块高度全网广播
发送块到其他节点
其他节点验证区块并将其存储在数据库中
日志输出模块
使用自制的日志包,程序启动后,会在当前目录下默认生成一个log+端口号的日志文件(可在配置文件中设置),程序生成的所有调试信息都会被打印到这个日志文件。 建议开一个实时Listening的窗口,观察节点间的交互和出块的详细步骤
【日志包特点】:
使用的主要工具包
程序运行教程
1.下载后编译
本demo建议在linux/mac下运行,否则会出现助记符乱码,无法点对点网络等问题。
git clone https://github.com/corgi-kx/blockchain_golang.git
go build -mod=vendor -o chain main.go
2.打开多个窗口
为了简化操作,在同一台电脑启动不同的端口来模拟P2P节点(三个窗口启动程序,三个窗口实时查看日志)
在真机上运行时,如果找不到其他节点,可能是防火墙的问题。 请关闭防火墙并重试。
3.修改配置文件
主要修改本地监听ip和本地监听端口。 其他默认就可以了。
不建议降低难度门槛以避免区块分叉。 该演示尚未处理块分叉。
vi config.yaml
blockchain:
#挖矿难度值,越大越难挖
mine_difficulty_value: 24
#挖矿奖励代币数量
token_reward_num: 25
#交易池大小(满足多少条交易才开始进行挖矿)
trade_pool_length: 2
#日志存放路径
log_path: "./"
#中文助记词种子路径
chinese_mnemonic_path: "./chinese_mnemonic_world.txt"
network:
#本地监听IP
listen_host: "192.168.0.164"
#本地监听端口
listen_port: "9000"
#节点组唯一标识名称(如果节点间名称不同会找不到网络)
rendezvous_string: "meetme"
#网络传输流的协议id(如果节点间id不同发送不了数据)
protocol_id: "/chain/1.1.0"
4.启动节点,创建钱包,生成创世块
开始节点 1
./chain
通过命令,生成三个钱包地址
> generateWallet
助记词:["肺段","生地","齿槽","几维","中葡","芒鱼","光华"]
私钥:6HrLjHE4Qm31dZFGjemwNLZM3iqnxoSUqKb5VtEKbWzh
地址:12BwtcVWimms9rrKxxoCev68woGyMYS4sk
> generateWallet
助记词:["扭伤","剪创","肌病","下陷","广发","浊音","斜疝"]
私钥:7yBRSB46q8ZeEiYbwZDSvKzzsh1MYAygeo2i689uEMAf
地址:1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS
> generateWallet
助记词:["心室","缺缸","瓣胃","黑茶","份额","张铜","回游"]
私钥:872CCeLS8bDrC7bdSoFrgUSWm57eqTdypEhKbErYC9xi
地址:1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD
生成创世块(给定第一个地址100Tokens)
> genesis -a 12BwtcVWimms9rrKxxoCev68woGyMYS4sk -v 100
已成生成创世区块
日志1 实时查看日志(可以看到挖矿过程)
tail -f log9000.txt
5.同步块
节点2和节点3依次修改配置文件的端口号为9001和9002,并启动这两个节点同步创世块;
此时,节点 1 的日志检测到网络中存在的其他节点。
节点2和节点3启动后会自动同步创世块
6.执行转账操作
各节点设置挖矿奖励地址(也可以不设置,不设置则节点挖矿后不产生奖励);
节点1设置挖矿奖励地址:
> setRewardAddr -a 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
已设置地址12BwtcVWimms9rrKxxoCev68woGyMYS4sk为挖矿奖励地址!
节点2设置挖矿奖励地址:
> setRewardAddr -a 1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS
已设置地址1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS为挖矿奖励地址!
节点3设置挖矿奖励地址:
> setRewardAddr -a 1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD
已设置地址1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD为挖矿奖励地址!
节点1执行转账操作(创世地址和其他两个地址一样各转10个Token)。
> transfer -from ["12BwtcVWimms9rrKxxoCev68woGyMYS4sk","12BwtcVWimms9rrKxxoCev68woGyMYS4sk"] -to ["1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS","1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD"] -amount [10,10]
已执行转帐命令
7.查询余额
三个节点中,如果区块被节点2挖出,则节点2应获得25个Token的挖矿奖励
此时在任意节点输入getBalance查看余额命令,可以查看三个地址的余额信息
> getBalance -a 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
地址:12BwtcVWimms9rrKxxoCev68woGyMYS4sk的余额为:80
> getBalance -a 1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS
地址:1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS的余额为:35
> getBalance -a 1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD
地址:1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD的余额为:10
8.查看区块详情
任意节点输入printAllBlock命令查看区块信息
Block 1是创世块,只有100个UTXO输出给12BwtcVWimms9rrKxxoCev68woGyMYS4sk
Block 2可见:
在第一笔交易中,地址12BwtcVWimms9rrKxxoCev68woGyMYS4sk首先花费创世块配额为100的UTXO,为自己生成90个UTXO,为地址1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS生成10个UTXO。
第二笔交易地址12BwtcVWimms9rrKxxoCev68woGyMYS4sk使用第一笔交易输出的90个UTXO为自己生成80个UTXO,为地址1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD生成10个UTXO。
第三笔交易是挖矿奖励交易,所以只有输出,没有输入,对地址1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS产生25个UTXO(配置文件中设置的25个奖励金额)
> printAllBlock
========================================================================================================
本块hash 00000008acfb9a8dcf3bb923f4eb6f2ddfc27dcaff861ea6848a9074ca46d85b
------------------------------交易数据------------------------------
本次交易id: 988ecbe7f374855aa94addb873f22960cf43646bdaeb562533f3e683478270db
tx_input:
交易id: bb717bd6717c8cae3829875187b97f256859277ad4a52ac57cdbc132895ca154
索引: 0
签名信息: 8c8b0628ceadebbc9e97b490a40a23494d3f8286f1af045f1e1f18d529c49a90afa194799182c264ee15871b5dd35c773e5dd46427fc8e2c268356ce09f6b60b
公钥: 8e0f1fe7d6177f11027818663048392cee8952cefcf1ceeec8edc84e176f46cedd338575f709b412eeab904d7027056354038f8aef7a1940f45264f7116ba793
地址: 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
tx_output:
金额: 90
公钥Hash: 0d0a1aeb1baf838828a54ac97b09524f0b0c3210
地址: 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
---------------
金额: 10
公钥Hash: 6eb2d1846217aa089dfa26e3147b767e1de0b08d
地址: 1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS
本次交易id: 443b4a4f04204bd8ed2bdfcc096642a27457c27aa47c2ee81486d7440b059521
tx_input:
交易id: 988ecbe7f374855aa94addb873f22960cf43646bdaeb562533f3e683478270db
索引: 0
签名信息: 2a064297227ba07c7ea92eebb1d43f3fe4dfbd6c7e78be8ec2d1d30e20fa51500c8bdb591c11908a877aeef61b4c64f9a851cc44af441cbe6893e1b80e42032c
公钥: 8e0f1fe7d6177f11027818663048392cee8952cefcf1ceeec8edc84e176f46cedd338575f709b412eeab904d7027056354038f8aef7a1940f45264f7116ba793
地址: 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
tx_output:
金额: 80
公钥Hash: 0d0a1aeb1baf838828a54ac97b09524f0b0c3210
地址: 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
---------------
金额: 10
公钥Hash: 8fa79c32a067830be3b16ade637d370e1d1e6e0d
地址: 1E6aRBxfncAsypUnjGxPJYbR4JQ3gZ6hHD
本次交易id: 2420c67272ab7832d6148a36a6b38166862d12e265f184439e6ab2e606b01245
tx_input:
tx_output:
金额: 25
公钥Hash: 6eb2d1846217aa089dfa26e3147b767e1de0b08d
地址: 1B6KYdABXZDwq8xGTbdDknpHBo11CkihxS
--------------------------------------------------------------------
时间戳 2019-11-18 03:23:57 PM
区块高度 2
随机数 2808567053068705071
上一个块hash 0000007d7b7c7b540d9d1b0d1d06b6936e1bc613f6ab7de1ae0275cdaef4e4a4
========================================================================================================
本块hash 0000007d7b7c7b540d9d1b0d1d06b6936e1bc613f6ab7de1ae0275cdaef4e4a4
------------------------------交易数据------------------------------
本次交易id: bb717bd6717c8cae3829875187b97f256859277ad4a52ac57cdbc132895ca154
tx_input:
交易id:
索引: -1
签名信息:
公钥:
地址:
tx_output:
金额: 100
公钥Hash: 0d0a1aeb1baf838828a54ac97b09524f0b0c3210
地址: 12BwtcVWimms9rrKxxoCev68woGyMYS4sk
--------------------------------------------------------------------
时间戳 2019-11-18 10:43:41 AM
区块高度 1
随机数 8604076799988393002
上一个块hash 0000000000000000000000000000000000000000000000000000000000000000
========================================================================================================
九、其他
也可以在节点2和节点3发起转账,但是首先需要通过助记词导入钱包信息,如下:
importMnword -m ["扭伤","剪创","肌病","下陷","广发","浊音","斜疝"]
更多功能请自行发现????,有什么想法欢迎在评论区告诉我们~!
来源地址: