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'}
bomben
  • 498
  • 2
  • 4
  • 11

1 Answers1

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

vincenzopalazzo
  • 1,303
  • 1
  • 8
  • 26
  • yes, i was just figuring it out myself also. :))) the function in the example does not need an argument. – bomben Aug 28 '19 at 17:56
  • Yes, I add the reference to the rpc documentation in the my answar – vincenzopalazzo Aug 28 '19 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 '19 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 '19 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 '19 at 18:44
  • So, yes the my reference is wrong, sorry the my code example is the another library. – vincenzopalazzo Aug 28 '19 at 18:49
  • it is not magic but it searches in the standard configuration, I have a personal directory where I aligned bitcoin core and the library generates this error for me `File "/usr/local/lib/python3.6/dist-packages/bitcoin/rpc.py", line 183, in __init__ with open(cookie_file, 'r') as fd: FileNotFoundError: [Errno 2] No such file or directory: '/home/vincenzo/.bitcoin/.cookie'` – vincenzopalazzo Aug 28 '19 at 18:51
  • i think cookie refers to authentication without user/password. for me it does also not work with user/password in the config file. will work on it tomorrow. – bomben Aug 28 '19 at 18:52
  • I have add the another library because I think the python-bitcoinrpc not is more magic and for a while the idea of what's going on – vincenzopalazzo Aug 28 '19 at 18:52
  • You have the bitcoin inside the home dir? – vincenzopalazzo Aug 28 '19 at 18:53
  • Update my answer @Ben – vincenzopalazzo Aug 28 '19 at 19:00
  • Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/98012/discussion-between-ben-and-vincenzopalazzo). – bomben Aug 29 '19 at 05:33