最近波场(TRON)发起了“加速器计划”,吸引开发者在波场上开发dApp,奖金总额高达100万美金。
今天抽了点时间研究了下波场:波场是从EthereumJ上fork出来的,共识机制换成了改良过的DPoS,另外借鉴了EOS上的RAM/CPU机制(对应Energy/Bandwidth Point)。智能合约还是用Solidity写的,唯一可能需要改动的地方:把代码里的货币单位ether/wei换算成trx/sun(波场币的最小面额是sun,孙宇晨的sun。。。),1 TRX = 1,000,000 sun。
所以,以太坊上的dApp,几乎不需要任何改动就可以移植到波场上。这里首先介绍一下波场的一些技术特点,心急赚钱的兄弟可以跳过,直接跳到第12节看怎么部署合约、连接前端就可以了,哈哈~
TRON采用了三层体系架构:
存储层:存储区块数据和状态数据
核心层:包括智能合约模块、账户管理模块、共识模块等
应用层:即各种dApp跟钱包等应用
另外,协议方面是用Google protobuf定义的,目前只有Java版本的实现,后续计划会扩展到其他语言(跟以太坊类似,以太坊也有geth,EthereumJ,cpp-ethereum等各种版本的实现)。
波场网络定义了3种类型的节点:
超级节点(Super Representative Witness Node):负责生产区块
全节点(Full Node):提供API服务,广播交易和区块
Solidity节点(Solidity Node):同步区块,提供查询API
这跟EOS基本是一样的,出于安全性考虑,最终用户是不可能直接跟超级节点通信的,需要通过全节点跟Solidity节点访问网络。如果你想做一个交易所,则需要部署一个全节点和一个Solidity节点。
波场的共识机制采用的是改良过的DPoS,称为TPoS。
网络中每6小时投一次票,选出27个超级节点负责出块和共识。投票是通过抵押TRX完成的,如果用户想取消抵押,需要等待3天才能释放。选出的超级节点轮流出块,每3秒出一个块,出块奖励会放在“超级账本“的一个子账户中,超级节点过24小时才能提取。
那么,所谓的“改良”体现在哪里呢?
我们知道,EOS的DPoS有一个问题:只有投票给前21个超级节点的用户可以分红,投给落选节点的用户一分钱都得不到。久而久之,大家就都不愿意投给排在后面的节点了,从而加剧中心化的风险。波场在DPoS基础上做了一些改良,使得落选的打包节点、投票给中选者的用户、投票给落选者的用户均可能获得一定量的补偿,以激励他们持续参与之后的竞选流程。
具体来说,奖励分为两类:
(1)投票奖励(vote reward)
每出一个块,将产生16 TRX的“投票奖励”,这部分奖励将由前127个候选节点共同瓜分。
因此,每过一轮(6小时),这127个候选节点一共会瓜分16TRX/block × 20blocks/min × 60mins/hr × 6hrs = 115,200 TRX。
(2)出块奖励(block reward)
每出一个块,将产生32 TRX的“出块奖励”,由27个超级节点共同瓜分。
因此,每过一轮(6小时),这27个候选节点一共会瓜分32TRX/block × 20blocks/min × 60mins/hr × 6hrs = 230,400TRX。
需要注意的是,这27个节点的最终收益是它们获得的“投票奖励”和“出块奖励”之和。
另外,波场承诺2021年1月1日前不增发,之后每年会增发固定数量的TRX。
当前轮次中的27个超级节点组成一个委员会,如果需要修改网络参数配置,则必须由其中一个超级节点发起提案,当收到超过19个赞成票时即可通过提案,并于3天后应用新的网络参数配置。
既然共识机制从PoW改成了TPoS,TPS必然会有提升。官方宣称能达到2000 TPS:
目前实网TPS峰值为748:
账户有基本账户、资产发布账户和合约账户三种类型:
一个账户包含账户名称、账户类型、地址、余额、投票、其他资产、上次操作时间等7种属性。更进一步的,基本账户可以申请成为验证节点,验证节点具有额外的属性,比如投票统计数目、公钥、URL、以及历史表现等等。
账户地址的生成规则结合了以太坊和比特币的特点:
数据存储主要分为两类:
交易签名和以太坊一样采用secp256k1算法,每笔交易需要等待19个区块确认,按3秒一个块来算,确认一笔交易最少需要57秒,还是比较快的。
另外,波场也借鉴了EOS中的TaPoS的概念,交易头中包含近期区块的hash,从而可以减少分叉风险。
交易有多种类型,包括账户创建、转账、转账资产、资产投票、见证节点投票、见证节点创建、资产发布、合约部署等26种类型。代码里把这些类型定义为ContractType,不是很理解。。。
另外,波场借鉴了EOS中的RAM/CPU的设计,在执行普通交易时需要消耗Bandwidth Point,而执行智能合约操作时则需要同时消耗Bandwidth Point和Energy,后面会一一介绍。
执行普通交易需要消耗“Bandwidth Point”,简称BP,类似于EOS中CPU。
每人每天5000个免费BP,如果不够用需要额外抵押TRX获取BP。消耗的BP数量和交易字节数成正比,如果BP用完了,则会消耗用户的TRX,具体消耗顺序:
用户抵押TRX获得的BP > 用户每天5000个免费BP > 消耗TRX(字节数*10 SUN)
上面的规则适用于创建和修改操作,执行查询操作是不收费的。
另外,有一些特殊交易类型采用固定收费方式:
首先提一下波场的虚拟机TVM,是在EVM的基础上改的,增加了一些投票相关的built-in函数。
另外Solidity也是从以太坊fork出来的,兼容Solidity ^0.4.24。
TVM执行智能合约需要消耗Energy,和以太坊的gas不同,Energy需要通过抵押TRX来获得。这一点和EOS上的RAM有点类似,但是不尽相同,EOS上的RAM是要用你手里的EOS去买的,而Energy则是通过抵押获得的,抵押率是一个网络参数,由委员会负责制定和修改。
看了下目前的代码,Energy的计算跟以太坊gas的计算方式基本没啥区别~
ERC-20 token大家都比较熟悉,对应到波场上叫TRC-20。另外,波场上还有一种TRC-10 token,可以理解为一种“一键发币”功能,用来应付类似于积分或者优惠券之类的需求已经足够了。
发行TRC-10 token只需要指定下面这些参数,然后发送一笔交易就搞定了:(需要消耗1024 TRX)
TRC-10 token通过API和智能合约都能访问(Explorer上也可以查到),但是只有固定的对外接口。TRC-20可以对接口进行定制,但是只能通过智能合约进行访问。另外,TRC-10的交易费用比TRC-20低1000倍,且只消耗Bandwidth Point,不消耗Energy。
介绍了这么多,那么怎么在波场上开发dApp呢?
波场的开发工具配套还是挺全的,基本上以太坊上有的它都有,参考下表中的对比:
以太坊 | 波场 | |
---|---|---|
智能合约 | Solidity | Solidity |
前端 | Web3 | TronWeb |
开发框架 | Truffle | TronBox |
IDE | Remix | TronStudio |
Chrome插件 | MetaMask | TronLink |
IaaS | Infura | TronGrid |
如果想要在本地开发dApp,建议使用docker模式在本地运行一个私有测试网,包含一个全节点、一个Solidity节点和一个Event Server(可以监听合约event):
docker run -it -p 8091:8091 -p 8092:8092 -p 8090:8090 -p 50051:50051 -p 50052:50052 --rm --name tron trontools/quickstart:1.2.6
其中8090和8091分别是全节点和Solidity节点的HTTP端口,50051和50052分别是全节点和Solidity节点的gRPC端口,8092是Event Server的通信端口。
可以用下面的命令验证一下节点是否运行正常:
docker exec -it tron ps aux
默认情况下会帮你创建10个测试账户,每个账户里有10000TRX,可以用下面的命令查询账户信息:
curl http://127.0.0.1:8090/admin/accounts
TronStudio是波场的智能合约开发IDE,类似于以太坊中的Remix。
首先下载TronStudio源码:
git clone https://github.com/tronprotocol/tron-studio
然后编译,注意必须是Java8,我机器上装的Java10编译会报错。。
./gradlew build -x test -x check
启动TronStudio:
java -jar build/libs/TronStudio.jar
接下来就可以愉快地编写HelloWorld合约了,界面长这样:
编译合约:点击Compile按钮
部署合约:首先点击右上角齿轮,配置Local TVM地址和端口:127.0.0.1:50051,然后点击右边的Deploy按钮就可以了。合约部署完后可以在右边的面板中发起合约调用。
和以太坊中的Web3类似,波场中的dApp使用TronWeb和节点进行通信。
如果你只是想在命令行上试用一下TronWeb的API,可以下载下面的工具,类似于以太坊的geth控制台:
git clone https://github.com/tronprotocol/docker-tron-quickstart.git
然后安装依赖:
cd docker-tron-quickstart
cd app
npm install
cd ..
注意:代码中默认指定的端口是9090,需要改成我们刚刚运行docker时指定的端口号,修改app/src/config.js:
接下了就可以用下面的命令进入node命令行了:
node tronWeb
比如我们可以用下面的命令查询区块信息、交易的执行情况:
tronWeb.trx.getCurrentBlock().then(result => console.log(result))
tronWeb.trx.getTransaction('0f71dd1bd643bb953fe6d609d05112d8645b1e621e5dffd248cda46069c1af5e').then(result => console.log(result))
完整API列表参见:https://developers.tron.network/v3.0/reference#tronwebapi
如果你是一个前端程序员,需要在代码里访问节点,那么只需要在你的项目添加tronweb依赖:
npm install tronweb
然后就可以在代码使用了,以调用上面的HelloWorld合约为例:
const TronWeb = require('tronweb');
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = new HttpProvider('http://127.0.0.1:8090'); //Your local TVM URL
const solidityNode = new HttpProvider('http://127.0.0.1:8091');
const eventServer = 'http://127.0.0.1:8092';
const privateKey = '6d8d7cdc92dbcbe945643efe1a9fcd80d875ea82fbee3460ee0207611d12e1e9';
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
privateKey
);
async function changestate(){
let contractAddress = 'TKjGYzq8svwBZXKSsV1bsmNZTeMswrncHe'; //Your address
let contract = await tronWeb.contract().at(contractAddress);
let resultPost = await contract.postMessage("TRON to the Future").send();
let resultGet = await contract.getMessage().call();
console.log('resultGet: ', resultGet);
}
changestate()
首先需要创建一个TronWeb对象,其中fullNode和solidityNode参数是必须指定的,后面两个参数可选。
TronWeb对象内部包含了好几个模块:
具体的调用方法参见上面的API列表链接,或者你也可以直接看源码:
波场目前前的实现基本上就是以太坊+DPoS,同时借鉴了EOS上的一些概念。实际上,在波场上开发dApp和在以太坊上基本没多大区别,想赚快钱的小伙伴赶紧行动起来,提交自己的dApp作品吧,截止时间是2019年1月4日,第一名的奖金是20万美金哦~
更多文章欢迎关注“鑫鑫点灯”专栏:https://blog.csdn.net/turkeycock
或关注飞久微信公众号: