Skip to content

Commit

Permalink
Add documentation for Fullnode class + remove Fullnode.get_transactio…
Browse files Browse the repository at this point in the history
…ns()

because unable to make function signature ==
PrivateKey.get_transaction() in a scalable way.
  • Loading branch information
AustEcon committed Nov 23, 2019
1 parent 68a4e1a commit afd425f
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 25 deletions.
2 changes: 1 addition & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Unreleased (see `master <https://github.com/AustEcon/bitsv>`_)
--------------------------------------------------------------
- No new changes since 0.10.0 yet.

0.10.0 (2019-10-27)
0.10.0 (2019-11-23)
-------------------

- Added new Fullnode class for connecting to local bitcoin node via JSON-RPC (thanks goes to https://github.com/xloem for the initial legwork).
Expand Down
28 changes: 27 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Forked from Ofek's awesome Bit library: https://github.com/ofek/bit
Noticeboard:
------------

Latest Release - 0.10.0_ (2019-10-27)
Latest Release - 0.10.0_ (2019-11-23)

.. _0.10.0: https://github.com/AustEcon/bitsv/blob/master/HISTORY.rst

Expand Down Expand Up @@ -104,6 +104,32 @@ Here's the transaction `<https://whatsonchain.com/tx/dec895d1aa0e820984c5748984b
This sets memo.sv name (linked to this bitcoin address) to "New_Name" (as per https://memo.sv/protocol)

3. Connect to a local 'fullnode' via JSON-RPC:

.. code-block:: python
>>> from bitsv import Fullnode
>>> fullnode = FullNode(
conf_dir='/home/username/.bitcoin/regtest.conf',
rpcuser='user',
rpcpassword='password',
network='regtest')
note: wallet features of the node software will soon be deprecated. However, possible use cases may include

- Rapid transaction broadcasting ~ 200tx/sec):
- Regtesting of app in AzurePipelines or Travis CI for example.
- Learning / reproducing "too-long-mempool-chain" type errors without waiting a long time for confirmations.

The fullnode object has a complete internal list of all JSON-RPC methods added to __dict__ for code completion and methods return appropriate
error messages:

.. figure:: images/obj_dict.png

For more detailed examples of using the Fullnode class, see README_

.. _README: https://github.com/AustEcon/bitsv/blob/master/bitsv/network/services/README.rst

Features
--------

Expand Down
2 changes: 1 addition & 1 deletion bitsv/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from bitsv.format import verify_sig
from bitsv.network.rates import SUPPORTED_CURRENCIES, set_rate_cache_time
from bitsv.network.services import set_service_timeout
from bitsv.network.services import set_service_timeout, FullNode
from bitsv.wallet import Key, PrivateKey, wif_to_key

__version__ = '0.10.0'
2 changes: 1 addition & 1 deletion bitsv/network/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
currency_to_satoshi, currency_to_satoshi_cached,
satoshi_to_currency, satoshi_to_currency_cached
)
from .services import NetworkAPI
from .services import NetworkAPI, FullNode
61 changes: 61 additions & 0 deletions bitsv/network/services/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"Full node" connectivity
========================

This feature has been added by popular demand. Pull requests for refinement are welcome.
However, do bear in mind that the wallet functionality of the bitcoin node will soon be removed
so this feature may not be of much use long-term.

.. code-block:: python
>>> from bitsv import Fullnode
>>> fullnode = FullNode(
conf_dir='/home/username/.bitcoin/regtest.conf',
rpcuser='user',
rpcpassword='password',
network='regtest')
note: wallet features of the node software will soon be deprecated. However, possible use cases may include

- Rapid transaction broadcasting ~ 200tx/sec):
- Regtesting of app in AzurePipelines or Travis CI for example.

The fullnode object has a complete internal list of all JSON-RPC methods added to __dict__ for code completion:

.. figure:: images/obj_dict.png

Example RegTest functionality:

