区块链学习——问题汇总1

2022/1/26 23:07:05

本文主要是介绍区块链学习——问题汇总1,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

区块链学习的一些原理问题

在学习区块链的第一阶段,根据导师提出的一些问题,总结各路大神回答,汇总了以下的结果,仅作个人学习使用!


文章目录

  • 区块链学习的一些原理问题
  • 正文
    • 1、非对称加密算法、哈希算法和数字签名基本原理
      • 1.1 非对称加密
      • 1.2 哈希算法
      • 1.3 数字签名
    • 2、对等网(P2P)基本原理,包括结构化对等网和非结构化对等网,掌握几种常见的组网方法
    • 3、比特币区块链数据结构和快增(挖矿)原理,包括Merkle 树、公钥、私钥、地址生成方法和钱包工作原理
      • 3.1 比特币数据结构
      • 3.2 比特币挖矿原理
      • 3.3 Merkle树
      • 3.4 比特币钱包
    • 4、UTXO、比特币交易验证方法和脚本解锁验证原理
      • 4.1 UTXO
      • 4.2 交易过程
      • 4.3 验证
    • 5、以太坊区块链数据结构和快增原理
      • 5.1 数据结构
      • 5.2 挖矿原理
    • 6、以太坊交易内容、类型和验证机制,以太坊合约和状态数据管理基本原理
      • 6.1 以太坊交易
    • 7、智能合约基本原理
  • 总结


正文

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


1、非对称加密算法、哈希算法和数字签名基本原理

1.1 非对称加密

需要两个密钥:公钥 (publickey) 和私钥 (privatekey)。公钥和私钥是一对,如果用公钥对数据加密,那么只能用对应的私钥解密。如果用私钥对数据加密,只能用对应的公钥进行解密。因为加密和解密用的是不同的密钥,所以称为非对称加密。

主要有RSA算法、DSA算法、ECC算法、DH算法

1.2 哈希算法

一种只能用来加密,不能解密的算法。因为不能解密,所以只能用能通过枚举法来试过正确答案。比特币用的是SHA-256

哈希算法=哈希表+散列函数

散列函数主要有SHA256、SHA512等

1.3 数字签名

把信息用哈希算法算出一个哈希值,用某种非对称算法(比特币是SHA256)对哈希值进行加密。接收方则对哈希值解密,若解出的哈希值和传来哈希值一致,证明信息原文没有被修改过。因为哈希值有个特点,原文有一丁点的改动,哈希值都会有很大的变化。为啥不直接对原文用非对称算法加密和解密,我的想法是原文一般都太长了,直接加密和解密很慢,很影响效率。而且数字签名不需要对内容加密,只是确保没被篡改就行了。

2、对等网(P2P)基本原理,包括结构化对等网和非结构化对等网,掌握几种常见的组网方法

对等网络,即对等计算机网络,是一种在对等者(Peer)之间分配任务和工作负载的分布式应用架构,是对等计算模型在应用层形成的一种组网或网络形式。

集中目录模式

集中目录式的P2P模式也称为结构化的P2P模式。在这种模式中,通过设置一个中心服务器来负责记录和管理所有结点的共享信息资源。每个对等结点通过查询该服务器来了解对等网络中哪一个结点拥有自己所需要的共享信息资源,查找到以后,获取其主机地址,然后进一步向该主机请求自己所需要的信息资源,最后由该主机将其共享信息复制并发送给请求的主机集中目录式P2P网络。 [3]

非集中目录模式

非集中目录的P2P模式也称为纯P2P模式。在非集中式的P2P模式中,对等网络不需要设置一个中心服务器来负责记录和管理所有结点的共享信息资源。任何一个结点要获取某个共享信息资源都是首先询问其相邻结点是否有该资源,如果某个相邻结点没有,则进一步向它的相邻结点询问(询问报文中必须包括初始请求结点的地址),直到具有该信息资源的结点接收到询问请求,那么就由这个结点向最初的请求结点进行肯定应答(同时指明自己的地址)。最后,由初始请求结点向这个结点提出资源请求,这个结点就将其共享信息复制并发送给初始请求结点。

3、比特币区块链数据结构和快增(挖矿)原理,包括Merkle 树、公钥、私钥、地址生成方法和钱包工作原理

3.1 比特币数据结构

一个完整的区块包含以下数据:

(1) 神奇数:神奇数为0xD9B4BEF9,这是一个固定值,作为区块之间的分隔符;

