基于golang编写的区块链公链demo


源码地址:https://github.com/corgi-kx/blockchain_golang.git


    本程序是模仿比特币的功能所编写的区块链公链demo,主要应用到了密码学,共识算法,对等网络,区块链防篡改结构等相关知识,并把各个知识点结合到一起,编写成了简单完善的可运行公链demo
程序特点:
  • 基于工作量证明共识算法,数据以区块链的结构进行存储
  • 去中心化,运用P2P技术各个节点之间相对独立
  • 主动寻找网络中的对等节点,自动连接并存入本地节点池
  • 节点退出时会向全网广播,其余节点动态更新当前可连接节点池
  • 挖矿成功节点获得记账权,并向全网广播同步最新区块,其余节点验证通过后存入本地区块链中
  • 交易转帐使用UTXO交易模型,支持一次交易存在多笔转账
  • 支持中文助记词导入,由助记词生成公私钥密钥对(使用的椭圆曲线算法)
  • 交易转账使用私钥进行数字签名,公钥验证,并因为UTXO的结构避免了签名的重复使用问题
  • 为未花费UTXO单独建立数据表,优化转账交易速度
  • 使用默克尔树生成交易的根hash(当前demo并没有区分区块头与区块体,仅仅是想使用此数据结构练练手)
  • 持久化区块链与公私钥信息,存入节点本地数据库中(每个节点拥有自己的独立数据库)
  • 自定义挖矿难度值、旷工挖矿奖励值
  • 自定义交易池大小,满足指定笔数的交易后才会开始挖矿

主要模块:
  • 命令调度模块
  • UTXO交易生成模块
  • 密码学加解密模块
  • 区块生成、验证模块
  • 数据持久化模块
  • P2P网络通讯模块
  • 日志输出模块

命令调度模块

    启动程序后,控制台捕捉用户输入信息,通过对用户的输入解析出命令以及跟随在命令后的值。根据不同命令对程序进行相关操作

UTXO交易生成模块

    交易转账模块基于UTXO模型,但并没有引入比特币脚本,脚本处直接使用数字签名的字节数组进行替代。当用户A转账给用户B时,需要用户A使用私钥对"输入" (包含了用户A所拥有的"输出"交易hash、索引等信息)进行数字签名,生成交易后发送给其他节点,其他节点则使用用户A的公钥对其进行签名验证。
    由于UTXO的特殊结构,天然的避免了重放攻击,并不需要像以太坊账户系统一样添加nonce值,但是为了避免UTXO的重复计算问题,在上一笔转账未打包进区块之前暂不支持同一地址的再次转账
    支持一笔交易多笔转账,并为了优化转账查询速度创建了UTXO数据表专门用于存储所有区块链中未花费的输出
    想要了解更多关于UTXO相关,建议参考这篇文章

密码学加解密模块
  1. 单向散列函数:sha256 ripemd-160
    主要用于将整体区块通过计算转换为固定长度的字符串,方便进行数据校验
  2. 编解码算法:base58
    由于私钥原始长度过长不利于记忆,使用base58编码对私钥、地址进行可视化编码
  3. 非对称加密:椭圆曲线算法(crypto/elliptic p256)
    通过助记词文本提取7对中文词语作为种子,通过使用椭圆曲线算法生成公私钥密钥对,私钥用于对交易数据进行数字签名,公钥对签名进行验证来确保发起人身份。
    公钥通过一系列运算生成地址,地址用于查询余额,以及接收转账Token

   地址生成规则如下:

  • 通过椭圆曲线算法生成公钥
  • 对公钥进行sha256散列和ripemd160散列,获得publickeyHash
  • 在publickeyHash前面加上version(版本)字节数组获得versionPublickeyHash
  • 对versionPublickeyHash进行两次sha256散列并取前4位字节,获得tailfHash
  • 将tailfHash拼接到versionPublickeyHash后面,获得公钥的最终Hash即finalHash
  • 最后将finalHash进行Base58编码得到比特币地址

曾经有个疑问,为何比特币生成地址要这么麻烦,既然非对称加密只拥有公钥是无法倒推出私钥的,为何不直接使用公钥当地址,而是对公钥进行hash多次来取得地址,直到最近看了篇文章才明白,该文章提到量子计算机是可以破解椭圆曲线加密的,其可以通过公钥快速寻找到私钥信息。但是量子计算机很难逆转Hash算法(或者说需要2的80次方个步骤来破解Hash),所以你的比特币放在一个未支付过的地址中(根据UTXO交易模型,输出存的是公钥Hash而不是公钥,这同样解释了为何UTXO输入存的是公钥而输出存的是公钥Hash)是相当安全的。也就是说已有花费的地址在面对量子计算机面前是不安全的,没有花费的地址有较强的抗量子性。

区块生成、验证

    基于POW共识算法生成区块,首先根据难度值(可在配置文件里定义)来定义挖矿难度(一串大数),通过调用go自身的随机数包crypto/rand来不断的变换随机数nonce(上个版本用的nonce值自身累加的方法,但是分叉的概率太大),不断哈希区块自身来使最终计算出来的区块自身hash值小于当前定义的挖矿难度则获得出块权利。
    出块节点可获得奖励代币并拥有记账权,出块后像全网进行广播。其余P2P节点收到区块后首先对区块自身hash进行验证,其次检验区块里的prehash与本地的前区块hash是否一致,最后存入本地数据库中。

数据持久化模块

    持久化层基于KV型数据库blot多封装了一层,主要接口为put、view、delete。每次调用接口会单独打开、关闭数据库的句柄,所以不会出现被其他线程占用的情况。数据库分别建立了三个表 BlockBucket(用于存放区块的详细信息)、AddrBucke

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值