建议和反馈

请填写你的反馈内容

使用Python编译,部署和调用以太坊智能合约

2020-01-13 ·944次阅读 ·读完需要2分钟

我们在Ubuntu 16.04上使用Python 3.5.3,并进行以下设置:

  1. pip3 install web3==4.7.2 py-solc==3.2.0

  2. python3 -m solc.install v0.4.24

  3. export PATH="$PATH:$HOME/.py-solc/solc-v0.4.24/bin

核心软件包是:

  1. web3  :与以太坊区块链交互的官方python界面

  2. py-solcsolcsolidity编译器)的官方python包装器。因此solc需要安装(在上面的设置中覆盖)

要在文件(.sol)中编译实体智能合约,我们可以使用以下方法:

  1. def compile_contract(contract_source_file, contractName=None):

  2.    """

  3.    Reads file, compiles, returns contract name and interface

  4.    """

  5.    with open(contract_source_file, "r") as f:

  6.        contract_source_code = f.read()

  7.    compiled_sol = compile_source(contract_source_code) # Compiled source code

  8.    if not contractName:

  9.        contractName = list(compiled_sol.keys())[0]

  10.        contract_interface = compiled_sol[contractName]

  11.    else:

  12.        contract_interface = compiled_sol['<stdin>:' + contractName]        

  13.    return contractName, contract_interface

要部署已编译的智能合约,我们使用:

  1. def deploy_contract(acct, contract_interface, contract_args=None):

  2.    """

  3.    deploys contract using self-signed tx, waits for receipt, returns address

  4.    """

  5.    contract = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])

  6.    constructed = contract.constructor() if not contract_args else contract.constructor(*contract_args)

  7.    tx = constructed.buildTransaction({

  8.        'from': acct.address,

  9.        'nonce': w3.eth.getTransactionCount(acct.address),

  10.    })

  11.    print ("Signing and sending raw tx ...")

  12.    signed = acct.signTransaction(tx)

  13.    tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction)

  14.    print ("tx_hash = {} waiting for receipt ...".format(tx_hash.hex()))

  15.    tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash, timeout=120)

  16.    contractAddress = tx_receipt["contractAddress"]

  17.    print ("Receipt accepted. gasUsed={gasUsed} contractAddress={contractAddress}".format(**tx_receipt))

  18.    return contractAddress

部署后,我们可以创建合约对象来调用其公共读取方法或属性:

  1. contract = w3.eth.contract(address=contract_address, abi=contract_interface['abi'])

  2. # call public methods

  3. val = contract.functions.get().call()

  4. # call public attributes

  5. val = contract.functions.storedData().call()

但是为了调用write / update方法,我们需要创建一个事务:

  1. def exec_contract(acct, nonce, func):

  2.    """

  3.    call contract transactional function func

  4.    """

  5.    construct_txn = func.buildTransaction({'from': acct.address, 'nonce': nonce})

  6.    signed = acct.signTransaction(construct_txn)

  7.    tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction)

  8.    return tx_hash.hex()