(2) 区块大小:该字段之后的区块的大小,单位为字节;

(3) 区块头:包含版本号、前一个区块的哈希指针、默克尔树根、时间戳、工作量证明的目标特征值、Nonce;

(4) 交易个数:记录了当前区块的交易个数;

(5) 交易记录。

神奇数、区块大小、交易个数的概念都比较好理解,重点聊一聊区块头的各项数据和交易记录的各项数据。

区块头包含以下数据:

(1) 版本号:生成该区块所用的比特币协议版本;

(2) 前一个区块的哈希指针:当前区块通过保存前一个区块的哈希指针指向前一个区块,前一个区块指向更前一个区块,这样便形成了一个链式结构,这也是区块链的由来;

(3) 默克尔树根:在《基于默克尔树的SPV证明》一文中比特猫聊过默克尔树,在此不再赘述,注意的一点是默克尔树的叶子节点和交易记录是一一有序对应的;

(4) 时间戳:比特币的时间戳是Unix时间戳,即从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒;

(5) 工作量证明的目标特征值:由于比特币的挖矿难度是动态调整的,该数据正是用于调整挖矿难度的;

(6) Nonce:运行比特币挖矿程序的矿机不断对区块进行hash运算,如果生成的hash值不是以规定个数的0开头,则增加Nonce值,继续运算hash值。即Nonce是一个挖矿特征数据。

一条完整的交易记录包含以下数据:

(1) 交易生成时间;

(2) 交易的hash指针:指向该交易所花费的比特币所在交易的哈希指针;

(3) 交易记录索引编号:本次交易的索引编号;

(4) 交易输入地址:记录本次交易输出比特币的地址;

(5) 交易输出地址:记录本次交易接收比特币的地址;

(6) 输入地址数量;

(7) 输出地址数量;

(8) 数字签名;

(9) 版本号:生成该交易所用的比特币协议版本;

挖矿:通过穷举随机数来争夺交易记账权,获取记账权的矿工可以得到一定数量的比特币奖励。

3.2 比特币挖矿原理

记账工作

由于记账是有奖励的,每次记账都可以给自己凭空增加一定数量的个比特币(当前是12.5比特币,博文写作时每个比特币是4万人民币以上,大家可以算算多少钱),因此就出现大家争相记账,大家一起记账就会引起问题:出现记账不一致的问题,比特币系统引入工作量证明来解决这个问题,规则如下:

  • 一段时间内(10分钟左右,具体时间会与密码学难题难度相互影响)只有一人可以记账成功
  • 通过解决密码学难题(即工作量证明)竞争获得唯一记账权
  • 其他节点复制记账结果

不过在进行工作量证明之前,记账节点会做进行如下准备工作:

  • 收集广播中还没有被记录账本的原始交易信息
  • 检查每个交易信息中付款地址有没有足够的余额
  • 验证交易是否有正确的签名
  • 把验证通过的交易信息进行打包记录
  • 添加一个奖励交易:给自己的地址增加12.5比特币

如果节点争夺记账权成功的话,就可以得到12.5比特币的奖励。

工作量证明

从区块链记账原理我们了解到,每次记账的时候回把上一个块的Hash值和当前的账页信息一起作为原始信息进行Hash。
如果仅仅是这样,显然每个人都可以很轻松的完成记账。
为了保证10分钟左右只有一个人可以记账,就必须要提高记账的难度,使得Hash的结果必须以若干个0开头。同是为了满足这个条件,在进行Hash时引入一个随机数变量。

3.3 Merkle树

merkle tree就是一个hash二叉树,父节点是两个子节点的double sha256的结果,叶子节点就是交易的content的double sha256结果;

最下面那一层就是交易数据data block,每一个交易都可以计算出一个hash,从而层层向上,得到merkle root。

但是由于blockchain里面都merkle运算要求叶子节点是偶数,所以,当一个区块内包含当交易数量为奇数时,把最后一个交易复制一份,凑成偶数。

最后就是把merkle root保存在区块头中,交易数据被保存在区块体中,其实中间当那些hash并没有被保存,它们只是运算过程数据。

3.4 比特币钱包

生成私钥

生成钱包要从生成私钥开始,钱包地址可以通过私钥运算出来。选择私钥的过程就是在一个限定范围内,随机选择一个数。

