一分钟理解:比特币第一次严重漏洞,生产1844亿枚比特币!是如何发生的

1、事件

2010年8月15日(也就是比特币诞生的第二年,创世区块于2009年1月3日诞生),有人发现,在比特币区块链的第74638块上,一笔让人惊愕的交易。

这笔交易出现了184 467 440 737.09551616个比特币,其中有922亿个比特币被发送到两个地址,交易如下:

图片

比特币总量是2100万——《比特币知识(3)——比特币上限为什么是2100万》,为什么这两笔交易,会大于总比特币总量?

这恐怕是比特币史上最严重一次漏洞事件了,如果不及时修复这个问题,比特币系统或许直接被毁掉。

2、溢出原理

这个问题是怎么发生的?原理其实也简单:大数溢出引起,算是编码不严谨引起的了。

在小时候,我们学数数时候,用的方法——掰手指。

图片

从1数到10,十个手指最多可以表示到10(不考虑用脚或者半截手指情况),如果数到11,10个手指不够用,手指表示就回到1了,这算是最原始的一个大数溢出的认识吧。

计算机对数的表示也是类似,也有最大限度。

为了方便表达,我们用Go语言的uint8做例子,一个uint8 表示,uint8一个字节空间,表达的范围是:bin(00000000) 到bin(11111111),也就是0-255,如果再大,就会发生溢出,高位被抛弃掉,又会变成0开始了。

图片

代码演示:

图片

理解了这个,比特币的漏洞的理解就方便了。

3、故事例比

用个简朴的例子,父亲去给两个孩子交学费:父亲把钱递给学校财务,搞定,回家睡觉。

嗯~貌似还漏了些什么,得看看两个孩子学费一共要多少,自己带的钱够不够,如果够,就缴费;如果不够还能啥,筹钱去啊!

父亲这次兜里带着10块钱去给两个孩子缴129块钱的学费。

还是用Go的uint8,封装一个函数做演示,:

import (    "fmt")
func submit(account, cost1, cost2 uint8) (bool, uint8) {    var total = cost1 + cost2    if total <= account {        fmt.Printf("账户金额:%d, 待缴金额:(%d+%d=)%d\n", account, cost1, cost2, total)        return true, account - total    }
    return false, account}
func main() {    account := uint8(10)    cost1 := uint8(129)    cost2 := uint8(129)
    success, account := submit(account, cost1, cost2)    if success {        fmt.Println("缴费成功,余额:", account)    } else {        fmt.Println("金额不够,凑钱去!")    }}

代码看着没有问题,如果预期正常,应该输出:金额不够,凑钱去!

但实际上却缴费成功了。

图片

(对了,哪的学校兜里10块钱就敢去交学费了?告诉我,我也去霸个学位)

学费为129+129=258(也就是256+2),在一个字节的 uint8存储,就发生了溢出。

图片

回到比特币的那个漏洞,就是和“父亲交学费”的逻辑一样,发生错误的原因:当时的比特币系统仅检测转出的总额是否小于未花费输出,而没有检测每笔转出是否小于未花费输出,以及也没有考虑总额是否有溢出的情况。

当时转出两个922亿个比特币的账户,仅有0.5btc,为什么会转账成功?

因为两个转出额之和发生了溢出(和uint8溢出原理一样,不同是其他的小数类型的溢出):

打包区块奖励= 输入金额 - 总输出金额= 0.50btc - (92233720368.54275808 + 92233720368.54275808))= 0.50 btc- (-0.010btc))= 0.51btc

这个打包奖励被矿机收囊,更大的影响是无中生有的发行了1844亿个比特币。

4、问题修复

在漏洞被披露后的三小时内,中本聪及其他比特币开发者发布了0.3.1版本的修复程序,此更新引入了逻辑,拒绝具有溢出输出值的交易。

在第74691区块时候,带补丁版本的块链终于追赶上出现漏洞的块链,也就是大约20多小时后,比特币以硬分叉情况有惊无险地解决了这次最为重大的危机事件。

对于大数溢出逻辑代码如何修复,就不用讲述了,应该会coding 的伙伴都懂,可能实际编码中不太严谨而已。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/652557.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# WinForm —— 08 Form初始化、布局、注册事件

Form 初始化 Form初始化的时候会调用 Designer.cs 里的 InitializeComponent(); 函数&#xff0c;在InitializeComponent(); 函数里面有Load Form语句时会调用 FrmLogin_Load()函数 Form布局 两种方式&#xff1a; 拖控件到窗体&#xff0c;设置属性在Load事件中写代码添加…

