以太坊开发需知(转)

相比起传统应用而言,以太坊开发引入了新的基础设施,由此必不可少的带来了部署和运维的复杂度,比如作为系统设计者,我们需要做出选择:以太坊开发请咨询郑州国金科技孙经理185-9586-0096

自建节点,还是信任第三方节点?
公有链、联盟链、私有链?
由于加入了新的设计单元:智能合约,我们将面对

设计的复杂度
合约的升级问题:因为智能合约一旦发布就无法更改,万一需要更新合约错误或规则,怎么办?
合约的组织问题。
与一般代码不同,合约的好坏直接与金钱挂钩
不安全的合约会造成客户的金钱损失,立竿见影。
合约的每一步都需要消耗gas,不讲究的合约会造成执行成本高居不下。
并且,以太坊本身的限制同样也会影响到整个应用系统的设计和选型:

交易确认需要时间:20笔/秒
交易易受外界影响
交易费的高低
流行应用会造成网络拥堵,从影响交易的确认
相比起传统CS编程,与以太坊进行交互要复杂得多:

需要有钱包账户
发出去的交易需要签名
由于整个过程是异步为主,因此交易需要验证
对于区块链本身的定位,同样也会影响设计:

仅仅用作数据共享和防篡改的基础设施?
围绕区块链打造价值网络?
Token设计模式
Token引入对于业务本身带来的影响
这一点尤其差异巨大,不单单像传统开发那样仅仅只需要了解用户的业务就可以开足马力前进。Token设计本身需要一定的经济常识,虽说这部分可以由专业背景的人来设计,但对于开发者和架构师而言,不了解必要的基础知识肯定会对开发的顺利进行有阻碍。

以太坊Dapp的典型技术架构

Serverless风格

图片.png
这种架构非常明了,客户端直接与部署在以太坊节点上的智能合约打交道就好了。它的优点和缺点都很明显:

优点
轻量级
运维简单
彻底的去中心化
缺点:
胖客户端:交互 + 业务逻辑
智能合约难以承载复杂业务逻辑
典型场景:投票、博彩、小游戏等
CS + 区块链

图片.png
这种架构相当于传统CS(注:这里的传统相对于区块链应用而言,因此像桌面客户端 + 服务器、Web系统、前后端、移动互联网应用等都属于本文中所说的传统应用。)融入了区块链,客户端和服务器都和区块链直接交互。

为什么客户端也需要跟区块链直接交互?原因很简单:区块链应用的账户信息(尤其是私钥)一般都由用户自己保管,不会放在服务器上。服务器上只会存放系统自己的账户信息。

这种系统的优缺点如下:

优点
传统应用和区块链融合
适用复杂业务逻辑,服务器完全可以包含复杂业务逻辑,合约只承载与价值流转相关的商业规则。
缺点
重量级
运维负担重
部分中心化,话说回来,在我看来,中心化算不上太坏,因为中心化本身代表了专业化。
典型场景:具有复杂业务逻辑的应用系统,如物品溯源、信用质押、供应链金融等等。
Server + 区块链

图片.png
这种架构相当于上面的一种变体:客户端委托服务器完成与区块链相关的交互,甚至于客户端完全都不知道区块链的存在。为何不推荐采用这种架构呢?原因很明显:它要求客户端绝对信任服务器。

这种架构的优缺点如下:

优点
对客户端屏蔽了区块链的复杂度
缺点
私钥中心化管理
典型场景:客户端绝对信任服务器
最后,说说关于密钥的存放:

若合约部署于第三方节点,如Infura,毫无疑问只能是自己管理。
假如是自建节点,那么你有两种选择
方式1:托管
方式2:自管
同时出于保障资金安全的角度:

控制托管账户的可用资金,每当可用资金用完,从自管账户中转入
对于自管账户,最好也分散风险,建立多个自管账户,将资金分散其中,避免被一锅端。
以太坊应用的开发流程

以太坊应用的开发流程如下图,相比起传统开发流程没有本质的区别,只是测试过程相对繁琐:先本地环境测试,再上测试网试运行,最后部署于主网。只是由于合约的更新麻烦,因此建议尽量提前多做一些测试,将问题提前消灭掉。

图片.png
以太坊开发注意事项

谈完差异,看过架构和展示了开发流程之后,接下来就进入正题,说说本文的重点:以太坊开发的那些坑。

智能合约

智能合约开发的常用工具:

Solidity + Truffle + VS Code
常用类库:
Token和ICO相关:OpenZepplin和TokenMarketNet/ICO
可升级合约:ZOS
关于合约的执行成本,我之前写过一篇文章有详细介绍,这里就不再赘述,请参见原文,避免不必要的金钱损失。

关于合约的安全,我在这篇文章中略有提及。但远远不够,这段时间以来,我也翻阅了相关资料,整理如下:

Overflow & Underflow,使用OpenZeppelin的SafeMath lib
可见性和delegatecall说明如下,相关推荐:优先external, 并留意避免在delegatecall中包含恶意代码
public,无限制
external,仅外部调用
private,仅本合约内
internal,类似protect
delegatecall,类似js中的apply,被调用代码和调用合约处于一个上下文
可重入性(DAO攻击),利用CDI模式
检查 -> 更改合约状态 -> 支付
优先使用pull模式,而非push/send模式
withdraw 优于 send/transfer
避免使用随机数、now和block.blockhash作为合约逻辑
分布式网络的时钟问题
注意短地址攻击,检查message.data的合法性
地址不足会用金额部分数据补0
利用Modifier完成权限方面的校验
至于合约的设计和组织:

单一大合约 VS 合约模块化
Hub – Spoke模式
使用mapping保存合约数据
合约升级的主要模式
Proxy
数据合约 + 控制合约
Truffle

猜你喜欢

转载自blog.csdn.net/guojin12345/article/details/83501823