bibajz / bitcoin-python-async-rpc Goto Github PK
View Code? Open in Web Editor NEWMinimal Bitcoin JSON-RPC Python asynchronous client
License: MIT License
Minimal Bitcoin JSON-RPC Python asynchronous client
License: MIT License
Hello, I'm having an issue collecting the network hash rate. I've used this repo to collect transaction and network information before, but I'm having issues with the getnetworkhashps()
function.
It's throwing this error:
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
SCRIPT:
# needed to connect to btc node
btc_rpc_connection = AuthServiceProxy("http://%s:%s@%s"%(RPC_BTC_USER, RPC_BTC_PASS, BTC_NODE))
x = btc_rpc_connection.getnetworkhashps()
print(x)
Any help would be great. Thanks
HI,I am new to Bitcoin, I have a problem and need help, first of all, thank you, the following is my question:
I tried to use the following code to convert the scriptPubKey in the Bitcoin transaction to an address, but why p2sh cannot be converted? Is there a similar python package that can be converted to an address by drinking it directly
I got no address from the rpc interface
{'txid': 'ca0cae6cd13e9150757612b1a3ea2e0e2d990d31098252892d032ffa73fc4f83', 'hash': 'ca0cae6cd13e9150757612b1a3ea2e0e2d990d31098252892d032ffa73fc4f83', 'version': 1, 'size': 205, 'vsize': 205, 'weight': 820, 'locktime': 0, 'vin': [{'txid': '05a9f3f1ed8099af7f37f818ce92442a1dccf9b471375bcb7dd4771db8080361', 'vout': 0, 'scriptSig': {'asm': '0 3045022041a325a85809d9b0c14b7858d8a7169f6dd847d41dbf342bfb745d76d15699c1022100cd6e77a8c3ffb95372d5ea716e0522efe121f253cf2381fd1d004204a8feeee7[ALL]', 'hex': '00483045022041a325a85809d9b0c14b7858d8a7169f6dd847d41dbf342bfb745d76d15699c1022100cd6e77a8c3ffb95372d5ea716e0522efe121f253cf2381fd1d004204a8feeee701'}, 'sequence': 4294967295}], 'vout': [{'value': 1.999, 'n': 0, 'scriptPubKey': {'asm': '1 037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588 0002d4a196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a2403937 2 OP_CHECKMULTISIG', 'hex': '5121037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588210002d4a196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a240393752ae', 'type': 'nonstandard'}}], 'hex': '0100000001610308b81d77d47dcb5b3771b4f9cc1d2a4492ce18f8377faf9980edf1f3a905000000004a00483045022041a325a85809d9b0c14b7858d8a7169f6dd847d41dbf342bfb745d76d15699c1022100cd6e77a8c3ffb95372d5ea716e0522efe121f253cf2381fd1d004204a8feeee701ffffffff01603bea0b00000000475121037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588210002d4a196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a240393752ae00000000', 'blockhash': '00000000000002b211876fa753c8bf5c3b4f43198c6a20d91b26cd1ed5b71918', 'confirmations': 471187, 'time': 1355895514, 'blocktime': 1355895514}
I tried to convert the address myself, but it still doesn't work? Is there any way? thank you
def cover_address(script_pub_key):
script_pub_key_str=hashStr(script_pub_key)
if script_pub_key_str[0:4]==b'76a9':
#This is a pubkeyhash
bytes=script_pub_key[2] #number of bytes in the pub_key
try:
assert bytes==20
except:
return None
public_key = script_pub_key[3:3+bytes] #20 bytes
z=b'\00'+public_key
#checksum=sha256(sha256(z))[:4]
#address1=base58.b58encode(z + checksum)
address2=base58.b58encode_check(z) # adds checksum for you
return format(address2.decode())
elif script_pub_key_str[0:2]==b'a9':
#this is a scripthash (pay-to-script address)
bytes=script_pub_key[1] #number of bytes in the pub_key
try:
assert bytes==20
except:
return None
public_key = script_pub_key[2:2+bytes] #20 bytes
z=b'\05'+public_key #used for mainnet
address2=base58.b58encode_check(z)
return address2.decode()
elif script_pub_key_str[0:2]==b'00':
spk = binascii.unhexlify(script_pub_key_str.decode())
version = spk[0] - 0x50 if spk[0] else 0
program = spk[2:]
return bech32.encode('bc', version, program)
else:
#print(script_pub_key_str)
return None
Hi - thank you for this great (and light) library!
Upon exiting the script, I often get the following warning:
/lib/python3.9/site-packages/httpx/_client.py:1781: UserWarning: Unclosed <httpx.AsyncClient object at 0x7ac57ff51310>.
See https://www.python-httpx.org/async/#opening-and-closing-clients for details.
I'm not really familiar with the httpx library so not sure what this implies. Should the bitcoinrpc library provide a call to close the httpxAsyncClient?
Since version v0.3.1
I claim this package is python3.9
compatible. This statement is backed only by the fact I was able to install it on python3.9.0rc1
and call
...
>>> await rpc.getbestblockhash()
... yes, it does return correct hash
That is weak.
To be confident this package is able to withstand production-level usage and reach v1
status, test suite must be devised.
class Btc():
def connect(self):
self.ConnRpc = BitcoinRPC(RPC_ADDRESS, RPC_PORT, RPC_USER,RPC_PASSWORD)
self.OldConnRpc=AuthServiceProxy("http://%s:%s@%s"%(RPC_USER, RPC_PASSWORD, OLDRPC_ADDRESS))
async def async_get_tx(self,tx):
while True:
raw_tx = await self.ConnRpc.getrawtransaction(tx, True)
break
async def extract_block_addresses(self, block_hash):
block = self.OldConnRpc.getblock(block_hash)
tasks = []
for tx in block[u'tx']:
tasks.append(self.async_get_tx(tx))
await asyncio.gather(*tasks)
def get_block_address(self,block):
add_insert = []
while True:
try:
block_hash = self.OldConnRpc.getblockhash(block)
break
except:
self.connect()
print("get block error")
sleep(1)
self.loop.run_until_complete(self.extract_block_addresses(block_hash))
Is the error below caused by the query speed being too fast?
Traceback (most recent call last):
File "scripthash_address.py", line 147, in <module>
data.storage_address_scripthash()
File "scripthash_address.py", line 131, in storage_address_scripthash
self.get_block_address(block)
File "scripthash_address.py", line 102, in get_block_address
self.loop.run_until_complete(self.extract_block_addresses(block_hash))
File "/usr/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
return future.result()
File "scripthash_address.py", line 88, in extract_block_addresses
await asyncio.gather(*tasks)
File "scripthash_address.py", line 59, in async_get_tx
raw_tx = await self.ConnRpc.getrawtransaction(tx, True)
File "/usr/local/lib/python3.7/dist-packages/bitcoinrpc/bitcoin_rpc.py", line 146, in getrawtransaction
timeout=httpx.Timeout(timeout),
File "/usr/local/lib/python3.7/dist-packages/bitcoinrpc/bitcoin_rpc.py", line 63, in acall
resp = orjson.loads((await req).content)
orjson.JSONDecodeError: expected value at line 1 column 1: line 1 column 1 (char 0)
The error will stop at this txid : 103e90d89a2695f8952b513b12c705850b6b91d6ee1a9040c87d2344a3e38ff9
The title is pretty self explanatory, I'm not familiar enough with the project to create a pull request, but this is the patch I use to get this functionality:
import orjson
from bitcoinrpc import BitcoinRPC as BaseBitcoinRPC
from bitcoinrpc._exceptions import RPCError
class BitcoinRPC( BaseBitcoinRPC ):
async def abatch( self, mp_pairs, **kwargs ):
response = await self.client.post(
url = self.url,
content = orjson.dumps([
{
"jsonrpc": "2.0",
"id": self._counter(),
"method": mp.pop(0),
"params": mp,
}
for mp in mp_pairs
]
),
**kwargs,
)
response.raise_for_status()
return [
RPCError(content["error"]["code"], content["error"]["message"])
if content['error'] else
content['result']
for content in orjson.loads(response.content)
]
## BitcoinRPC Patch End```
Subj
:)
As noted in #3, httpx.AsyncClient
basic settings are fine in most cases.
However, if one needs to a more fine-grained customization due to need of more concurrent connections, proxies, etc., they have no option to do so now.
For now, I have a following solution in mind:
class ImproperlyConfigured(Exception):
pass
class BitcoinRPC:
def __init__(self, host: str, port: int, rpc_user: str, rpc_password: str, **kwargs) -> None:
self._url = self._set_url(host, port)
self._client = self._configure_client(rpc_user, rpc_password, **kwargs)
@staticmethod
def _configure_client(rpc_user: str, rpc_password: str, **options) -> httpx.AsyncClient:
auth = (rpc_user, rpc_password)
headers = {"content-type": "application/json"}
options = dict(options)
if not options:
return httpx.AsyncClient(auth=auth, headers=headers)
if "auth" in options:
raise ImproperlyConfigured("Authentication cannot be set via options!")
if "headers" in options:
_additional_headers = dict(options.pop("headers"))
headers.update(_additional_headers)
# guard against content-type overwrite
headers["content-type"] = "application/json"
return httpx.AsyncClient(auth=auth, headers=headers, **options)
All the keyword arguments passed to the initializer of BitcoinRPC
will be passed directly to the httpx.AsyncClient
, with the exception of auth
keyword. Also, headers
will need to be tamed a bit with the content-type
key since it is supposed to be application/json
.
It will then be this library's user's responsibility to conform to the interface exposed by httpx.AsyncClient
's initiliazer.
I do not recall which version of Bitcoin Core was the last released version of this library tested against.
With Bitcoin Core v24.1 being released few days ago - https://github.com/bitcoin/bitcoin/releases/tag/v24.1 - and v25.0 possible being released in few weeks, it's worth taking a look on:
#15 should help with testing this.
As for the additional RPC methods, of particular interest are those related to PSBTs, so take a look at them.
As was already noted here - #10 (comment) - the way to instantiate BitcoinRPC
is quite clunky.
It allows a user to instantiate the underlying httpx.AsyncClient
with a auth
tuple (which is btw mandatory, you cannot create a BitcoinRPC
to connect to a server not requiring user/passwd!) and then somewhat awkwardly headers and other options...
To better accomodate for more advanced configurations of the httpx.AsyncClient
(proxy support, connection pooling, timeouts - #13 (comment) ), BitcoinRPC
should be instantiated with an argument client: httpx.AsyncClient
.
However, to preserve the ease of one-shot testing and shield the users from dealing with the underlying httpx
library, an option to instantiate the BitcoinRPC
with (url, rpc_user, rpc_password
) should be preserved.
Sketched roughly:
class BitcoinRPC:
def __init__(self, url: str, client: httpx.AsyncClient):
self._url = url
self._client = client
...
@classmethod
def from_url(cls, url, rpc_user, rpc_password):
client = setup_client_with_sane_defaults(rpc_user, rpc_password)
return cls(url, client)
...
NOTE: This will result in a BREAKING change.
As noted in #6 (comment), remembering to call BitcoinRPC.aclose
to close the underlying httpx.AsyncClient
feels repetitive and one may forget it.
Implement __aenter__
and __aexit__
coroutines which will handle the closing automatically.
In this commit encode/httpx@397aad9, it is clearly stated that usage of data
kwarg in BitcoinRPC.acall
will be deprecated.
Fix to content
kwarg instead.
Probably found a bug here
Try to change line to:
if content.get("error") is not None:
raise RPCError(content["error"]["code"], content["error"]["message"])
As noted in #5 , it would be nice to have a way to test this library.
Easiest way is to test it is pointing it to a fresh regtest
node.
I have not surveyed the current state of Bitcoin regtest
images and how up-to-date they are, but even if they were OK, I believe it's still worth having a knowledge how Bitcoin node is compiled and configured.
Also, having the Docker/Containerfile
around means giving other contributors a way to audit against what version the tests are run as well as inspiration for their further experiments.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.