那么这个范围是什么呢?答案非常简单,第一,私钥必须是32个字节,也就是说是32乘以8位的二进制数。实际使用中,私钥可以表示为二进制格式、八进制格式、Base64格式、WIF格式或者助记词格式。不管什么样的格式,底层都对应相同的256位二进制数。第二,私钥必须是正数并且小于 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,这是一个非常大的数了,绝大部分的256位二进制数都要比它小。

那么为什么会有上面的限制范围呢?这是因为比特币通过私钥运算公钥的时候会使用一套名为 ECDSA 的签名算法,全称是椭圆曲线数字签名算法。ECDSA 还可以选择不同的曲线,比特币选择的曲线被叫做 secp256k1。签名算法决定了私钥的选择范围。

生成私钥的时候唯一要考虑的就是安全问题。例如,通过 Python 语言 random.getrandbits(256) 就可以生成256位的随机数,就可以当私钥用了,但是这样生成的随机性其实只取决于生成时间,所以如果攻击者能够猜到你生成这个私钥的大致时间就会相对容易的通过暴力搜索的形式获得私钥。而采用 secrets.randbits(256) 就比较安全一些,因为随机性取决于系统上的一些不可复现的行为,即使我把自己的系统给你,你也不可能重新获得我的私钥。实际中,有人会到 https://www.bitaddress.org 上面生成私钥,这里的随机性取决于我们用鼠标在屏幕上随意滑动的轨迹。

总之,私钥只要满足范围,并且保证别人肯定获取不到就可以了。

计算公钥

有了私钥就可以通过 ECDSA 算法来生成比特币公钥了。

首先,我们需要把私钥传入 ECDSA 算法,这样得到的结果是一个64字节的整数,这个数是由长度均为32字节的一个点的 X 值和 Y 值拼接到一起得到的,例如,1e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead14487d7。

接下来,由这个结果获得比特币的完整公钥是非常容易的,只需要在结果的最开头加上 0x04,也就是 041e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead14487d7。

完整公钥看起来很长,所以可以压缩一下。我们知道公钥其实是一个点的 X 值和 Y 值拼接而成的,现在已知这条曲线,那么给定一个 X 值,只可能有正负两个 Y 值处在这条曲线上,所以我们可以从完整公钥里面把 Y 值剔除,只保留 Y 值的正负号。这样,如果以后需要的话,我们就可以很容易的运算出 Y 值来了。具体的做法是这样的,我们从完整公钥之中取出 X 值,如果 Y 值的最后一个字节是偶数,那么在 X 值的开头添加 0x02。如果 Y 值的最后一个字节是奇数,则在 X 值的开头添加 0x03。所以,我们当前情况下得到的压缩公钥就是 031e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7。

这就是计算公钥的过程,主要就是对私钥进行了椭圆曲线运算。以前的钱包软件通常会使用完整公钥,而现在大部分钱包都使用压缩公钥了。

获得地址

比特币的地址是通过公钥进行了一系列的转换而获得的,其中主要的是进行了多重的哈希运算。

第一步,对公钥进行加密。这里的公钥既可以是完整版,也可以是压缩版,我们选择压缩版。有了公钥之后,对公钥进行两次哈希运算,第一次通过 SHA-256 算法得到运算结果后,对结果再进行一次 RIPEMD-160 运算,最终得到的结果就是所谓的加密版的公钥了453233600a96384bb8d73d400984117ac84d7e8b。

第二步,对加密版公钥添加网络标识字节。比特币一共有两个网络:主网和测试网。如果我们需要生成一个主网地址,就要在加密版公钥开头添加 0x00,得到的结果是 00453233600a96384bb8d73d400984117ac84d7e8b。

第三步,添加校验值。校验值是通过对第二步得到的结果运行两次 SHA-256 哈希运算,然后取最终哈希值的前四个字节得到的,表示成十六机制就是 512f43c4。把这个校验值添加到第二步结果的末尾,得到的就是钱包地址了,也就是 00453233600a96384bb8d73d400984117ac84d7e8b512f43c4。有了校验值,钱包软件就很容易帮我们判定地址有没有填错或者损坏了。

但是,很多时候我们看到的钱包地址不是用十六进制表示的,而是用 Base58 格式,所以看起来可能是这个样子 17JsmEygbbEUEpvt4PFtYaTeSqfb9ki1F1。

总结

最后来总结一下,生成钱包的过程主要分了这么几步:第一步,生成一个32字节的私钥。第二步,通过椭圆曲线签名算法由私钥获得公钥。第三步,公钥经过一系列的转换得到钱包地址。注意,转换过程中采用了不可逆的哈希运算,所以从地址是不能够反向运算出公钥的。

