Skip to content

Commit

Permalink
Merge pull request #2943 from CounterpartyXCP/fixes
Browse files Browse the repository at this point in the history
No RPC retry from mempool follower
  • Loading branch information
adamkrellenstein authored Jan 15, 2025
2 parents ac60794 + 0bed836 commit eb05d6c
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 6 deletions.
8 changes: 4 additions & 4 deletions counterparty-core/counterpartycore/lib/backend/bitcoind.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ def is_api_request():
return False


def rpc(method, params):
if is_api_request():
def rpc(method, params, no_retry=False):
if is_api_request() or no_retry:
return safe_rpc(method, params)

payload = {
Expand Down Expand Up @@ -199,8 +199,8 @@ def convert_to_psbt(rawtx):


@functools.lru_cache(maxsize=10000)
def getrawtransaction(tx_hash, verbose=False):
return rpc("getrawtransaction", [tx_hash, 1 if verbose else 0])
def getrawtransaction(tx_hash, verbose=False, no_retry=False):
return rpc("getrawtransaction", [tx_hash, 1 if verbose else 0], no_retry=no_retry)


def getrawtransaction_batch(tx_hashes, verbose=False, return_dict=False):
Expand Down
5 changes: 3 additions & 2 deletions counterparty-core/counterpartycore/lib/follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ def receive_sequence(self, body):
raw_tx = self.raw_tx_cache.get(item_hash)
if raw_tx is None:
try:
raw_tx = backend.bitcoind.getrawtransaction(item_hash)
raw_tx = backend.bitcoind.getrawtransaction(item_hash, no_retry=True)
except exceptions.BitcoindRPCError:
logger.trace("Transaction not found in bitcoind: %s", item_hash)
logger.warning("Transaction not found in bitcoind: %s", item_hash)
return
# add transaction to mempool block
# logger.trace("Adding transaction to mempool block: %s", item_hash)
Expand All @@ -205,6 +205,7 @@ def receive_sequence(self, body):
logger.trace("Waiting for new transactions in the mempool or a new block...")
# transaction removed from mempool for non-block inclusion reasons
elif label == "R":
logger.debug("Removing transaction from mempool: %s", item_hash)
mempool.clean_transaction_events(self.db, item_hash)

def receive_message(self, topic, body, seq):
Expand Down
65 changes: 65 additions & 0 deletions counterparty-core/counterpartycore/test/regtest/regtestnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ def start_bitcoin_node(self):
"-acceptnonstdtxn",
"-minrelaytxfee=0",
"-blockmintxfee=0",
"-mempoolfullrbf",
f"-datadir={self.datadir}",
_bg=True,
_out=sys.stdout,
Expand All @@ -384,6 +385,7 @@ def start_bitcoin_node_2(self):
"-minrelaytxfee=0",
"-blockmintxfee=0",
"-bind=127.0.0.1:2223=onion",
"-mempoolfullrbf",
_bg=True,
_out=sys.stdout,
)
Expand Down Expand Up @@ -1134,6 +1136,69 @@ def test_fee_calculation(self):
)
assert size * 3 - 3 <= unsigned_tx["btc_fee"] <= size * 3 + 3

def test_rbf(self):
self.start_and_wait_second_node()

unsigned_tx = self.compose(
self.addresses[0],
"send",
{
"destination": self.addresses[1],
"quantity": 1,
"asset": "XCP",
"exact_fee": 1,
"verbose": True,
"validate": False,
},
)["result"]
transaction = Transaction.from_raw(unsigned_tx["rawtransaction"])
raw_hexs = []
# create 10 transactions with increasing fees
for _i in range(10):
transaction.outputs[1].amount -= 170
new_raw_transaction = transaction.to_hex()
signed_tx = json.loads(
self.bitcoin_wallet("signrawtransactionwithwallet", new_raw_transaction).strip()
)["hex"]
raw_hexs.append(signed_tx)

# check that no transaction is in the mempool
mempool_event_count_before = self.api_call("mempool/events?event_name=TRANSACTION_PARSED")[
"result_count"
]
assert mempool_event_count_before == 0

# broadcast the transactions to the two nodes
tx_hahses = []
for i, raw_hex in enumerate(raw_hexs):
tx_hash = self.bitcoin_wallet("sendrawtransaction", raw_hex, 0).strip()
tx_hahses.append(tx_hash)
print(f"Transaction {i} sent: {tx_hash}")

# check that all transactions are in the mempool
mempool_event_count_after = self.api_call("mempool/events?event_name=TRANSACTION_PARSED")[
"result_count"
]
while mempool_event_count_after == 0:
time.sleep(1)
mempool_event_count_after = self.api_call(
"mempool/events?event_name=TRANSACTION_PARSED"
)["result_count"]
time.sleep(10)

print("Mempool event count: ", mempool_event_count_after)

# only one event should be in the mempool
assert mempool_event_count_after == 1
# check that RBFed transactions are removed from the mempool
for tx_hash in tx_hahses[:-1]:
assert f"Removing transaction from mempool: {tx_hash}" in self.server_out.getvalue()
event = self.api_call("mempool/events?event_name=TRANSACTION_PARSED")["result"][0]
# check that the last transaction is the one in the mempool
assert event["tx_hash"] == tx_hahses[-1]

print("RBF test successful")


class RegtestNodeThread(threading.Thread):
def __init__(self, wsgi_server="waitress", burn_in_one_block=True):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ def run_scenarios(serve=False, wsgi_server="gunicorn"):
regtest_node_thread.node.test_electrs()
print("Testing fee calculation...")
regtest_node_thread.node.test_fee_calculation()
print("Testing RBF...")
regtest_node_thread.node.test_rbf()
except KeyboardInterrupt:
print(regtest_node_thread.node.server_out.getvalue())
pass
Expand Down
1 change: 1 addition & 0 deletions release-notes/release-notes-v10.9.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The following transaction construction parameters have been deprecated (but rema
- Handle correctly RPC call errors from the API
- Don't clean mempool on catchup
- Retry 5 times when getting invalid Json with status 200 from Bitcoin Core
- Don't retry RPC call when parsing mempool transactions


## Codebase
Expand Down

0 comments on commit eb05d6c

Please sign in to comment.