我已经在Kaleido上成功部署了以下合同:
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; } }
我尝试像这样与合同进行互动:
from web3 import Web3 from web3.providers import HTTPProvider from solc import compile_source from web3.contract import ConciseContract # 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[':Greeter'] w3 = Web3(HTTPProvider("https://user:password@u0telyzine-u0od4ny83j-rpc.us-east-2.kaleido.io")) # address from previous deployment contract_address = Web3.toChecksumAddress("0x4c94e89d5ec3125339906109f143673f40868df2") greeter = w3.eth.contract( address=contract_address, abi=contract_interface['abi'], ) print('Default contract greeting: {}'.format( greeter.functions.greet().call() )) # --- this hangs --- 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"
但是,当我尝试提交调用setGreeting
的事务时,事务挂起。查看Kaleido日志,我看到VM in read-only mode. Mutating opcode prohibited
。另外,当我访问节点的区块浏览器时,事务不会加载,而区块却会加载。
对于这种只读模式我该怎么办?
答案 0 :(得分:1)
moghadasian,
“处于只读模式的VM”是因为您正在使用call
与Smart Contract方法进行交互。因此,它只是以只读模式调用您的方法。您可以使用它来调用查询数据合同的方法,而不必向链上提交交易。
[edit]-上面的建议通常对“处于只读模式的VM”很有帮助,但是如果您尝试使用python web3,则可能需要其他答案以及完整的工作示例:https://stackoverflow.com/a/51155413/4972840 [/ edit]
关于彼得,
答案 1 :(得分:1)
moghadasian
提交事务时,我无法重新创建“只读模式的VM”-成功运行。 但是,我必须做一些调查才能使web3 / python连接到Kaleido-因此,我添加了一个单独的答案来帮助其他尝试入门的人。
在我的Mac上,默认安装了web3的pip3,我发现用auth配置Python会话的唯一方法是使用$HOME/.netrc
文件,例如:
machine u0oaXXXXXX-u0c4XXXXXX-rpc.us-east-2.kaleido.io
login u0d0bxXXXX
password jA-pJdIrcRaIx7XXXXXXXXXXXXXXXXXXXXXXXXX
我的连锁店使用的是Geth / PoA,因此我必须按照此处的说明安装所需的中间件: http://web3py.readthedocs.io/en/stable/middleware.html#geth-style-proof-of-authority
这是成功部署并报告Updated contract greeting: Nihao
的python3。
您需要将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"