算法 || 二分查找

目录 二分查找 在排序数组中查找元素的第一个和最后一个位置 搜索插入位置 一个数组经过划分后具有二段性的都可以用二分查找 二分查找 704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; ​ 暴力解法&#xff1a;直接遍历数组&#xff0c;找到 target 便返回下标&am…

基于微信小程序云开发实现考研题库小程序V2.0

不久之前&#xff0c;基于云开发的微信答题小程序搭建题库小程序V1.0&#xff0c;软件架构是微信原生小程序云开发。现在来回顾一下&#xff0c;已经实现的功能。 一、V1.0项目预览 1、页面结构 首页 答题页 结果页 我的页 排行榜页 答题历史页 登录页 使用指引页 2…

LeetCode57. 插入区间

LeetCode57.插入区间 题目思路: 代码 /* 前置知识&#xff1a; vector<vector<int>> a,b; 二维vector数组是可以将二维中的一维vector数组给push_back的&#xff0c; 不是只有单个元素才可以&#xff0c;整个一维的vector数组也可以 b[0] {1,2,3},b[1] {4,5,6}…

如何消除浏览器SmartScreen对网站“不安全”提示?

面对互联网时代用户对网站安全性和可信度的严苛要求&#xff0c;网站运营者时常遭遇Microsoft Defender SmartScreen&#xff08;SmartScreen&#xff09;提示网站不安全的困扰。本文将剖析SmartScreen判定网站不安全的原因&#xff0c;并为运营者提供应对策略&#xff0c;以恢…

element 分页切换时:current-page无效 页数不会跟着一起切换

问题回溯&#xff1a;使用el-pagination组件 选择切换当前分页 页数为2 问题结果&#xff1a;el-pagination组件 当前页切换失败 一直都是 1&#xff0c;接口传参分页数据是2&#xff0c;打印当前分页也是2 解决方案1&#xff1a;使用 current-page参数 .sync 修饰符 解决方案2…

DM8达梦数据库模式下,备份库中具体某一张表SQL操作

1、进行达梦数据库的安装路径&#xff0c;我的默认安装路径为 /home/dmdba/dmdbms/bin 2、执行表备份的命令dexp ./dexp MO_FORM_V5/"MO_FORM_V5"192.168.179.11:5236 DIRECTORY/opt/dm_back/ FILEsystem.dmp TABLES"MO_FORM_V5.FORM_WARN_RULE" LOGs…

【问题实操】银河高级服务器操作系统实例分享,配置hugepages启动异常

1.问题现象 某运营商国产服务器操作系统项目&#xff0c;部署Kylin-Server-0524-aarch64服务器系统&#xff0c;内核从4.19.90-24.4升级到4.19.90-25.14。在grub中配置huagepages大页内存后&#xff0c;系统在内核启动阶段黑屏&#xff0c;只显示一个光标。grub配置如下图&…

商店数据(八)

目录 57.后台权限表 58.推荐记录表 ​59.系统上传资源表 ​60.角色表 ​61.订单结算表 62.店铺表 63.店铺认证表 64.店铺申请&#xff08;移动端&#xff09;表 57.后台权限表 CREATE TABLE wat_privilgeid (privilegeod int(11) NOT NULL AUTO_INCREMENT COMMENT 自增…

C#命名空间常用函数

在C#中&#xff0c;不同命名空间下有各种常用函数&#xff0c;下面列举一些常见的函数及其对应的命名空间&#xff1a; System命名空间&#xff1a; Console.WriteLine()&#xff1a;用于向控制台输出信息。Convert.ToInt32()&#xff1a;用于将其他数据类型转换为整数类型。 S…

数据结构--栈与队列【您的关注是我创作的动力!】

文章目录 栈什么是栈&#xff1f;栈的具体实现 队列什么是队列&#xff1f;队列的实现 栈 什么是栈&#xff1f; 栈也是顺序表的一种&#xff0c;栈的逻辑实现是先进后出&#xff08;后进先出&#xff09;就跟子弹夹一样。 具体逻辑就是它只允许在固定的一端进行数据的插入与…

小程序使用阿里巴巴矢量图标库

一、登录官网 www.iconfont.cn 二、在搜索框中搜索想要的图标&#xff0c;将鼠标移动到图标上会看到三个标记 可以使用下载&#xff0c;直接使用&#xff1a; 可以使用css文件使用&#xff1a; 首先点击购物车样式的选项&#xff0c;而后点击下图位置&#xff1a; 点击自己创…