web3.py: eth_abi.exceptions.InsufficientDataBytes: Tried to read 32 bytes. Only got 0 bytes
- Version: 3.8.1
- Python: 3.5
- OS: linux
- Parity v1.7.0-unstable-b0e4c91-20170502/x86_64-linux-gnu/rustc1.17.0
What was wrong?
While trying to fix #181, I updated my toolchain and now I’m having problems interacting with my contract.
Setting up web3 works fine
# load contract ABI
contractAbi = json.loads(open('../contracts/MeasPub.abi').read())
measpub = web3.eth.contract(abi = contractAbi)
f=open('MeasPub.address')
measpub.address = f.read().strip()
f.close()
f=open('publisher.address')
publisher_addr = f.read().strip()
f.close()
web3.personal.unlockAccount(account = publisher_addr, passphrase='*******')
but then I want to call a function
N = measpub.call({'from':publisher_addr}).getSubscriberCount()
which fails with:
Traceback (most recent call last):
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/web3/contract.py", line 767, in call_contract_function
output_data = decode_abi(output_types, return_data)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_abi/abi.py", line 108, in decode_abi
return decoder(stream)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_abi/decoding.py", line 102, in __call__
return self.decode(stream)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_utils/functional.py", line 22, in inner
return callback(fn(*args, **kwargs))
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_abi/decoding.py", line 140, in decode
yield decoder(stream)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_abi/decoding.py", line 102, in __call__
return self.decode(stream)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_abi/decoding.py", line 165, in decode
raw_data = cls.read_data_from_stream(stream)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_abi/decoding.py", line 247, in read_data_from_stream
len(data),
eth_abi.exceptions.InsufficientDataBytes: Tried to read 32 bytes. Only got 0 bytes
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "publisher.py", line 96, in <module>
main()
File "publisher.py", line 62, in main
N = measpub.call({'from':publisher_addr}).getSubscriberCount()
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/eth_utils/string.py", line 85, in inner
return force_obj_to_text(fn(*args, **kwargs))
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/web3/contract.py", line 779, in call_contract_function
raise_from(BadFunctionCallOutput(msg), e)
File "/home/ethadm/.virtualenvs/dapp/lib/python3.5/site-packages/web3/utils/exception_py3.py", line 2, in raise_from
raise my_exception from other_exception
web3.exceptions.BadFunctionCallOutput: Could not decode contract function call getSubscriberCount return data 0x for output_types ['uint256']
And here’s my contract, which I did successfully test with truffle/mocca//testRPC:
pragma solidity ^0.4.6;
contract MeasPub
{
address public publisher;
string public description;
uint public price_per_second; // [wei per second]
// dictionary that maps addresses to balances
// always be careful about overflow attacks with numbers
mapping (address => uint) private balances;
// dictionary that remebers the timestamp when the last measurement was published to that subscriber
mapping (address => uint) private last_publish_block;
// dictionary that provides an iterable list of subscribers
mapping (uint => address) private subscriber_index;
uint subscriber_count;
// dictionary for RSA public keys
mapping (address => string) private subscriber_pubkey;
event LogPublished(
address _subscriber, // the subscriber
bytes _pwdenc, // the encoded password needed for decryption of data stored in ipfs
bytes _ipfsaddr, // the ipfs address where the encrypted measurement can be fetched by the subscriber
uint _cost // cost of single publishing item
);
event LogDebug(
string _msg
);
// The constructor. It accepts a string input that describes the nature of this publishing.
function MeasPub() public
{
publisher = msg.sender;
price_per_second = 0; // Wei
}
// the publisher may change pricing anytime
function setPricePerSecond(uint _price) public
{
if (msg.sender == publisher)
price_per_second = _price;
}
function publish(address _subscriber, bytes _pwdenc, bytes _ipfsaddr) public returns (bool covered)
{
if (msg.sender == publisher)
{
uint cost;
cost = (now - last_publish_block[_subscriber]) * price_per_second;
if (balances[_subscriber] >= cost)
{
balances[_subscriber] -= cost;
// send money to publisher
if (!publisher.send(cost))
{
balances[_subscriber] += cost;
return false;
}
last_publish_block[_subscriber] = now;
LogPublished(_subscriber, _pwdenc, _ipfsaddr, cost);
return true;
}
LogDebug("subscriber has insufficient funds");
return false;
}
LogDebug("only publisher can publish");
return false;
}
function getSubscriberCount() public returns (uint count)
{
//if (msg.sender == publisher)
return subscriber_count;
}
function getSubscriber(uint _index) public returns (address _subscriber, string _pubkey)
{
if (msg.sender == publisher)
return (subscriber_index[_index],subscriber_pubkey[subscriber_index[_index]]);
}
function subscribe(string _pubkey) payable public returns (bool success) {
if (last_publish_block[msg.sender] == uint(0x0))
{
// subscriber is new to us
last_publish_block[msg.sender] = now;
subscriber_index[subscriber_count] = msg.sender;
subscriber_count += 1;
}
subscriber_pubkey[msg.sender] = _pubkey;
balances[msg.sender] += msg.value;
LogDebug("new subscription successful");
return true;
}
/**********
Standard kill() function to recover funds
**********/
function kill()
{
if (msg.sender == publisher)
suicide(publisher); // kills this contract and sends remaining funds back to creator
}
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 3
- Comments: 31 (20 by maintainers)
I think this can be safely closed.
I solved this by changing the function that generates the event from external to public in solidity. For web3js this was irrelevant, but was not the case for web3py.
https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#types
@carver I think this indicates that booleans are QUANTITY
Now what I’m curious about is whether solidity is returning
0x
(empty return value) for false, or if javascript is incorrectly interpreting no return value asfalse
.