.. code-block:: python
>>> address = fullnode.getaccountaddress("my_account")
>>> fullnode.generate(200) # mine 200 blocks on regtest network
>>> fullnode.sendtoaddress(address, 10)
'd4574b01471d95e63d218885324996d7d6c8fd4180a5fd024e48b5c27b956ca6'
>>> # usual bitsv network_api functions also available:
>>> fullnode.get_balance(address)
1000000000
>>> fullnode.get_unspents(address)
[Unspent(amount=1000000000, confirmations=0, script='76a9141d03bffd36f5adab7c892255a703d032616146c488ac',
txid='d4574b01471d95e63d218885324996d7d6c8fd4180a5fd024e48b5c27b956ca6', txindex=1)]
>>> fullnode.get_transaction("d4574b01471d95e63d218885324996d7d6c8fd4180a5fd024e48b5c27b956ca6")
Transaction(txid='d4574b01471d95e63d218885324996d7d6c8fd4180a5fd024e48b5c27b956ca6',
amount_in=5000000000, amount_out=4999996160, fee=3840, inputs=1, outputs=2)
>>> fullnode.dumpprivkey(address)
"cTW5PD5ZVcRTzSL3QByiQDdCvAffpRVjEdhPe6VQPKC9pYjGFsyp"
>>> import bitsv
>>> my_regtest_key = bitsv.PrivateKey("cTW5PD5ZVcRTzSL3QByiQDdCvAffpRVjEdhPe6VQPKC9pYjGFsyp")
>>> rawtx = my_regtest_key.create_op_return_tx([b"Hello"], unspents=fullnode.get_unspents(address))
>>> rawtx
'0100000001a66c957bc2b5484e02fda58041fdc8d6d79649328588213de6951d47014b57d4010000006b48304502210'
'0ba39a87afe9417141dae2bf8835710bdf801915a017ed11a51ba43f239d4839f02203f6385f7d87504d97dd94533eb'
'26d2bc45ad82ede08cfd15d96c30ebc703aab7412102eac16d7d16ae1427802650d05e91616a76378bf64a3993a8b33'
'22bcda060f4c3ffffffff02000000000000000008006a0548656c6c6f2fc99a3b000000001976a9141d03bffd36f5ad'
'ab7c892255a703d032616146c488ac00000000'
>>> fullnode.broadcast_tx(rawtx)
"2588b60aef1cf82e78f558bf868de6001bc36f822ec18375cc260d5f233b707d"
Another use case is simply for manufacturing scenarios to learn from.
For example, try the create_op_return_tx() + broadcast_tx() repeatedly > 25x and observe the
"JSONRPCException: -26: 64: too-long-mempool-chain" error. Then observe it going away after
generating a new block... on RegTest there is no waiting 10 minutes for confirmations to
reproduce this kind of error, useful for an accelerated development cycle.
36 changes: 15 additions & 21 deletions bitsv/network/services/fullnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@

bitsv_methods = [
'get_balance',
'get_transactions',
'get_transaction',
'get_unspents',
'send_transaction',
'broadcast_tx',
'rpc_connect',
'rpc_reconnect'
]
Expand Down Expand Up @@ -101,14 +100,6 @@ def reconnect_if_needed(self, *args, **kwargs):
def get_balance(self, address):
return sum(unspent.amount for unspent in self.get_unspents(address))

@Decorators.handle_broken_pipe
def get_transactions(self, address):
acct = self.rpc.getaccount(address)
txs = self.rpc.listtransactions(acct)
txids = (tx['txid'] for tx in txs)
txids = list(txids)
return txids

@Decorators.handle_broken_pipe
def get_transaction(self, txid):
rawtx = self.rpc.getrawtransaction(txid)
Expand All @@ -118,16 +109,19 @@ def get_transaction(self, txid):
amount_in = 0
amount_out = 0
for vin in txjson['vin']:
src = self.rpc.getrawtransaction(vin['txid'], True)
src = self.rpc.decoderawtransaction(src['hex'])
src = src['vout'][vin['vout']]
addr = None
if 'addresses' in src['scriptPubKey']:
addr = src['scriptPubKey']['addresses'][0]
amount = int((src['value'] * BSV_TO_SAT_MULTIPLIER).normalize())
amount_in += amount
part = TxInput(addr, amount)
inputs += [part]
if vin.get('coinbase'):
raise NotImplementedError("Handling of coinbase transaction inputs not implemented")
else:
src = self.rpc.getrawtransaction(vin['txid'], True)
src = self.rpc.decoderawtransaction(src['hex'])
src = src['vout'][vin['vout']]
addr = None
if 'addresses' in src['scriptPubKey']:
addr = src['scriptPubKey']['addresses'][0]
amount = int((src['value'] * BSV_TO_SAT_MULTIPLIER).normalize())
amount_in += amount
part = TxInput(addr, amount)
inputs += [part]

for vout in txjson['vout']:
addr = None
Expand Down Expand Up @@ -157,7 +151,7 @@ def get_unspents(self, address):
) for tx in unspents]

@Decorators.handle_broken_pipe
def send_transaction(self, tx_hex):
def broadcast_tx(self, tx_hex):
return self.rpc.sendrawtransaction(tx_hex, True)


Expand Down
Binary file added images/obj_dict.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit afd425f

Please sign in to comment.