0

From Antonopoulos' book I try to use the example 3-3 on page 49 which uses a python skript called rpc_example.py to show the usage of the JSON-RPC API:

    from bitcoin.rpc import RawProxy
    p = RawProxy()
    info = p.getinfo()
    print(info['blocks'])

which on $ python rpc_example.py should give 394875.


Of course getinfo has been depricated and I would like to use another function, for example getblock.

I am not sure if I use it correctly or if I have an error in my syntax or if the problem below is due to something related to python.


I already had some troubles installing the library with pip install python-bitcoinlib and also did pip3 install python-bitcoinlib because I was not sure if the problem I now have is related to encoding/decoding in python version 2.


My code now is

from bitcoin.rpc import RawProxy
p = RawProxy()
infoblock = p.getblock()
print(infoblock['difficulty'])

which should print the difficulty of the block, at least in my understanding (I am new to python and to bitcoin).

I get the following error with python 2:

$ python BuchSkripte/49_rpc_example.py
Traceback (most recent call last):
File "BuchSkripte/49_rpc_example.py", line 2, in <module>
    p = RawProxy()
File "/usr/local/lib/python2.7/dist-packages/bitcoin/rpc.py", line 295, in __init__
    **kwargs)
File "/usr/local/lib/python2.7/dist-packages/bitcoin/rpc.py", line 159, 
in __init__
    if '#' in line:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 5: ordinal not in range(128)

With python3 I get:

$ python3 BuchSkripte/49_rpc_example.py
Traceback (most recent call last):
  File "BuchSkripte/49_rpc_example.py", line 3, in <module>
    infoblock = p.getblock()
  File "/usr/local/lib/python3.5/dist-packages/bitcoin/rpc.py", line 306, in <lambda>
    f = lambda *args: self._call(name, *args)
  File "/usr/local/lib/python3.5/dist-packages/bitcoin/rpc.py", line 238, in _call
    raise JSONRPCError(response['error'])
bitcoin.rpc.JSONRPCError: {'code': -1, 'message': 'getblock "blockhash" ( verbosity )\n\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block \'hash\'.\nIf verbosity is 1, returns an Object with information about block <hash>.\nIf verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n\nArguments:\n1. blockhash    (string, required) The block hash\n2. verbosity    (numeric, optional, default=1) 0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data\n\nResult (for verbosity = 0):\n"data"             (string) A string that is serialized, hex-encoded data for block \'hash\'.\n\nResult (for verbosity = 1):\n{\n  "hash" : "hash",     (string) the block hash (same as provided)\n  "confirmations" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n  "size" : n,            (numeric) The block size\n  "strippedsize" : n,    (numeric) The block size excluding witness data\n  "weight" : n           (numeric) The block weight as defined in BIP 141\n  "height" : n,          (numeric) The block height or index\n  "version" : n,         (numeric) The block version\n  "versionHex" : "00000000", (string) The block version formatted in hexadecimal\n  "merkleroot" : "xxxx", (string) The merkle root\n  "tx" : [               (array of string) The transaction ids\n     "transactionid"     (string) The transaction id\n     ,...\n  ],\n  "time" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n  "mediantime" : ttt,    (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n  "nonce" : n,           (numeric) The nonce\n  "bits" : "1d00ffff", (string) The bits\n  "difficulty" : x.xxx,  (numeric) The difficulty\n  "chainwork" : "xxxx",  (string) Expected number of hashes required to produce the chain up to this block (in hex)\n  "nTx" : n,             (numeric) The number of transactions in the block.\n  "previousblockhash" : "hash",  (string) The hash of the previous block\n  "nextblockhash" : "hash"       (string) The hash of the next block\n}\n\nResult (for verbosity = 2):\n{\n  ...,                     Same output as verbosity = 1.\n  "tx" : [               (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 "tx" result.\n         ,...\n  ],\n  ,...                     Same output as verbosity = 1.\n}\n\nExamples:\n> bitcoin-cli getblock "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"\n> curl --user myusername --data-binary \'{"jsonrpc": "1.0", "id":"curltest", "method": "getblock", "params": ["00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"] }\' -H \'content-type: text/plain;\' http://127.0.0.1:8332/\n'}

1 Answer 1

1

Your code works well, but you have an error when you go to call the function getBlock(), with the bitcoin core reference the getBlock() function have a parameter and this parameter is the hash of the block.

So, your code works because of the RPC framework response with an error

