1

我已经在 Kaleido 上成功部署了以下合约:

编译指示 ^0.4.0;

合同迎宾{
    字符串公共问候语;

    功能迎宾员(){
        问候 = '你好';
    }

    功能 setGreeting(字符串 _greeting)公共 {
        问候=_问候;
    }

    函数 greet() 常量返回(字符串){
        回礼;
    }
}

我尝试像这样与合同进行交互:

从 web3 导入 web3
从 web3.providers 导入 HTTPProvider
从 solc 导入 compile_source
从 web3.contract 导入 ConciseContract

# Solidity 源代码
contract_source_code = '''
编译指示 ^0.4.0;

合同迎宾{
    字符串公共问候语;

    功能迎宾员(){
        问候 = '你好';
    }

    功能 setGreeting(字符串 _greeting)公共 {
        问候=_问候;
    }

    函数 greet() 常量返回(字符串){
        回礼;
    }
}
'''

已编译溶胶 = 编译源(合同源代码)
contract_interface = compiled_sol[':Greeter']

w3 = Web3(HTTPProvider("https://user:password@u0telyzine-u0od4ny83j-rpc.us-east-2.kaleido.io"))

# 之前部署的地址
contract_address = Web3.toChecksumAddress("0x4c94e89d5ec3125339906109f143673f40868df2")

迎宾员 = w3.eth.contract(
    地址=合约地址,
    abi=contract_interface['abi'],
)

print('默认合同问候语:{}'.format(
    greeter.functions.greet().call()
))

# --- 这挂了 ---
print('设置问候你好...')
tx_hash = greeter.functions.setGreeting('Nihao').transact({'from': w3.eth.accounts[0], 'gas': 100000})

w3.eth.waitForTransactionReceipt(tx_hash)

print('更新的合同问候语:{}'.format(
    greeter.functions.greet().call()
))

读者 = ConciseContract(问候语)
断言 reader.greet() == "你好"

但是,当我尝试提交调用setGreeting该事务的事务时挂起。查看 Kaleido 日志,我看到了VM in read-only mode. Mutating opcode prohibited。此外,当我访问节点的区块浏览器时,交易不会在区块加载时加载。

交易未加载

我可以对这种只读模式做些什么?

4

2 回答 2

2

摩加达人

提交事务时,我无法重新创建您的“处于只读模式的虚拟机” - 成功运行。但是,我必须做一些调查才能让 web3/python 连接到 Kaleido - 所以我添加了一个单独的答案来帮助其他人尝试开始。

从 Python web3 配置对 Kaleido 的 HTTPS 身份验证

在我的 Mac 上,使用 web3 的默认 pip3 安装,我发现使用 auth 配置 Python 会话的唯一方法是使用$HOME/.netrc如下文件:

machine u0oaXXXXXX-u0c4XXXXXX-rpc.us-east-2.kaleido.io
login u0d0bxXXXX
password jA-pJdIrcRaIx7XXXXXXXXXXXXXXXXXXXXXXXXX

为 Geth/PoA 配置 web3

我的链使用 Geth/PoA,所以我必须按照此处的说明安装所需的中间件: http ://web3py.readthedocs.io/en/stable/middleware.html#geth-style-proof-of-authority

更新示例,包括合约部署

这里是成功部署并上报的python3 Updated contract greeting: Nihao。您需要将您的更改HTTPProvider为节点的 HTTPS RPC URL,但没有身份验证标头。

from web3 import Web3
from web3.providers import HTTPProvider
from solc import compile_source
from web3.contract import ConciseContract
from web3.middleware import geth_poa_middleware

# Solidity source code
contract_source_code = '''
pragma solidity ^0.4.0;

contract Greeter {
    string public greeting;

    function Greeter() {
        greeting = 'Hello';
    }

    function setGreeting(string _greeting) public {
        greeting = _greeting;
    }

    function greet() constant returns (string) {
        return greeting;
    }
}
'''

compiled_sol = compile_source(contract_source_code) 
contract_interface = compiled_sol['<stdin>:Greeter']

w3 = Web3(HTTPProvider("https://u0oaXXXXXX-u0c4XXXXXX-rpc.us-east-2.kaleido.io"))
w3.middleware_stack.inject(geth_poa_middleware, layer=0)

Greeter = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
tx_hash = Greeter.constructor().transact({ 'from': w3.eth.accounts[0], 'gas': 1000000})
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
print('Deployed greeter contract: {}'.format(tx_receipt.contractAddress))

# address from previous deployment
contract_address = Web3.toChecksumAddress(tx_receipt.contractAddress)

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

print('Default contract greeting: {}'.format(
    greeter.functions.greet().call()
))

print('Setting the greeting to Nihao...')
tx_hash = greeter.functions.setGreeting('Nihao').transact({ 'from': w3.eth.accounts[0], 'gas': 100000})

w3.eth.waitForTransactionReceipt(tx_hash)

print('Updated contract greeting: {}'.format(
    greeter.functions.greet().call()
))

reader = ConciseContract(greeter)
assert reader.greet() == "Nihao"
于 2018-07-03T13:06:02.073 回答
1

摩加达人,

“VM 处于只读模式”是因为您正在使用call与您的智能合约方法进行交互。所以它只是在只读模式下调用你的方法。您可以使用它来调用查询数据的合约上的方法 - 无需向链提交交易。

[编辑] - 上述建议通常对“只读模式下的虚拟机”有帮助,但如果您正在尝试 python web3,您可能希望通过完整的工作示例获得另一个答案:https ://stackoverflow.com/ a/51155413/4972840 [/编辑]

问候,彼得

于 2018-06-28T17:00:02.000 回答