2

Related to following answer:

function block_hash_validation(uint blockNumber, bytes32 blockHash) 
    constant returns(bool isValid) 
{
    return (block.blockhash(blockNumber) == blockHash);
}

When I call it as follows from a python script:

blockHash   = web3.eth.getBlock(0)["hash"]; //'0x040db90fe13e6688c86ff93c5ce8e4a0a61‌​faaf6a734c548febd0d0‌​b44c86aa8'
block_hash_validation(0, blockHash); 

It gives following error: TypeError: One or more arguments could not be encoded to the necessary ABI type. Expected types are: bytes32

When I replace bytes32 as string => (string blockHash) it now gives following problem:

contracts/Receipt.sol:26:48: Error: Operator == not compatible with types bytes32 
and string memory
if( blk_start_ >= blk_end_ || core_ < 0 || block.blockhash(blk_end_) == b2 )
                                           ^-----------------------------^

I have implemented following code but now the comparison is wrong:

     function block_hash_validation(uint blockNumber, string blockHash) 
         constant returns(bool isValid) 
     {
        bytes32 blockHash_result;
        assembly {
        blockHash_result := mload(add(blockHash, 32)) //this also obtains hash's first 32 characters which is wrong.
        }
         return (block.blockhash(blockNumber) == blockHash_result);
     }

=> This should have return true, but it returns false. When I only return block.blockhash(1) inside populus, it returns some random characters for example: "òÓ F»\TÕ' ʦ,ºåY¹DèÝ�¿"

In additon to that on my private ethereum network I tried following contract:

    contract C {
      function get_block_hash(uint blockNumber) constant returns( bytes32 my_hash ) {
            return (block.blockhash(blockNumber));
      }
    }

It always return "0x" for the any block numbers I have tried.

[geth]> C.get_block_hash(block.number - 1)
"0x0000000000000000000000000000000000000000000000000000000000000000"

[Q] How could I overcome those problems I am facing? Please note that I am experimenting inside populus.

Thank you for your valuable time and help.

  • Why are you using strings at all? All of the values that you are working with are <32 bytes, using strings is just asking for trouble. – Tjaden Hess Feb 4 '17 at 19:25
  • 1
    Also, you can only get the block hashes for the last 256 blocks within a contract, so if you use C.get_block_hash(1), it's going to be 0. – Tjaden Hess Feb 4 '17 at 19:26
  • 1
    Also, when you pass a the string, you need to make sure it's a binary string, not ASCII. Those random characters are the ASCII representation of the raw blockhash. Again, stay away from string if you don't absolutely need it and know exactly what you're doing. – Tjaden Hess Feb 4 '17 at 19:28
  • 1
    When you get binary junk back from the python libraries you can make sense of it with web3.utils.encoding.encode_hex() – Edmund Edgar Feb 4 '17 at 23:00
  • 1
    I wouldn't mess around with ascii here, just represent things in hex when you want to read them and bytes32 etc in the contract. When you have hex and want to pass it in, use decode_hex(). If there's a leading 0x you should strip it, eg decode_hex(myvar[2:]) – Edmund Edgar Feb 4 '17 at 23:07
1

Here's something that works as expected using javascript/truffle.

BlockHash.sol

contract BlockHash {

    function isBlockHash(uint blockNumber, bytes32 checkHash) 
        public
        constant
        returns(bool isIndeed)
    {
        return(block.blockhash(blockNumber) == checkHash);
    }

    function getBlockHash(uint blockNumber)
        public
        constant
        returns(bytes32 blockHash)
    {
        return block.blockhash(blockNumber);
    }  

}

deployed in testrpc

$ truffle migrate
...

$ truffle console
truffle(default)> var blockhash = BlockHash.deployed()
undefined
truffle(default)> blockhash.getBlockHash(1);
'0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6'
truffle(default)> blockhash.isBlockHash(1,'0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6')
true
truffle(default)> 

I would interpret that as an indication that the contract works as expected. Possibly someone else will join in with a python integration to show how that side would work.

Hope it helps.

1

I have tested @Rob Hitchens BlockHash contract. The reason I was getting "0x" was a @Tjaden Hess mentioned:

"the reason for "0x" is I can only get the block hashes for the last 256 blocks within a contract."

In the following example since blockchain starts from block number 0, I can retrieve block hash for block number 1.

Python integration side, based on @EdmundEdgar 's guide:

"When you get binary junk back from the python libraries you can make sense of it with web3.utils.encoding.encode_hex()"

using encode_hex() and decode_hex() solved the problem I was facing.

test:py

#!/usr/bin/pythonA
import StringIO
import pytest

from web3.utils.encoding import (
    encode_hex,
    decode_hex,
)

def test_linkedlist(web3, accounts, chain, unmigrated_chain):
    my_contract       = unmigrated_chain.get_contract('BlockHash');
    blockHash_        = my_contract.call().getBlockHash( 1 );
    blockHash         = encode_hex(blockHash_);
    print( blockHash ); #Prints a valid hash.

    blockHash_bytes32 = decode_hex(blockHash);
    isValid           = my_contract.call().isBlockHash( 1, blockHash_bytes32 );
    print( isValid ); ## returns True!!!

Thank you for the all help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.