bitcoin.rpc.JSONRPCError: {'code': -1, 'message': 'getblock "blockhash" ( verbosity )\n\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block \'hash\'.\nIf verbosity is 1, returns an Object with information about block <hash>.\nIf verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n\nArguments:\n1. blockhash    (string, required) The block hash\n2. verbosity    (numeric, optional, default=1) 0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data\n\nResult (for verbosity = 0):\n"data"             (string) A string that is serialized, hex-encoded data for block \'hash\'.\n\nResult (for verbosity = 1):\n{\n  "hash" : "hash",     (string) the block hash (same as provided)\n  "confirmations" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n  "size" : n,            (numeric) The block size\n  "strippedsize" : n,    (numeric) The block size excluding witness data\n  "weight" : n           (numeric) The block weight as defined in BIP 141\n  "height" : n,          (numeric) The block height or index\n  "version" : n,         (numeric) The block version\n  "versionHex" : "00000000", (string) The block version formatted in hexadecimal\n  "merkleroot" : "xxxx", (string) The merkle root\n  "tx" : [               (array of string) The transaction ids\n     "transactionid"     (string) The transaction id\n     ,...\n  ],\n  "time" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n  "mediantime" : ttt,    (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n  "nonce" : n,           (numeric) The nonce\n  "bits" : "1d00ffff", (string) The bits\n  "difficulty" : x.xxx,  (numeric) The difficulty\n  "chainwork" : "xxxx",  (string) Expected number of hashes required to produce the chain up to this block (in hex)\n  "nTx" : n,             (numeric) The number of transactions in the block.\n  "previousblockhash" : "hash",  (string) The hash of the previous block\n  "nextblockhash" : "hash"       (string) The hash of the next block\n}\n\nResult (for verbosity = 2):\n{\n  ...,                     Same output as verbosity = 1.\n  "tx" : [               (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 "tx" result.\n         ,...\n  ],\n  ,...                     Same output as verbosity = 1.\n}\n\nExamples:\n> bitcoin-cli getblock "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"\n> curl --user myusername --data-binary \'{"jsonrpc": "1.0", "id":"curltest", "method": "getblock", "params": ["00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"] }\' -H \'content-type: text/plain;\' http://127.0.0.1:8332/\n'}

I think the problem is your configuration bitcoin-core, the code of the RawProxy, wants bitcoin to be configured in the default directory

This is the code for the how configuration library

if service_url is None:
            # Figure out the path to the bitcoin.conf file
            if btc_conf_file is None:
                if platform.system() == 'Darwin':
                    btc_conf_file = os.path.expanduser('~/Library/Application Support/Bitcoin/')
                elif platform.system() == 'Windows':
                    btc_conf_file = os.path.join(os.environ['APPDATA'], 'Bitcoin')
                else:
                    btc_conf_file = os.path.expanduser('~/.bitcoin')
                btc_conf_file = os.path.join(btc_conf_file, 'bitcoin.conf')

            # Bitcoin Core accepts empty rpcuser, not specified in btc_conf_file
            conf = {'rpcuser': ""}

            # Extract contents of bitcoin.conf to build service_url
            try:
                with open(btc_conf_file, 'r') as fd:
                    for line in fd.readlines():
                        if '#' in line:
                            line = line[:line.index('#')]
                        if '=' not in line:
                            continue
                        k, v = line.split('=', 1)
                        conf[k.strip()] = v.strip()

            # Treat a missing bitcoin.conf as though it were empty
            except FileNotFoundError:
                pass

            if service_port is None:
                service_port = bitcoin.params.RPC_PORT
            conf['rpcport'] = int(conf.get('rpcport', service_port))
            conf['rpchost'] = conf.get('rpcconnect', 'localhost')

            service_url = ('%s://%s:%d' %
                ('http', conf['rpchost'], conf['rpcport']))

Inside your code, if you have written with correct syntax you can run the command with the hash of the block, ann example

from bitcoin.rpc import RawProxy
p = RawProxy()
hash = p.getbestblockhash(0)
infoblock = p.getblock(hash)
print(infoblock['time'])

This is the official documentation rpc framework of bitcoin core

12
  • yes, i was just figuring it out myself also. :))) the function in the example does not need an argument.
    – bomben
    Aug 28, 2019 at 17:56
  • Yes, I add the reference to the rpc documentation in the my answar Aug 28, 2019 at 17:57
  • What I did not think of was the need for password and user. We talked earlier today and back then the user credentials where actually not necessary because my bitcoin-cli runs on the same machine as bitcoind. In this case another form of authentication will be used. But I have to include the RPC connection into python now, right? I try to keep it simple so I will enter a fixed hash into the script.
    – bomben
    Aug 28, 2019 at 18:03
  • Did you check your code? Even if I put a fixed hash (I got from bitcoin-cli I am not able to get the skript to work. And I am sure the skript should work without authentication stuff because the example from the book also did. Also, your documentation is for pip install python-bitcoinrpc but I installed python-bitcoinlib. Not sure if it is the same...
    – bomben
    Aug 28, 2019 at 18:24
  • The class RawProxy is doing all of the authentication from the config file. I probably have to put username and password into this file.
    – bomben
    Aug 28, 2019 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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