1

I've successfully deployed the following contract on 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;
    }
}

I try to interact with the contract like so:


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"

However, when I try to submit a transaction which calls setGreeting the transaction hangs. Viewing the Kaleido logs, I see VM in read-only mode. Mutating opcode prohibited. Also, when I visit the block explorer for my node, the transactions don't load while the blocks do.

transactions not loading

What can I do about this read only mode?

Paymahn Moghadasian
  • 9,301
  • 13
  • 56
  • 94

2 Answers2

2

moghadasian

I could not recreate your "VM in read-only mode" when submitting a transaction - that worked successfully. However, I had to do a bit of investigation to get web3/python connecting to Kaleido - so I'm adding a separate answer to help others trying to get going.

Configuring HTTPS authentication to Kaleido from Python web3

On my Mac, with a default pip3 installation of web3, I found the only way to configure the Python Session with auth was to use a $HOME/.netrc file such as:

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

Configure web3 for Geth/PoA

My chain was using Geth/PoA, so I had to follow the instructions here, to install the required middleware: http://web3py.readthedocs.io/en/stable/middleware.html#geth-style-proof-of-authority

Updated example including deployment of contract

Here is the python3 that successfully deployed and reported Updated contract greeting: Nihao. You will need to change your HTTPProvider to the HTTPS RPC URL of your node, but without the authentication headers.

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"
  • Thanks for all the help Peter. I'm not sure what was going on, maybe the problem came about because of Quorum + RAFT. I've since switched to Geth + PoA and it's working flawlessly now except for the fact that contract deployment takes more time than before (a few seconds instead of instant). – Paymahn Moghadasian Jul 04 '18 at 19:03
1

moghadasian,

The "VM in read-only mode" is because you are using call to interact with your Smart Contract method. So it's just calling your method in a read-only mode. You would use this to call methods on contracts that query data - without having to submit a transaction to the chain.

[edit] - the above advice is generally helpful for "VM in read-only mode", but if you're trying out python web3, you pobably want the other answer with a full working example: https://stackoverflow.com/a/51155413/4972840 [/edit]

Regards, Peter

  • Hmm, I don't think I understand. The call function `greeter.functions.greet().call()` works fine. It's the other function, `greeter.functions.setGreeting('Nihao').transact({ 'from': w3.eth.accounts[0], 'gas': 100000})` which hangs because of what looks like a read-only vm. – Paymahn Moghadasian Jun 30 '18 at 00:32
  • Hi Paymahn, I tried your solidity on Mac with the Python web3 py-solc installed via pip3. After exploring the web3 code, I found that to set the HTTPS authentication for Kaleido, I could set a `.netrc` file such as: ``` machine rcNs@u0oaulux2d-u0c4XXXXXX-rpc.us-east-2.kaleido.io login u0d0bxXXXX password jA-pJdIrcRaIx7XXXXXXXXXXXXXXXXXXXXXXXXX ``` – Peter Broadhurst Jul 03 '18 at 12:42
  • I was then connected and received: web3.exceptions.ValidationError: The field extraData is 97 bytes, but should be 32. It is quite likely that you are connected to a POA chain. Refer http://web3py.readthedocs.io/en/stable/middleware.html#geth-style-proof-of-authority for more details. The full extraData is: HexBytes(' ... Continuing to work through it – Peter Broadhurst Jul 03 '18 at 12:43
  • ... will move to an answer once I have worked through getting web3/python to connect – Peter Broadhurst Jul 03 '18 at 12:44