4、UTXO、比特币交易验证方法和脚本解锁验证原理

4.1 UTXO

UTXO(Unspent Transaction Output)即为未消费交易输出的意思。在比特币中类似于以太坊中的账户模型。 在比特币中,一笔交易的每一条输入和输出实际上都是UTXO,输入UTXO 就是以前交易剩下的, 更准确的说是以前交易的输出UTXO。这是比较官方的一个说法。

简单来说,我们都知道比特币是虚拟的,本质上就是一串代码。而记录比特币交易的账户模型,就是UTXO。它记录了,包括你账户交易了多少比特币,两者的交易地址,资金来源,数额等等。所以本质上说,确实没有什么比特币,有的只是记录的一个个UTXO。

举个例子,假如我们现在钱包里有100块钱,你要花5块钱,然后找零95块。当你拿出来100块大洋花出去的时候,这100块就已经不能再算作UTXO,只有找零得到的95块,才会算做UTXO。所以,比特币使用前后所链接的公链,记录所有交易记录,当之前的 UTXO 出现在后续交易的输入时,就表示这个 UTXO 已经花费掉了,不再是 UTXO 了。不过整个新的交易,会记录在新的区块上,没有改变历史区块的数据。

另外还要提一下,UTXO与传统的账户系统有什么区别。假如有两个人,一个是小明,一个是小美。小明要给小美转100块钱。那么传统的账户模型是这样的:先判断小明账户里是否有100块的余额,然后在小明的账户里减少100块,在小美账户里增加100块。

但UTXO的机制是这样的:小明的账户里有200块钱,他要想给小美转账,必须将200块钱全部消耗掉。所以他不仅要给小美转100块,还要给自己账户转100块。这样一个好处就是,如果从第一个区块开始逐步计算所有比特币地址中的余额,就可以计算出不同时间的各个比特币账户的余额了。

4.2 交易过程

假如A分两次转给B 2个和3个比特币,此时B表面上就拥有了5个比特币,实质上是有2个UTXO,其中一个有2个比特币,另一个有3个。

B如果需要向C转4个比特币,此时的交易就会有2个输入,就是分别有2个和3个的那两个UTXO,这两个UTXO都是用B的地址锁定的。由于只需要向C转4个比特币,那么还会剩余一个(先不考虑手续费),那这个会存放在哪里呢?是不是某个UTXO里面会留一个?

比特币的设计机制是只要某个UTXO被消耗掉,就会从数据库中永久删除,也就是说B的这两个UTXO都会被彻底删除。这时需要一个找零地址,将剩余的比特币用找零地址对应的公钥哈希生成一个新的UTXO。

具体就是4个比特币用C的公钥哈希锁定生成一个新的UTXO,剩余的比特币用找零地址对应的公钥哈希再生成一个新的UTXO,这个找零地址可以是B现在的地址,也可以是一个新的地址。

4.3 验证

  • 解锁脚本可以验证UTXO是否属于你,解锁脚本包括你的数字签名和你的公钥。上一章讲过用私钥签名,公钥可以验证签名。
  • 比特币的脚本语言是一种基于逆波兰表示法的执行语言。
    • 是一个非常简单的数据结构,有压栈和出栈两种操作,其特点是先进后出,后进先出。
    • 逆波兰表示法,在逆波兰表示法中,所有操作符置于操作数的后面,又被称为后缀表示法(我们传统的运算为中缀表示法,比如(1+2)*3)。逆波兰表示法不需要括号来标识操作符的优先级,只需按照表达式顺序求值即可。

