背景
最近开始做以太坊区块链开发工作。大多数开发工具,包括solidity语言都倾向JavaScript。
当我开始使用Tunffle进行测试时,我发现JavaScript测试(IMO)太长,不必要。
但这是语言的本质问题。我一直比较喜欢Python,而不是js。我喜欢并在以前的项目中使用了py.test。所以如果我能选择使用py.test去测试我的智能合约话,我肯定会尝试一下。
这时候我碰到了Populus,不过目前看它还不够强大(我目前这么认为,官方可不这么看)。
最初,这是一个个人项目,它正式通过以太坊官方组织(github)的推荐,确实已经为已经完成的出色工作增加极高的可信度。
你可以在这里阅读官方英文版的文件。
测试
正如我前面提到的,我来选择尝试用py.test测试智能合约。
编写测试(连同web3.py)相当简单。
在populus test中进行试验(和truffle test类似)。它是通过py.test,执行命令是这样的py.test /。
这里我遇到了一个“小故障”,挺有意思,这个是问题和解决办法
我喜欢使用py.test的一点原因是我不需要明确地启动testrpc。
对于truffle test,testrpc或geth需要明确运行。否则你会得到以下错误:
1
2
3
4
5
6$ truffle test
Could not connect to your Ethereum client. Please check that your Ethereum client:
- is running
- is accepting RPC connections (i.e., "--rpc" option is used in geth)
- is accessible over the network
- is properly configured in your Truffle configuration file (truffle.js)
我并不是说这有什么不对,只是可以省略一步,对于懒人来说很好。
创建本地链
另外一个很好的特点是populus有truffle创建本地geth实例的功能。
这可以很容易地实现:
1populus chain new
这个功能包括了以下几个方面:
创建一个genesis.json(通常需要手工创建,或者从某个地方复制现成的并进行修改)
创建一个帐户,并且有足够的余额。
建两个脚本。一个创建创世纪块(init_chain.sh)
另一个启动“节点”(run_chain.sh)
好处是,新手不需要理解genesis.json和geth命令行中很长的列表选项和各种选项的复杂性。
这样一句话就行了。
这对有一定经验的开发人员也是有用的。可以根据需要修改genesis.json和脚本。
由于没有“修改密码”的概念,我们不能创建一个我们认为“更好”的密码,却不用删除现有的帐户,就能完成修改一个密码。这意味着需要修改run_chain.sh脚本,因为它提到了一个解锁参数的帐户。还需要修改genesis.json,因为“预置”帐户是在alloc下的。
但也是可以的接受的,因为populus这样做都是为了更方便开发。
阅读关于使用populus创建本地链的详细教程
还有一个命令:populus chain reset ,但有时不起作用。我在这里提出了一个问题。
部署智能合约
对于简单的一次性合约,有一个命令行版本:
1populus deploy
对于稍微复杂的合约部署,尤其是当需要将参数传递给合约的构造函数时,需要编写自己的Python代码。
这与在truffle中编写迁移脚本没有什么不同,不过在truffle ini上可以获得默认脚本,我们这里没有。
用命令行部署一个合约
部署是通过部署命令$ populus deploy来处理的,下面这些都是自动处理的。
选择应该被部署到哪个区块链。
运行给定区块链。
项目合约的编制。
导出库依赖关系。
库链接。
个人合同部署。
让我们部署一个简单的钱包合约。首先,我们需要一个合约在我们的./contracts目录中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14// ./contracts/Wallet.sol
contract Wallet {
mapping (address => uint) public balanceOf;
function deposit() {
balanceOf[msg.sender] += 1;
}
function withdraw(uint value) {
if (balanceOf[msg.sender] < value) throw;
balanceOf[msg.sender] -= value;
if (!msg.sender.call.value(value)()) throw;
}
}
在上面代码中,可以看到基本部署的输出。
如果在项目目录之外,请使用:
1$ populus -p /path/to/my/project deploy Wallet -c local_a
以编程方式部署合约
还可以使用Python脚本部署合约。如果你的智能合约采用构造函数参数或需要更复杂的初始化调用,这是一种合适的方法。
示例(deploy_testnet.py):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79"""Deploy Edgeless token and smart contract in testnet.
A simple Python script to deploy contracts and then do a smoke test for them.
"""
from populus import Project
from populus.utils.wait import wait_for_transaction_receipt
from web3 import Web3
def check_succesful_tx(web3: Web3, txid: str, timeout=180) -> dict:
"""See if transaction went through (Solidity code did not throw).
:return: Transaction receipt
"""
# http://ethereum.stackexchange.com/q/6007/620
receipt = wait_for_transaction_receipt(web3, txid, timeout=timeout)
txinfo = web3.eth.getTransaction(txid)
# EVM has only one error mode and it's consume all gas
assert txinfo["gas"] != receipt["gasUsed"]
return receipt
def main():
project = Project()
# This is configured in populus.json
# We are working on a testnet
chain_name = "ropsten"
print("Make sure {} chain is running, you can connect to it, or you'll get timeout".format(chain_name))
with project.get_chain(chain_name) as chain:
# Load Populus contract proxy classes
Crowdsale = chain.get_contract_factory('Crowdsale')
Token = chain.get_contract_factory('EdgelessToken')
web3 = chain.web3
print("Web3 provider is", web3.currentProvider)
# The address who will be the owner of the contracts
beneficiary = web3.eth.coinbase
assert beneficiary, "Make sure your node has coinbase account created"
# Random address on Ropsten testnet
multisig_address = "0x83917f644df1319a6ae792bb244333332e65fff8"
# Deploy crowdsale, open since 1970
txhash = Crowdsale.deploy(transaction={"from": beneficiary}, args=[beneficiary, multisig_address, 1])
print("Deploying crowdsale, tx hash is", txhash)
receipt = check_succesful_tx(web3, txhash)
crowdsale_address = receipt["contractAddress"]
print("Crowdsale contract address is", crowdsale_address)
# Deploy token
txhash = Token.deploy(transaction={"from": beneficiary}, args=[beneficiary])
print("Deploying token, tx hash is", txhash)
receipt = check_succesful_tx(web3, txhash)
token_address = receipt["contractAddress"]
print("Token contract address is", token_address)
# Make contracts aware of each other
print("Initializing contracts")
crowdsale = Crowdsale(address=crowdsale_address)
token = Token(address=token_address)
txhash = crowdsale.transact({"from": beneficiary}).setToken(token_address)
check_succesful_tx(web3, txhash)
# Do some contract reads to see everything looks ok
print("Token total supply is", token.call().totalSupply())
print("Crowdsale max goal is", crowdsale.call().maxGoal())
print("All done! Enjoy your decentralized future.")
if __name__ == "__main__":
main()
完整的示例代码在这里
迁徙
populus在旧版本中有这个特性,但是它被移除了。gitter中问的时候,被告知有一个计划会把他们带回来。
最后的想法
虽然我想用populus作为唯一的选择,但我认为这与truffle相比还是不太成熟。
现在,我用truffle作为我与他人分享的项目(因为truffle似乎更为受大家欢迎),但对于我的个人项目,我继续使用populus(并报告问题,讨论并发送PR如果我知道问题在哪儿的话)
注意:您可以在这里查看我的(正在进行中的)代码。它既有truffle,也有populus配置文件。测试只在Python中进行。我在Python中有一个部署脚本。
python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
web3j教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
以太坊教程,主要介绍智能合约与dapp应用开发,适合入门。
以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和事件等内容。
汇智网原创翻译,转载请标明出处。这里是原文