这是一个使用上述方法来编译,部署和调用简单智能合约的示例:

  1. // contract.sol

  2. pragma solidity ^0.4.21;

  3. contract simplestorage {

  4.  uint public storedData;

  5.  event Updated(address by, uint _old, uint _new);

  6.  function set(uint x) {

  7.    uint old = storedData;

  8.    storedData = x;

  9.    emit Updated(msg.sender, old, x);

  10.  }

  11.  function get() constant returns (uint retVal) {

  12.    return storedData;

  13.  }

  14. }

    1. from web3 import Web3, HTTPProvider

    2. from solc import compile_source

    3. import random

    4. # config

    5. RPC_ADDRESS = 'http://localhost:8545'

    6. CONTRACT_SOL = 'contract.sol'

    7. CONTRACT_NAME = 'simplestorage'

    8. PRIVATE_KEY = "yourprivatekey"

    9. # instantiate web3 object

    10. w3 = Web3(HTTPProvider(RPC_ADDRESS, request_kwargs={'timeout': 120}))    

    11. acct = w3.eth.account.privateKeyToAccount(PRIVATE_KEY)

    12. # compile contract to get abi

    13. print('Compiling contract..')

    14. contract_name, contract_interface = compile_contract(CONTRACT_SOL, CONTRACT_NAME)

    15. # deploy contract    

    16. print('Deploying contract..')

    17. contract_address = deploy_contract(acct, contract_interface)

    18. # create contract object

    19. contract = w3.eth.contract(address=contract_address, abi=contract_interface['abi'])

    20. # call non-transactional method

    21. val = contract.functions.get().call()

    22. print('Invoke get()={}'.format(val))

    23. assert val == 0

    24. # call transactional method

    25. nonce = w3.eth.getTransactionCount(acct.address)

    26. from_block_number = w3.eth.blockNumber  

    27. new_val = random.randint(1, 100)      

    28. contract_func = contract.functions.set(new_val)

    29. print('Invoke set()={}'.format(new_val))

    30. tx_hash = exec_contract(acct, nonce, contract_func)

    31. print('tx_hash={} waiting for receipt..'.format(tx_hash))

    32. tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash, timeout=120)        

    33. print("Receipt accepted. gasUsed={gasUsed} blockNumber={blockNumber}". format(**tx_receipt))

    34. # catch event

    35. contract_filter = contract.events.Updated.createFilter(fromBlock=from_block_number)

    36. entries = None

    37. print('Waiting for event..')

    38. while not entries: entries = contract_filter.get_all_entries()    

    39. # _new == new_val

    40. args = entries[0].args

    41. print(args)

    42. assert args._old == 0

    43. assert args._new == new_val

    44. assert args.by == acct.address

    45. # call non-transactional method

    46. val = contract.functions.get().call()

    47. print('Invoke get()={}'.format(val))

    48. assert val == new_val

如果您使用的是infura.io,则此代码也将适用,但“ catch event”部分除外,因为infura.io不支持  eth_newFilter

完整的代码可以在我的github中找到。请享用!

评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

以太坊区块链的简单可靠性智能合约

这是使用Solidity的典型智能合约示例简单银行的修改版本,例如:https : //github.com/ScottWorks/ConsenSys-Academy-Notes/blob/maste......
区块链社区 · 2020-01-21
751阅读 · 0赞赏 · 0问答

如何从私钥创建以太坊钱包地址

在本系列的第一篇文章中,我们生成了一个比特币私钥:60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2。在这里,我们将使用该......
区块链网 · 2020-01-19
708阅读 · 0赞赏 · 0问答

plasma能否解决以太坊的可扩展性问题?

plasma是一种新技术,可以解决以太坊的可扩展性问题。第二大市值的以太坊(Ethereum)试图解决Plasma和更高级的Plasma Cash的各种问题。在本文中,我们将介绍plasma的机理和好......
区块链社区 · 2020-01-14
805阅读 · 0赞赏 · 0问答

web3.js v1.0.0如何监控以太坊合约

为了使前台显示的数据与DApp中合同的数据同步,我检查了是否可以监视合约的状态。这可以通过定期获取数据来实现,但是考虑到前部负载和气体成本,我们将选择一种有效的方法。验证DApp将SetValue事件......
Blockchain · 2020-01-14
952阅读 · 0赞赏 · 0问答

以太坊挖矿初学者指南

挖矿在区块链应用中很受欢迎,围绕比特币的炒作真的不足为奇。开采比特币需要大量投资于一种非常专业的机器。它被称为ASIC矿工。ASIC是专用集成电路的缩写。简而言之,这些设备是为完成一件事情而定制的:挖......
古风 · 2020-01-13
1015阅读 · 0赞赏 · 0问答

HBO

2251

LK币

19

粉丝

40

笔记

感谢"HBO"

这篇精彩的笔记,目前已经帮助

  • 0
  • 0
  • 9
  • 4
  • 4
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!