Skip to content

Commit

Permalink
Merge pull request #425 from 1200wd/providers-and-testnet4
Browse files Browse the repository at this point in the history
Providers and testnet4
  • Loading branch information
mccwdev authored Dec 9, 2024
2 parents 9859db1 + e152697 commit baf5486
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 23 deletions.
33 changes: 33 additions & 0 deletions bitcoinlib/data/networks.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,39 @@
"fee_max": 2000000,
"priority": 8
},
"testnet4":
{
"description": "Bitcoin Test Network 4",
"currency_name": "test-bitcoin",
"currency_name_plural": "test-bitcoins",
"currency_symbol": "TBTC",
"currency_code": "tBTC",
"prefix_address": "6F",
"prefix_address_p2sh": "C4",
"prefix_bech32": "tb",
"prefix_wif": "EF",
"prefixes_wif": [
["043587CF", "tpub", "public", false, "legacy", "p2pkh"],
["043587CF", "tpub", "public", true, "legacy", "p2sh"],
["04358394", "tprv", "private", false, "legacy", "p2pkh"],
["04358394", "tprv", "private", true, "legacy", "p2sh"],
["044A5262", "upub", "public", false, "p2sh-segwit", "p2sh_p2wpkh"],
["024289EF", "Upub", "public", true, "p2sh-segwit", "p2sh_p2wsh"],
["044A4E28", "uprv", "private", false, "p2sh-segwit", "p2sh_p2wpkh"],
["024285B5", "Uprv", "private", true, "p2sh-segwit", "p2sh_p2wsh"],
["045F1CF6", "vpub", "public", false, "segwit", "p2wpkh"],
["02575483", "Vpub", "public", true, "segwit", "p2wsh"],
["045F18BC", "vprv", "private", false, "segwit", "p2wpkh"],
["02575048", "Vprv", "private", true, "segwit", "p2wsh"]
],
"bip44_cointype": 1,
"denominator": 0.00000001,
"dust_amount": 1000,
"fee_default": 10000,
"fee_min": 1000,
"fee_max": 2000000,
"priority": 8
},
"regtest":
{
"description": "Bitcoin regtest",
Expand Down
15 changes: 13 additions & 2 deletions bitcoinlib/data/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,20 @@
"network_overrides": null,
"timeout": 0
},
"mempool.litecoin": {
"mempool.testnet4": {
"provider": "mempool",
"network": "litecoin_testnet",
"network": "testnet4",
"client_class": "MempoolClient",
"provider_coin_id": "",
"url": "https://mempool.space/testnet4/api/",
"api_key": "",
"priority": 10,
"denominator": 1,
"network_overrides": null
},
"mempool.litecoin": {
"provider": "mempool",
"network": "litecoin",
"client_class": "MempoolClient",
"provider_coin_id": "",
"url": "https://litecoinspace.org/api/",
Expand Down
20 changes: 7 additions & 13 deletions bitcoinlib/services/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,13 @@ def __init__(self, network=DEFAULT_NETWORK, min_providers=1, max_providers=1, pr
raise ServiceError("Provider '%s' not found in provider definitions" % p)

self.providers = {}
if provider_name:
if provider_name not in self.providers_defined:
raise ServiceError("Provider with name '%s' not found in provider definitions" % provider_name)
if self.providers_defined[provider_name]['network'] != self.network:
raise ServiceError("Network from provider '%s' is different than Service network" % provider_name)
self.providers.update({provider_name: self.providers_defined[provider_name]})
else:
for p in self.providers_defined:
if (self.providers_defined[p]['network'] == network or self.providers_defined[p]['network'] == '') and \
(not providers or self.providers_defined[p]['provider'] in providers):
self.providers.update({p: self.providers_defined[p]})
exclude_providers_keys = {pi: self.providers[pi]['provider'] for
pi in self.providers if self.providers[pi]['provider'] in exclude_providers}.keys()
for p in self.providers_defined:
if ((self.providers_defined[p]['network'] == network or self.providers_defined[p]['network'] == '') and \
(not providers or self.providers_defined[p]['provider'] in providers)
and self.providers_defined[p]['priority']):
self.providers.update({p: self.providers_defined[p]})
exclude_providers_keys = {pi: self.providers[pi]['provider'] for pi in self.providers if self.providers[pi]['provider'] in exclude_providers}.keys()

for provider_key in exclude_providers_keys:
del(self.providers[provider_key])

Expand Down
8 changes: 4 additions & 4 deletions bitcoinlib/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,12 +696,12 @@ def __init__(self, value, address='', public_hash=b'', public_key=b'', lock_scri
raise TransactionError("Could not determine script type of address %s" % self._address)
self.encoding = address_dict['encoding']
network_guesses = address_dict['networks']
if address_dict['network'] and self.network.name != address_dict['network']:
raise TransactionError("Address %s is from %s network and transaction from %s network" %
(self._address, address_dict['network'], self.network.name))
elif self.network.name not in network_guesses:
if self.network.name not in network_guesses:
raise TransactionError("Network for output address %s is different from transaction network. %s not "
"in %s" % (self._address, self.network.name, network_guesses))
# if address_dict['network'] and self.network.name != address_dict['network']:
# raise TransactionError("Address %s is from %s network and transaction from %s network" %
# (self._address, address_dict['network'], self.network.name))
self.public_hash = address_dict['public_key_hash_bytes']
self.witness_type = address_dict['witness_type']
if not self.encoding:
Expand Down
2 changes: 1 addition & 1 deletion docs/_static/manuals.security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Frequently Asked Questions
Ten tips for more privacy and security when using Bitcoin and Bitcoinlib:

1. Run your own `Bitcoin core <https://bitcoinlib.readthedocs.io/en/latest/source/_static/manuals.setup-bitcoind-connection.html>`_,
`Bcoin node <manuals.setup-bcoin.html>`_ node or `Blockbook server <manuals.setup-blockbook.html>`_, so you are not depending on external Blockchain API service providers anymore.
`Bcoin node <manuals.setup-bcoin.html>`_ or `Blockbook server <manuals.setup-blockbook.html>`_, so you are not depending on external Blockchain API service providers anymore.
This not only increases your privacy, but also makes your application much faster and more reliable. And as extra bonus
you support the Bitcoin network.
2. Use multi-signature wallets. So you are able to store your private keys in separate (offline) locations.
Expand Down
2 changes: 1 addition & 1 deletion tests/test_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_networks_prefix_wif_network_by_value(self):
self.assertEqual(network_by_value('prefix_wif', '10'), [])

def test_networks_prefix_bech32_network_by_value(self):
self.assertEqual(network_by_value('prefix_bech32', 'tb'), ['testnet'])
self.assertEqual(network_by_value('prefix_bech32', 'tb'), ['testnet', 'testnet4'])

def test_networks_prefix_bech32_network_by_value_sorted(self):
self.assertEqual(network_by_value('prefix_bech32', 'ltc'), ['litecoin', 'litecoin_legacy'])
Expand Down
20 changes: 18 additions & 2 deletions tests/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ def test_service_transaction_get_raw_testnet(self):
'76a914f0d34949650af161e7cb3f0325a1a8833075165088acb7740f00'
self.assertEqual(raw_tx, ServiceTest(network='testnet').getrawtransaction(tx_id))

def test_service_transaction_get_raw_testnet4(self):
tx_id = '619c9db8597dc8aaaa37569e25930efa04c9aef7b604b1b8a26bd4f086b2785c'
raw_tx = ('010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff095100062f4'
'077697a2fffffffff0200f2052a010000001976a9140a59837ccd4df25adc31cdad39be6a8d97557ed688ac0000000000'
'000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000'
'000000000000000000000000000000000000000000000000000000000000000')
self.assertEqual(raw_tx, ServiceTest(network='testnet4').getrawtransaction(tx_id))

def test_service_transaction_get_raw_bitcoin(self):
tx_id = 'b7feea5e7c79d4f6f343b5ca28fa2a1fcacfe9a2b7f44f3d2fd8d6c2d82c4078'
raw_tx = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5d0342fe06244d69' \
Expand Down Expand Up @@ -468,6 +476,14 @@ def test_service_gettransactions_litecoin(self):
r_inputs[2]['prev_txid'] = 'fa422d9fbac6a344af5656325acde172cd5714ebddd2f35068d3f265095add52'
self.assertEqual(r_inputs[0], input0, msg="Unexpected transaction input values for %s provider" % provider)

def test_service_gettransactions_testnet4(self):
address = 'tb1qmtrlx4srl87dtcj73ue5gv39907e8n3qu8rs79'
srv = ServiceTest(network='testnet4')
txs = srv.gettransactions(address)
txids = [tx.txid for tx in txs]
self.assertIn(txs[0].txid, txids)
self.assertIn(txs[1].txid, txids)

def test_service_gettransaction_coinbase(self):
expected_dict = {
'block_hash': '0000000000000000002d966c99d68245b20468dc9c2a7a776a836add03362199',
Expand Down Expand Up @@ -610,7 +626,7 @@ def test_service_network_litecoin_legacy(self):
self.assertIn(txid, [utxo['txid'] for utxo in utxos])

def test_service_blockcount(self):
for nw in ['bitcoin', 'litecoin', 'testnet']:
for nw in ['bitcoin', 'litecoin', 'testnet']: # ToDo: add testnet4 when more providers are available
srv = ServiceTest(min_providers=3, cache_uri='', network=nw, exclude_providers=['bitgo', 'bitaps'])
srv.blockcount()
n_blocks = None
Expand Down Expand Up @@ -802,7 +818,7 @@ def test_service_transaction_unconfirmed(self):
self.assertIsNone(t.date)
self.assertIsNone(t.block_height)

def test_service_exlude_providers(self):
def test_service_exclude_providers(self):
srv = ServiceTest(network='testnet', cache_uri='')
providers = [srv.providers[pi]['provider'] for pi in srv.providers]
try:
Expand Down
5 changes: 5 additions & 0 deletions tests/test_wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ def test_wallet_create_with_passphrase(self):
key0 = wlt.get_key()
self.assertEqual(key0.address, "mqDeXXaFnWKNWhLmAae7zHhZDW4PMsLHPp")

wlt4 = Wallet.create("wallet-passphrase-testnet4", keys=passphrase, network='testnet4', witness_type='legacy',
db_uri=self.database_uri)
key0 = wlt4.get_key()
self.assertEqual(key0.address, "mqDeXXaFnWKNWhLmAae7zHhZDW4PMsLHPp")

def test_wallet_create_with_passphrase_litecoin(self):
passphrase = "always reward element perfect chunk father margin slab pond suffer episode deposit"
wlt = Wallet.create("wallet-passphrase-litecoin", keys=passphrase, network='litecoin',
Expand Down

0 comments on commit baf5486

Please sign in to comment.