Skip to content

Commit

Permalink
Check addresses and hashes format
Browse files Browse the repository at this point in the history
  • Loading branch information
Ouziel committed Jan 17, 2025
1 parent dbf9d72 commit 2a142d0
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 19 deletions.
14 changes: 11 additions & 3 deletions counterparty-core/counterpartycore/lib/api/apiserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
from counterpartycore.lib.ledger.currentstate import CurrentState
from counterpartycore.lib.monitors import sentry
from counterpartycore.lib.parser import check
from counterpartycore.lib.utils import database
from counterpartycore.lib.utils import address, database, helpers
from counterpartycore.lib.utils.database import LedgerDBConnectionPool, StateDBConnectionPool
from counterpartycore.lib.utils.helpers import to_json

multiprocessing.set_start_method("spawn", force=True)

Expand Down Expand Up @@ -170,7 +169,7 @@ def return_result(
api_result["result_count"] = result_count
if error is not None:
api_result["error"] = error
response = flask.make_response(to_json(api_result), http_code)
response = flask.make_response(helpers.to_json(api_result), http_code)
response.headers["X-COUNTERPARTY-HEIGHT"] = CurrentState().current_block_index()
response.headers["X-COUNTERPARTY-READY"] = is_server_ready()
response.headers["X-COUNTERPARTY-VERSION"] = config.VERSION_STRING
Expand Down Expand Up @@ -235,6 +234,15 @@ def prepare_args(route, **kwargs):
else:
function_args[arg_name] = str_arg

for arg_name, str_arg in function_args.items():
if str_arg is not None:
if arg_name.startswith("address"):
addresses = str_arg.split(",")
if not all([address.is_valid_address(addr) for addr in addresses]):

Check warning

Code scanning / pylint

Use a generator instead 'all(address.is_valid_address(addr) for addr in addresses)'. Warning

Use a generator instead 'all(address.is_valid_address(addr) for addr in addresses)'.
raise ValueError(f"Invalid address: {str_arg}")
elif arg_name.endswith("_hash") and not helpers.is_valid_tx_hash(str_arg):
raise ValueError(f"Invalid transaction hash: {str_arg}")

return function_args


Expand Down
12 changes: 2 additions & 10 deletions counterparty-core/counterpartycore/lib/api/composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from arc4 import ARC4
from bitcoinutils.keys import P2pkhAddress, P2shAddress, P2wpkhAddress, PublicKey
from bitcoinutils.script import Script, b_to_h
from bitcoinutils.setup import setup
from bitcoinutils.transactions import Transaction, TxInput, TxOutput, TxWitnessInput

from counterpartycore.lib import (
Expand Down Expand Up @@ -76,15 +75,8 @@ def is_address_script(address, script_pub_key):
################


def setup_bitcoinutils():
if config.NETWORK_NAME == "testnet4":
setup("testnet")
else:
setup(config.NETWORK_NAME)


def address_to_script_pub_key(address, unspent_list, construct_params):
setup_bitcoinutils()
helpers.setup_bitcoinutils()
if multisig.is_multisig(address):
signatures_required, addresses, signatures_possible = multisig.extract_array(address)
pubkeys = [search_pubkey(addr, unspent_list, construct_params) for addr in addresses]
Expand Down Expand Up @@ -1053,7 +1045,7 @@ def prepare_construct_params(construct_params):


def compose_transaction(db, name, params, construct_parameters):
setup_bitcoinutils()
helpers.setup_bitcoinutils()

construct_params, warnings = prepare_construct_params(construct_parameters)

Expand Down
6 changes: 1 addition & 5 deletions counterparty-core/counterpartycore/lib/cli/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import appdirs
import bitcoin as bitcoinlib
from bitcoinutils.setup import setup
from termcolor import colored, cprint

from counterpartycore.lib import (
Expand Down Expand Up @@ -222,10 +221,7 @@ def initialise_config(
config.NETWORK_NAME = "regtest"
network = f".{config.NETWORK_NAME}" if config.NETWORK_NAME != "mainnet" else ""

if config.NETWORK_NAME.startswith("testnet"):
setup("testnet")
else:
setup(config.NETWORK_NAME)
helpers.setup_bitcoinutils()

# Database
if database_file:
Expand Down
26 changes: 25 additions & 1 deletion counterparty-core/counterpartycore/lib/utils/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import bitcoin
from bitcoin.bech32 import CBech32Data
from bitcoinutils.keys import P2pkhAddress, P2shAddress, P2wpkhAddress
from counterpartycore.lib import config, exceptions
from counterpartycore.lib.parser import protocol
from counterpartycore.lib.utils import base58, multisig
from counterpartycore.lib.utils import base58, helpers, multisig

logger = logging.getLogger(config.LOGGER_NAME)

Expand Down Expand Up @@ -125,3 +126,26 @@ def unpack(short_address_bytes):
else:
check = bitcoin.core.Hash(short_address_bytes)[0:4]
return bitcoin.base58.encode(short_address_bytes + check)


def is_valid_address(address, network=None):
print("Checking address validity", address, config.NETWORK_NAME)
helpers.setup_bitcoinutils(network)
if multisig.is_multisig(address):
return True
try:
P2wpkhAddress(address).to_script_pub_key()
return True
except ValueError:
pass
try:
P2pkhAddress(address).to_script_pub_key()
return True
except ValueError:
pass
try:
P2shAddress(address).to_script_pub_key()
return True
except ValueError:
pass
return False
20 changes: 20 additions & 0 deletions counterparty-core/counterpartycore/lib/utils/helpers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import decimal
import itertools
import json
import string
from operator import itemgetter
from urllib.parse import urlparse

from bitcoinutils.setup import setup
from counterpartycore.lib import config

D = decimal.Decimal


Expand Down Expand Up @@ -90,3 +94,19 @@ def divide(value1, value2):
if value2 == 0 or value1 == 0:
return D(0)
return D(value1) / D(value2)


def setup_bitcoinutils(network=None):
if network is not None:
setup(network)
return
if config.NETWORK_NAME == "testnet4":
setup("testnet")
else:
setup(config.NETWORK_NAME)


def is_valid_tx_hash(hash):

Check warning

Code scanning / pylint

Redefining built-in 'hash'. Warning

Redefining built-in 'hash'.
if all(c in string.hexdigits for c in hash) and len(hash) == 64:
return True
return False
11 changes: 11 additions & 0 deletions counterparty-core/counterpartycore/test/api_v2_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,3 +551,14 @@ def test_asset_dispensers():
"close_block_index": None,
}
]


@pytest.mark.usefixtures("apiserver_v2")
def test_invalid_hash():
tx_hash = "65e649d58b95602b04172375dbd86783b7379e455a2bc801338d9299d10425a"
url = f"{API_ROOT}/v2/orders/{tx_hash}/matches"
result = requests.get(url).json() # noqa: S113
assert (
result["error"]
== "Invalid transaction hash: 65e649d58b95602b04172375dbd86783b7379e455a2bc801338d9299d10425a"
)
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,97 @@
"out": "2MtAV7xpAzU69E8GxRF2Vd2xt79kDnif6F5",
},
],
"is_valid_address": [
{
"in": ("18H63wjcZqaBwifMjopS9jSZejivq7Lgq4", "mainnet"),
"out": True,
},
{
"in": ("1MWqsvFhABHULk24U81tV9aTaWJj2z5m7Z", "mainnet"),
"out": True,
},
{
"in": ("1EDrzMiWkB1yW3YKbceDX25kuxpicUSPqn", "mainnet"),
"out": True,
},
{
"in": (
"2_1HFhTq3rzAaodxjU4dJ8ctxwUHZ6gHMDS7_1workshyTLmwVf1PvnDMLPUi3MZZWXzH8_2",
"mainnet",
),
"out": True,
},
{
"in": (
"2_17VLRV4y7g15KNhCepYvgigHHvREzbEmRn_1FkQMTyqzD2BK5PsmWX13AeJAHz5NEw7gq_1HhfcdD1hRaim17m5qLEwGgHY7PBTb1Dof_3",
"mainnet",
),
"out": True,
},
{
"in": ("bc1q707uusxpdv60jz8973z8rudj6y4ae73vwerhx8", "mainnet"),
"out": True,
},
{
"in": ("bc1q7rdrecerefrzenl6eq94fqxzhjj02shf0hm490", "mainnet"),
"out": True,
},
{
"in": ("bc1qx8g8dca9clxs4z6y4fdtmw6x2qcyffymtp4eed", "mainnet"),
"out": True,
},
{
"in": ("3Hcy4ypuvSnbySZAxSj2jiCfFCRzqvCXwC", "mainnet"),
"out": True,
},
{
"in": ("3FA93F7DgJEBkAvq1d9WFrrrFGGppkYHYd", "mainnet"),
"out": True,
},
{
"in": ("35cNLGf1SRG7R1Hkuh4V5dP4qfHmsyqUTk", "mainnet"),
"out": True,
},
{
"in": ("tb1q5ljtmkhtkhgrxdxaqvvut2trtrrsjgx8fsxfl5", "testnet"),
"out": True,
},
{
"in": ("tb1qv9g0n4qltu9hss0khegwmg94lxn6sy6haqhj7a", "testnet"),
"out": True,
},
{
"in": ("mtuTqahviyGpNL3qT5zV88Gm1YAbD2zZg8", "testnet"),
"out": True,
},
{
"in": ("mtuTqahviyGpNL3qT5zV88Gm1YAbD2zZg", "testnet"),
"out": False,
},
{
"in": ("tc1qv9g0n4qltu9hss0khegwmg94lxn6sy6haqhj7a", "testnet"),
"out": False,
},
{
"in": ("35cNLGf1SRG7R1Hkuh4V5dP4qfHmsyqUTk0", "mainnet"),
"out": False,
},
{
"in": ("toto", "mainnet"),
"out": False,
},
{
"in": ("toto", "testnet"),
"out": False,
},
{
"in": ("mn6q3dS2EnDUx3bmyWc6D4szJNVGtaR7zc", "testnet"),
"out": True,
},
{
"in": ("mtQheFaSfWELRB2MyMBaiWjdDm6ux9Ezns", "testnet"),
"out": True,
},
],
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,28 @@
}
],
},
"utils.helpers": {
"is_valid_tx_hash": [
{
"in": ("foobar",),
"out": False,
},
{
"in": ("3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42dda1",),
"out": True,
},
{
"in": ("3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42dda11",),
"out": False,
},
{
"in": ("3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42dda",),
"out": False,
},
{
"in": ("3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42ddaG",),
"out": False,
},
],
},
}
1 change: 1 addition & 0 deletions counterparty-core/counterpartycore/test/util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@ def exec_tested_method(tx_name, method, tested_method, inputs, server_db):
"get_der_signature_sighash_flag",
"get_schnorr_signature_sighash_flag",
"check_signatures_sighash_flag",
"is_valid_tx_hash",
]
or tx_name
in [
Expand Down

0 comments on commit 2a142d0

Please sign in to comment.