在逆波兰表示法中,(1+2)*3可以写作1 2 + 3 *,先读取1和2两个操作数,然后遇到加号后1、2相加得出3,然后3后面又有一个3,之后遇到乘号,3再乘以3得出9 。

  1. 将解锁脚本和锁定脚本组合在一起,即:*OP_DUP OP_HASH160OP_EQUALVERIFY OP_CHECKSIG*,在这个表达式里,签名、公钥和公钥哈希都是操作数,在验证不同人的UTXO时这3个都是不同的。而OP开头的都是指操作符。
  2. 计算的过程是遇到操作数就压栈,遇到操作符就进行相应的计算。由于数字签名和公钥都是操作数,所以先将它们进行压栈。
  3. 接着遇到OP_DUP,它会将栈顶的公钥复制一份,然后复制的公钥放置栈顶,此时,栈里的数据从下到上以次为:数字签名、公钥、公钥
  4. 然后是OP_HASH160,对栈顶的公钥执行ripemd160(sha256(公钥))运算,其结果其实就是pubKeyHash。此时栈里的数据从下到上以次为:数字签名、公钥、公钥哈希
  5. 接着遇到公钥哈希,并将公钥哈希压栈,此时栈里的数据从下到上以次为:数字签名、公钥、公钥哈希、公钥哈希。然后遇到OP_EQUALVERIFY,此操作符是对比两个数据是否相等,所以先把栈顶的两个数据弹栈,如果相等则继续往下走,弹出来的两个数据也不再压栈。此时栈里的数据从下到上以次为:数字签名、公钥
  6. 最后一个操作符是OP_CHECKSIG,其作用是验证签名是否正确。此时将栈内仅剩的签名和公钥弹栈,上一篇讲过用私钥进行签名,公钥可以验证签名,如果结果是true,则可以证明该UTXO属于该签名和公钥的所有者。
  • **举例:**假如这笔UTXO是你的,那么锁定脚本里面的公钥哈希必然是用你的公钥生成的,解锁脚本里面的数字签名和公钥也是你的,那么在执行OP_HASH160时生成的公钥哈希必然和锁定脚本里的公钥哈希相等,在执行OP_CHECKSIG时,你的公钥也必然能验证你的数字签名。如果这笔UTXO是小明的,那么锁定脚本里面的公钥哈希就是小明的,你的公钥生成的公钥哈希必然与其不同。如果你在解锁脚本里用小明的公玥代替你的公钥,则在执行OP_EQUALVERIFY时是能成功的,但是你是不能拿到小明的数字签名的,所以最后执行OP_CHECKSIG时,小明的公钥必然不能验证你自己的签名,所以最后你是不能花费别人的UTXO的。

5、以太坊区块链数据结构和快增原理

5.1 数据结构

网络结构

  • 在常规的互联网应用比如支付宝、微信中,用户数据和交易数据都存放在应用提供者的中心服务器上,通过IOE、MySQL集群等进行持久化的存储,当普通节点进行交易时,会向中心节点发出请求,中心节点进行各种增删改查的操作后,将结果返给用户节点。

img

  • 在以太坊中并不存在中心服务器,取而代之的是多个通过p2p协议连接起来的平等节点,在众多节点中存储了所有的数据。当用户发起一笔交易,会通过p2p协议将交易广播出去,矿工节点对此进行验证、打包并进一步广播至全网,在区块链内确认后,此操作即认为是不可更改的。
  • 在网络上关于区块链的文章中,都提到了分布式(distributed)和去中心化(decentralization)这两个词,有时候略有区别,有时侯又混用。笔者认为如果要精确区分的话,分布式强调系统的是多个组件通过发送消息协同工作,去中心化强调的是不存在一个中央节点控制整个系统的运行。因此我们认为以太坊兼具去中心化和分布式,或者说在一个分布式平台上运行了一个去中心化的程序。参考

区块链(BlockChain)

  • 在单个节点中,数据是以区块链(BlockChain)的形式来存储的。区块链由一个个串在一起的块(Block)组成。以太坊大概每十几秒会生成一个新块,记录了这个段时间内的各种信息。
  • 以太坊被描述为为一个交易驱动的状态机,它在某个状态下接受一些输入后,会确定的转移到一个新的状态。具体来说,在一个以太坊的状态下,每个账户上有确定的余额和存储信息,当接收到一组交易,被影响账户上的余额和存储信息会发生变动。从第一个创世块开始,不断的收到交易,由此能进入一连串新的状态。

img

  • 按照这个思路,以太坊每隔一段时间把交易数据和验证信息打包在一个块里,依次串接起来,就成为一个链。块越新,块号(BlockNumber,或叫块高度)便越大。

img

  • 每个块的块头(验证信息)里,保存了前一个块的块头哈希值(ParentHash,父块哈希)。这样区块链里的块就彼此联系了起来。假如我们更改了前间某个块的内容,后面块的父块哈希就和它对应不上,这种块就不被大家认可。这就保证了区块链数据的不可篡改性。

块(Block)

每个块包含块头和交易,其中块头的结构如下图所示。

img

