智能合约深度学习

前序

如果想直接入手合约,可以直接跳至合约开发模块哦

在进入智能合约学习环节之前,让我们先了解一下它的“爹”,即区块链

区块链,是一种区中心化,点对点系统的工具,也可以说是一种数据库系统(实际上就是一本记录各种交易的账本)

区别于传统的中心化系统,这个系统由各个区块(前区块的加密哈希,时间戳,交易数据)组成,在这个系统中,由网络中的大多数节点来决定新区块中交易记录的录入以及修改。这就使得其安全性远远超过了传统的系统。假设一个用户想要伪造一份交易,那么从理论来说他需要修改全网每个节点的总账,这个过程需要消耗巨量的算力有这算力谁还来伪造交易啊,每增加一个区块,需要全网51%以上的节点的认可才能够组成区块链

那么我们现在更具体一点,来谈一个家喻户晓的区块链系统———比特币系统

关于比特币系统

竞争记账

即挖矿,在一个区块建立之后,竞争记账的节点需要计算建立以来所有交易的哈希值(SHA256),再将其两两组合,不断重复,最终得到一个SHA256值(也叫默克根),最后需要进行以下计算

SHA256(默克根+前一区的ID+一个随机数)

通常这个值要满足哈希值的前20位为0(达成概率在百万分之一水平),也就是算力比拼

成功者向全网发送通知,若经过检验大家就公认他构造的这个区块并以其作为父区块,进行下一个区块的算力竞争(每10分钟进行一次)

成功者会获得12.5个比特币122w美刀(2024.12.9日汇率)作为奖励,这就是中本聪设计的激励机制img

长链与短链

又是算力竞争……在向全网通知时(假设你的答案正确),可能会有人与你在相同的时间发送了正确的答案,于是会出现两条链,那么就又到了拼算力的时候了,不同的矿工会选择不同的链继续下一轮区块计算,这里就不得不提另一种机制了,即总是选择工作量最大的链,于是哪条链先出现下一个区块,也就意味着会有更多的矿工选择这条链工作,那么另一条短链就会被废止。组装短链的矿工也得不到比特币奖励,结果就是区块链只有唯一一条主线。

比特币的交易

交易包括两个方向,Input以及Output.

两者可以不完全一致,但只能输入略大于输出,那么缺少的这部分去哪里了呢 ,是支付给了矿工哦,每笔交易在发布后可以选择支付交易费用,钱到位交易也会更快被打包。但是不代表不支付或支付很少交易费用不会有人处理你的交易,只是会被推迟,总之,不管是否支付交易费用,矿工都会获得比特币的奖励,你可以将其理解为:即使你不付给服务员小费,但并不影响他获得工资

比特币的交易加密

对于每个用户的钱包,都由三部分组成

16位的地址,公钥,私钥(256位)

假设在A与B交易,A发送给B一条A的私钥加密过的内容,那么若B没有A的公钥,B就无法解密内容

公钥的产生依赖于私钥,而钱包的地址生成依赖于公钥

img

贴一条其他师傅的说明过程。

第一步:生成随机私钥

私钥是一个随机数,随机选取一个32字节的数,这个数的范围大小是介于1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之间的一个数,为了方便后面的计算,我们随机生成一个合法的私钥:

8F72F6B29E6E225A36B68DFE333C7CE5E55D83249D3D2CD6332671FA445C4DD3

第二步:椭圆曲线算公钥

生成了私钥之后,我们使用椭圆曲线加密算法(ECDSA-secp256k1)计算私钥所对应的非压缩公钥,生成的公钥共65字节, 其中一个字节是0x04,其中32个字节是X坐标,另外32个字节是Y坐标:

公钥P.X:
06CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385

公钥P.Y:
FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB

第三步:计算公钥的SHA-256哈希值

将上述公钥地址拼合,得到标准地址:
0406CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB

对齐进行SHA-256哈希计算,得到结果:
2572e5f4a8e77ddf5bb35b9e61c61f66455a4a24bcfd6cb190a8e8ff48fc097d

第四步:计算 RIPEMD-160哈希值