几个关键字段的含义如下:

  1. ParentHash:父块的哈希值
  2. Number:块编号
  3. Timestamp:块产生的时间戳
  4. GasUsed:交易消耗的Gas
  5. GasLimit:Gas限制
  6. Difficulty:POW的难度值
  7. Beneficiary:块打包手续费的受益人,也称矿工
  8. Nonce:一个随机数,使得块头哈希满足POW需求
  • 账户发起交易需要花费一些gas,作为手续费归矿工所占有。在POW模式下,矿工在打包块的时候,需要不停的调整Nonce,使得整个块头的哈希值满足一定的条件(比如头几位都是0)
  1. StateRoot:状态树的根哈希值
  2. TransactionsRoot:交易树的根哈希值
  3. ReceiptsRoot:收据树的根哈希值
  • 每个矿工在把交易打包成块的时候,会组织三颗树:

    • 交易树,树叶里是交易
    • 收据树,树叶里是交易生成的收据
    • 状态树,树叶里是交易影响到的账户状态
    • 三棵树求取根哈希,可以得到 区块头中的StateRoot,TransactionsRoot,ReceiptsRoot三个字段。这样就建立了交易和区块头字段的映射。当其他用户收到块,根据块里的交易可以计算出收据和状态,计算三个根哈希后和区块头的三个字段进行验证,判断这是否为合法的块。

img

其中交易树和收据树是Merkle树,如上图所示。状态树是Merkle Patricia Tree,更详细的介绍可以参照这里

状态(State)

在上文中我们提到,以太坊是基于状态的。多个账户的状态共同组成了以太坊的全局状态。账户分为两种:

  1. 外部账户(Externally owned account),被私钥控制且没有任何代码与之关联。一个外部账户可以创建交易,来发送消息给另一个外部账户或合约账户,以此来触发转账交易和智能合约的调用、创建
  2. 合约账户(Contract account),被它们的合约代码控制且有代码与之关联。合约账户不可以自己发起一个交易,只能被外部账户调用。

img

每个账户包含了以下的字段:

  1. Balance:该账户的余额
  2. Nonce:该账户为外部账户时候,表示该账户创建的交易序号,每做一次交易都会加1。该账户为合约账户时候,表示该账户创建的合约序号,每创建一次会加1。
  3. CodeHash:该账户为合约账户时候,表示合约的哈希值,否则为空字符串的哈希
  4. StorageRoot:该账户的存储内容组成Merkle树后求得的根哈希值

img

多个块的MPT树共享了账户状态,子块状态树和父块状态树的差别在于它指向了在子区块中被改变了的账户。这样节省了总的存储空间,方便了块的回滚操作。

img

5.2 挖矿原理

以太坊,和所有区块链技术一样,使用激励驱动的安全模式。任何在网络上宣称自己是矿工的节点都可以尝试创建和验证区块。世界各地的很多矿工都在同一时间创建和验证区块。每个矿工在提交一个区块到区块链上的时候都会提供一个数学机制的“证明”。这个证明就像一个保证:如果这个证明存在,那么这个区块一定是有效的。

为了让一个区块添加到主链上,一个矿工必须要比其他矿工更快的提供出这个“证明”。通过矿工提供的一个数学机制的“证明”来证实每个区块的过程称之为工作量证明(proof of work)。证实了一个新区块的矿工都会被奖励一定价值的奖赏。奖赏是什么?以太坊使用一种内在数字代币—以太币(Ether)作为奖赏。每次矿工证明了一个新区块,那么就会产生新的以太币并被奖励给矿工。

以太坊的矿工收入主要也包含区块奖励与交易费两部分,但与比特币相比有几处不同:

以太坊的基础区块奖励没有比特币的定期减半计划。在初始阶段,以太坊的基础区块奖励是 5 ETH。在 2017 年名为拜占庭的硬分叉中,649 号提案被激活,基础区块奖励调整为 3 ETH。随后,1234 号提案将基础奖励进一步降低至 2 ETH。

为了给智能合约消耗的计算资源定价,用户在以太坊中发起交易时,不直接指定交易费,而是指定一个交易费单价,被称为燃料价格(gas price)。交易实际执行时按照计算量的多寡消耗燃料,燃料用量乘以燃料价格就是以太坊最终向每笔交易收取的交易费。

以太坊出块速度较快,所以会出现更多分叉。为了给矿工提供更好的挖矿体验,以太坊引入了“叔块”的概念。每个区块除了选择自己的父亲区块,还可以选择最多两个“叔块”,每选择一个叔块可额外获得基础区块奖励 1/32 的奖励。而被主链区块选中的叔块,其中的交易不会被执行(不为系统共享吞吐量),但挖到该块的矿工也可以获得一定的奖励,具体数值是:

img

6、以太坊交易内容、类型和验证机制,以太坊合约和状态数据管理基本原理

6.1 以太坊交易

https://www.jianshu.com/p/0e2f53acb7c7

以太坊的交易主要是指一条外部账户把经过签名的数据包发送给区块链上另一账户,这个数据包包含发送者的签名、接收者的地址以及发送者转移给接收者的以太币数量等内容。以太坊上的每一笔交易都需要支付一定的费用,用于支付交易执行所需要的计算开销。计算开销的费用并不是以太币直接计算的,而是引入Gas作为执行开销的基本单位,通过Gas Price与以太币进行换算。

一般一条交易可能包括下面的内容,

from:交易发送者的地址;to:交易接收者的地址;value:发送者要转移给接收者的以太币数量

data:数据字段,如果存在,则是表明该交易是一个创建或则调用智能合约交易

Gas Limit:表示这个交易允许消耗的最大Gas数量

GasPrice:表示发送者愿意支付给矿工的Gas价格

nonce:用来区别同一用户发出的不同交易的标记

hash:由以上信息生成的散列值(哈希值),作为交易的ID

r、s、v:交易签名的三个部分,由发送者的私钥对交易hash进行签名生成。

按照场景,交易可以分为三种类型

1)转账交易。转账是最简单的一种交易,从一个账户向另一账户发送以太币。

web3.eth.sendTransaction({undefined

from:

to:

value:

})

2)创建智能合约的交易。

web3.eth.sendTransaction({undefined

from:

value:

})

创建合约是指将合约部署在区块链上,这也是通过发送交易来实现的。在创建合约的交易中,“to”字段是一个空字符串,在“data”字段中指定初始化合约的二进制代码,之后合约被调用是,该代码的执行结果将作为合约代码。

3)执行智能合约的交易。

web3.eth.sendTransaction({undefined

from:

to:

value:

})

该交易是为了执行已经部署在区块链上的智能合约,在该交易中,from是合约地址,to是要调用智能合约的地址。
交易过程

在以太坊中,交易的处理是一个过程,从账户发起交易请求开始,到包含该交易的区块被共识节点同步为止(一般来说,出于安全性考虑,会等到该区块后面再“挖”出一些块,这笔交易才算确定),满足这一个过程才算完成一笔交易。

1、一笔普通的转账或合约调用的交易过程

1)发送交易请求。发送者(用户A)按照格式要求在以太坊网络中发起一个交易请求,该请求被传向用户A的对等节点,如图2所示。

img

2)交易请求验证和广播。网络上的节点(用户B)同步到此交易,检查交易是否有效、格式是否正确。如果符合要求,计算可能的最大交易费用,确定发送方的地址,并在本地的区块链上减去相应的费用,如果账户余额不足,则返回错误,这条交易废弃。对符合要求的交易请求,用户B将其放在交易存储池中,并且转发给其他节点。其他收到交易请求的节点重复用户B的处理过程。如图3所示。

img

3)记账节点打包交易和执行合约。对于转账交易,获得记账权的节点将该交易和其他交易一起打包到区块中;对于合约交易,矿工将该交易和其他交易一起打包到区块中,并在本地的EVM上运行被调用的合约代码,直到代码运行结束或Gas用完。如果代码并未结束而Gas已经用完,那么代码运行而改变的状态回滚到代码运行之前,但是已经支付的交易费用不可收回,交易费用有获得记账权的矿工获得。如果代码运行结束Gas还有剩余,那么矿工也只会获得消耗Gas x GasPrice作为手续费,不会收取剩余Gas对应的手续费。如图4所示。

img

4)区块广播。用户B把包含用户A的交易请求的区块发送至对等节点,并在全网传播。如图5所示。

5)区块验证同步。其他节点收到该区块后,验证区块,如果区块通过验证,节点将内存池中原来用户A的交易请求删除,同时同步该区块,将其添加到本地的区块链中。对于区块中的执行智能合约的交易,其他节点会在本地的EVM上运行该智能合约,并互相验证运行的结果。如图6所示。

img

通过上面五个步骤,整个交易的过程已经结束。但是一般来说,当包含交易的区块链被同步到区块链后,出于安全性的需求,还需要再挖掘一些块,这笔交易才能算是真正地被确认。

2、一个创建智能合约的交易过程

注:有些步骤和普通转账的一样,交易的图就不画了