取上一步结果,进行RIPEMD-160计算,得到结果:

0b14f003d63ab31aef5fedde2b504699547dd1f6

第五步:加入地址版本号(比特币主网版本号“0x00”)

取上一步结果,在前面加上16进制的00,即:

000b14f003d63ab31aef5fedde2b504699547dd1f6

第六步:计算 SHA-256 哈希值

取上一步结果,进行SHA-256计算,可得:

ddc2270f93cc84cc6869dd373f3c340bbf5cb9a8f5559297cc9e5d947aab2536

然后,对以上结果再次计算 SHA-256 哈希值,得到:

869ac57b83ccf75ca9da8895823562fffb611e3c297d9c2d4612aeeb32850078

第七步:取上一步结果的前4个字节(8位十六进制)

869ac57b

第八步:把这4个字节加在第五步的结果后面

作为校验位,将这4个字节加载第五步的结果后面,这就是比特币地址的16进制形态了:

869ac57b000b14f003d63ab31aef5fedde2b504699547dd1f6

第九步:用Base58编码变换一下地址

对上一步的结果进行Base58编码,得到:

1QCXRuoxWo5Bya9NxHaVBArBQYhatHJrU7

这就是我们经常看到的传统意义上的比特币钱包地址

智能合约开发

智能合约的开发,主要使用Solidity编译语言以及在线的Remix编译器

数据类型

整数

有符号整数类型包括int8、int16、int32、int64等,而无符号整数类型包括uint8、uint16、uint32、uint64等。这些类型表示不同位数的整数。

相较于C语言,保留了大部分运算,增加了乘方(**)运算以及更改了”<<””>>”的运算规则

x<<y  相当于x*2**y   x>>y相当于x/2**y

逻辑

即bool类型,会在内置函数中大量出现,默认值为false

地址

address来声明,长度为20位,表示以太坊网络上的账户地址

在地址型下有**transfer(转账)balance(账户)**两个变量

通过以下函数来处理地址类型(关于Gas的概念,请见交易处理板块)

<address>.balance(uint 256) ——>返回以wei为单位的该地址的以太币账户(1ETH=10^18wei)
<address>.transfer(uint 256 amount) ——> 给某地址转入指定数量的以太币(每次转账需要2300的Gas费用,且费用固定)

余额不足,Gas不足时会使合约无法执行,回滚已执行的程序并且发送异常信息(交易被终止

<address>.send(uint 256 amount) returns (bool) ——> 给某地址转入指定数量的以太币(每次转账需要2300的Gas费用,且费用固定)在交易成功或失败后会返回对应的bool值

余额不足,Gas不足时会终止程序但不会发送异常消息,会返回False

但使用.send是存在一定风险的,可能会导致转账失败(调用的堆栈>1024KB或发出方的Gas耗尽)的情况下交易的对方仍能收到以太币

<address>.call(...) returns (bool) ——>最常用的调用函数,失败返回false,Gas的费用可自己调整。

发布低级别的调用

call()下有两个控制交易的内置函数

gas()(支付的Gas值)与value()(支付的以太币值),两者同时调用没有先后顺序的要求

例如:address.call.gas(100000).value(1 ether)("register","Myname")
<address>.callcode(...) returns (bool)

发布低级别的调用,没call好用,不久就会被删除了

<address> .delegatecall(...) returns (bool)

发布低级别的代表调用,调用的是储存在另一个库中的库代码(Library code)

?故使用前要确定两个合约的储存设计都要适用于该函数?

[!WARNING]

call() callcode() delegatecall()都是低阶函数,使用时调用的未知合约可能是恶意合约,在调用是可能会被篡权,反过来被调用合约,因此调用函数返回时要注意原合约的参数是否已经被改变

地址常量

字节数组

分为固定长度的字节数组以及可变长度的字节数组

固定长度的数组可以用bytes1~bytes32来说明(bytes1也可以直接记作byte)

可以通过索引访问以及[变量名].length返回字节长度

可变长度的数组:

①bytes(与array性质相同)

②string(可以理解为特殊的数组),不可以调用.length/索引来访问