1)发送创建智能合约请求。发送者(用户A)按照一定的格式要求,在以太坊中发起一个创建智能合约的交易请求,如图7所示

img

2)交易请求验证和广播。网络上的节点(用户B)同步到此交易,检查交易是否有效、格式是否正确。如果符合要求,计算可能的最大交易费用,确定发送方的地址,并在本地的区块链上减去相应的费用,如果账户余额不足,则返回错位,这条交易废弃。对符合要求的交易请求,用户B将其放在交易存储池中,并且转发给其他节点。其他收到交易请求的节点重复用户B的处理过程。

3)打包,创建合约账户,部署合约。获得记账权的节点将该交易和其他交易一起打包到区块中,获得记账权的节点会根据其提供的交易费用和合约代码,创建合约账户,并在账户空间中部署合约。智能合约账户的地址是由发送者的地址(address)和交易随机数(nonce)作为输入,通过加密算法生成的、交易确认后智能合约的地址返回给发送者。如图8所示。

img

4)区块广播。用户B把包含用户A的交易请求的区块发送至对等节点,并在全网传播

5)验证区块,并部署智能合约到本地。共识节点接收到该区块,验证区块,如果区块通过验证,节点从内存池将原来用户A创建智能合约的交易请求删除掉,同步区块链,并将智能合约部署在各自的本地区块链中。如图9所示。

img

经过上面的五步,创建智能合约的交易完成。但是一般来说,当包含交易的区块链被同步到区块链后,出于安全性的需求,还需要再挖掘一些块,这笔交易才能算是真正地被确认。

7、智能合约基本原理

智能合约的本质

智能保证执行安全,并减少交易成本。智能合约允许在没有第三方的情况下进行可信交易,且交易可追踪、不可逆转。智能合约是以信息化方式传播、验证或执行合同的计算机协议。智能合约程序不是单纯自动执行的程序。它本身就是系统的有效参与者。它是运行在可复制、共享的账本上的计算机程序,可以处理信息,接收、储存和发送价值。

智能合约漏洞

去中心化执行的智能合约由于代码开源,会导致安全漏洞更容易被利用却可能无法迅速修复。2016年6月The DAO的智能合约漏洞造成损失5000万美元的损失,开发者未能就漏洞及时做出回应。最终通过回滚数据块、以太坊硬分叉挽回损失,却严重损害区块链的去中心化属性。

以太坊智能合约中的问题包括合约编程Solidity、编译器错误、以太坊虚拟机错误、对区块链网络的攻击、程序错误的不变性以及其他尚无文档记录的攻击。

智能合约的用途

区块链技术的去中心化账本功能可以被用来创建、确认、转移各种不同类型的资产及合约。几乎所有类型的金融交易都可以被改造成在区块链上使用,包括股票、私募股权、众筹、债券和其他类型的金融衍生品如期货、期权等。

智能合约工作原理

用户承诺双方的权利和义务编写为电子化的机器语言,参与者分别用各自的私钥签名。签名后的智能合约传入区块链网络中。合约通过P2P的方式在区块链全网中扩散,验证节点会将收到的合约先保存到内存中,等待触发对该份合约的共识和处理。共识时间到了,验证节点会把最近一段时间内保存的所有合约打包成一个合约集合,并算出这个合约集合的哈希值,组装成区块结构,扩散到全网;其他验证节点收到后,与自己保存的合约集合对比教验,同时发送一份自己认可的合约集合给其他验证节点;通过多轮的发送和比较,所有验证节点最终在规定的时间内对最新的合约集合达成一致。

每个区块包含以下信息:当前区块的Hash值、前一区块的Hash值、达成共识时的时间戳、以及其他描述信息;已经达成共识的合约集。

智能合约执行过程

智能合约定期检查自动机状态,逐条遍历每个合约内包含的状态机、事务以及触发条件;将条件满足的事务推送到待验证的队列中,进行签名验证,确保事务的有效性,等待多数验证节点达成共识,成功执行并通知用户;未满足触发条件的事务将继续存放在区块链上。

事务执行成功后,智能合约自带的状态机会判断所属合约的状态,当合约包括的所有事务都顺序执行完后,状态机会将合约的状态标记为完成,并从最新的区块中移除该合约;反之将标记为进行中,继续保存在最新的区块中等待下一轮处理,直到处理完毕。

总结

第一部分的问题就是讲比特币、以太坊的基本原理,第二部分将开始讲区块链设计的理念。



这篇关于区块链学习——问题汇总1的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程