Skip to content

Commit

Permalink
Merge pull request #2531 from CounterpartyXCP/develop
Browse files Browse the repository at this point in the history
v10.5.0
  • Loading branch information
ouziel-slama authored Oct 22, 2024
2 parents 8e06816 + 21b64fc commit 22f14da
Show file tree
Hide file tree
Showing 24 changed files with 4,148 additions and 3,671 deletions.
3,927 changes: 2,073 additions & 1,854 deletions apiary.apib

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions counterparty-core/counterpartycore/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def float_range_checker(arg):
("--no-confirm",),
{"action": "store_true", "default": False, "help": "don't ask for confirmation"},
],
[("--database-file",), {"default": None, "help": "the path to the SQLite3 database file"}],
[("--data-dir",), {"default": None, "help": "the path to the data directory"}],
[
("--log-file",),
{"nargs": "?", "const": None, "default": False, "help": "log to the specified file"},
Expand Down Expand Up @@ -429,7 +429,7 @@ def main():
parser_server.add_argument("--config-file", help="the path to the configuration file")
parser_server.add_argument(
"--catch-up",
choices=["normal", "bootstrap"],
choices=["normal", "bootstrap", "bootstrap-always"],
default="normal",
help="Catch up mode (default: normal)",
)
Expand Down
33 changes: 7 additions & 26 deletions counterparty-core/counterpartycore/lib/api/api_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ def run_api_server(args, interrupted_value, server_ready_value):
app = init_flask_app()

wsgi_server = None
parent_checker = None

try:
# Init the HTTP Server.
Expand All @@ -417,33 +416,15 @@ def run_api_server(args, interrupted_value, server_ready_value):
wsgi_server.run()
except KeyboardInterrupt:
logger.trace("Keyboard Interrupt!")
except Exception as e:
capture_exception(e)
logger.error("Error in API Server: %s", e)
finally:
logger.trace("Shutting down API Server...")
try:
watcher.stop()
watcher.join()
except Exception as e:
logger.error("Error stopping API Watcher: %s", e)

if wsgi_server is not None:
try:
wsgi_server.stop()
except Exception as e:
logger.error("Error stopping WSGI Server: %s", e)
watcher.stop()
watcher.join()

if parent_checker is not None:
try:
parent_checker.join()
except Exception as e:
logger.error("Error joining ParentProcessChecker: %s", e)

try:
APIDBConnectionPool().close()
except Exception as e:
logger.error("Error closing DB connection pool: %s", e)
wsgi_server.stop()
parent_checker.join()
APIDBConnectionPool().close()


# This thread is used for the following two reasons:
Expand Down Expand Up @@ -492,8 +473,8 @@ def stop(self):
waiting_start_time = time.time()
while self.process.is_alive():
time.sleep(1)
logger.trace("Waiting 10 seconds for API Server to stop...")
if time.time() - waiting_start_time > 10:
logger.trace("Waiting for API Server to stop...")
if time.time() - waiting_start_time > 2:
logger.error("API Server did not stop in time. Terminating...")
self.process.kill()
break
Expand Down
8 changes: 5 additions & 3 deletions counterparty-core/counterpartycore/lib/api/api_watcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
"DISPENSE": ["source", "destination"],
"BROADCAST": ["source"],
"BURN": ["source"],
"NEW_FAIRMINT": ["source"],
"NEW_FAIRMINTER": ["source"],
}

SKIP_EVENTS = ["NEW_TRANSACTION_OUTPUT"]
Expand Down Expand Up @@ -625,9 +627,9 @@ def update_fairminters(api_db, event):
cursor = api_db.cursor()
sql = """
UPDATE fairminters SET
earned_quantity = earned_quantity + :earn_quantity,
commission = commission + :commission,
paid_quantity = paid_quantity + :paid_quantity
earned_quantity = COALESCE(earned_quantity, 0) + :earn_quantity,
commission = COALESCE(commission, 0) + :commission,
paid_quantity = COALESCE(paid_quantity, 0) + :paid_quantity
WHERE tx_hash = :fairminter_tx_hash
"""
cursor.execute(sql, event_bindings)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- depends: 0012.add_index_on_event_index

UPDATE fairminters SET
earned_quantity = (
SELECT SUM(earn_quantity)
FROM fairmints
WHERE fairmints.fairminter_tx_hash = fairminters.tx_hash
),
paid_quantity = (
SELECT SUM(paid_quantity)
FROM fairmints
WHERE fairmints.fairminter_tx_hash = fairminters.tx_hash
),
commission = (
SELECT SUM(commission)
FROM fairmints
WHERE fairmints.fairminter_tx_hash = fairminters.tx_hash
);
16 changes: 15 additions & 1 deletion counterparty-core/counterpartycore/lib/api/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,11 @@ def inject_issuances_and_block_times(db, result_list):
):
block_indexes.append(result_item["params"][field_name])

if "asset_longname" in result_item and "description" in result_item:
if (
"asset_longname" in result_item
and "description" in result_item
and "max_mint_per_tx" not in result_item
):
continue
item = result_item
if "params" in item:
Expand Down Expand Up @@ -451,6 +455,16 @@ def inject_normalized_quantities(result_list):
"fee_required_remaining": {"asset_field": None, "divisible": True},
"fee_provided_remaining": {"asset_field": None, "divisible": True},
"fee_fraction_int": {"asset_field": None, "divisible": True},
"price": {"asset_field": "asset_info", "divisible": None},
"hard_cap": {"asset_field": "asset_info", "divisible": None},
"soft_cap": {"asset_field": "asset_info", "divisible": None},
"quantity_by_price": {"asset_field": "asset_info", "divisible": None},
"max_mint_per_tx": {"asset_field": "asset_info", "divisible": None},
"premint_quantity": {"asset_field": "asset_info", "divisible": None},
"earned_quantity": {"asset_field": "asset_info", "divisible": None},
"earn_quantity": {"asset_field": "asset_info", "divisible": None},
"commission": {"asset_field": "asset_info", "divisible": None},
"paid_quantity": {"asset_field": "asset_info", "divisible": None},
}

enriched_result_list = []
Expand Down
87 changes: 24 additions & 63 deletions counterparty-core/counterpartycore/lib/api/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import os
import signal
import sys
import tempfile
import time
from threading import Timer

import gunicorn.app.base
import waitress
import waitress.server
from counterpartycore.lib import backend, config, ledger, util
from counterpartycore.lib import backend, config, ledger, log, util
from counterpartycore.lib.api.util import get_backend_height
from counterpartycore.lib.database import get_db_connection
from flask import request
Expand Down Expand Up @@ -97,52 +96,17 @@ def start_refresh_backend_height(timer_db, args):
BACKEND_HEIGHT = 0


class DummyLogger:
def __init__(self) -> None:
pass

def info(self, *args, **kwargs):
pass

def debug(self, *args, **kwargs):
pass

def exception(self, *args, **kwargs):
pass

def warning(self, *args, **kwargs):
pass

def error(self, *args, **kwargs):
pass

def critical(self, *args, **kwargs):
pass

def close_on_exec(self):
pass

def reopen_files(self):
pass


class GunicornArbiter(Arbiter):
def __init__(self, app):
super().__init__(app)
self.workers_pid_file = tempfile.NamedTemporaryFile()
self.log = DummyLogger()

def add_worker_to_pid_file(self, pid):
self.workers_pid_file.write(f"{pid}\n".encode())
self.workers_pid_file.flush()

def get_workers_pid(self):
self.workers_pid_file.seek(0)
return [
int(value)
for value in self.workers_pid_file.read().decode().strip().split("\n")
if value
]
super().__init__(app) # Pass 'app' instead of 'app.cfg'
self.app = app
self.timeout = 30
self.graceful_timeout = 30
self.max_requests = 1000
self.max_requests_jitter = 50

def handle_winch(self):
pass

def spawn_worker(self):
self.worker_age += 1
Expand All @@ -162,23 +126,20 @@ def spawn_worker(self):
self.WORKERS[pid] = worker
return pid

# Do not inherit the temporary files of other workers
for sibling in self.WORKERS.values():
sibling.tmp.close()

# Process Child
# Child process
global logger # noqa F811
worker.pid = os.getpid()
logger = log.re_set_up(f".gunicorn.{worker.pid}")
try:
gunicorn_util._setproctitle("worker [%s]" % self.proc_name)
logger.debug("Booting Gunicorn worker with pid: %s", worker.pid)
self.add_worker_to_pid_file(worker.pid)
gunicorn_util._setproctitle(f"worker [{self.proc_name}]")
logger.trace("Booting Gunicorn worker with pid: %s", worker.pid)
self.cfg.post_fork(self, worker)
worker.init_process()
sys.exit(0)
except SystemExit:
raise
except AppImportError:
self.log.debug("Exception while loading the application", exc_info=True)
self.log.warning("Exception while loading the application", exc_info=True)
sys.stderr.flush()
sys.exit(self.APP_LOAD_ERROR)
except Exception:
Expand All @@ -187,15 +148,15 @@ def spawn_worker(self):
sys.exit(self.WORKER_BOOT_ERROR)
sys.exit(-1)
finally:
self.log.info("Worker exiting (pid: %s)", worker.pid)
logger.info("Worker exiting (pid: %s)", worker.pid)
try:
worker.tmp.close()
self.cfg.worker_exit(self, worker)
except Exception:
self.log.warning("Exception during worker exit")
logger.warning("Exception during worker exit")

def kill_all_workers(self):
for pid in self.get_workers_pid():
for pid in list(self.WORKERS.keys()):
try:
os.kill(pid, signal.SIGKILL)
except ProcessLookupError:
Expand All @@ -210,8 +171,10 @@ def __init__(self, app, args=None):
"worker_class": "gthread",
"daemon": True,
"threads": config.GUNICORN_THREADS_PER_WORKER,
"loglevel": "debug",
# "access-logfile": "-",
"loglevel": "trace",
"access-logfile": "-",
"errorlog": "-",
"capture_output": True,
}
self.application = app
self.args = args
Expand Down Expand Up @@ -243,12 +206,10 @@ def run(self):
sys.exit(1)

def stop(self):
logger.warning("Stopping Gunicorn")
if BACKEND_HEIGHT_TIMER:
BACKEND_HEIGHT_TIMER.cancel()
# if self.timer_db:
# self.timer_db.close()
if self.arbiter:
# self.arbiter.stop(graceful=False)
self.arbiter.kill_all_workers()


Expand Down
6 changes: 6 additions & 0 deletions counterparty-core/counterpartycore/lib/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,10 @@
"ledger_hash": "1c5f82ee5009fbc3d94bb8ff88d644aa0b2ec42f21409b315f555f1006bca6fc",
"txlist_hash": "1f5db508a80205eaaa6d915402c7833a0851bb369bea54a600e2fdda7e1d7ff5",
},
866750: {
"ledger_hash": "1c5164faca831bb726666eb6c63e5d8fd4070b382706c30f839ed407526c7de4",
"txlist_hash": "a536d8a1b2b3cf6164b9a2cd70edd2efaea615340e11291eebb6201c762aaaf5",
},
}

CONSENSUS_HASH_VERSION_TESTNET = 7
Expand Down Expand Up @@ -1010,6 +1014,8 @@ def __init__(self, message, required_action, from_block_index=None):


def check_need_reparse(version_minor, message):
if config.FORCE:
return
need_reparse_from = (
config.NEED_REPARSE_IF_MINOR_IS_LESS_THAN_TESTNET
if config.TESTNET
Expand Down
4 changes: 3 additions & 1 deletion counterparty-core/counterpartycore/lib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


# Semantic Version
__version__ = "10.5.0-rc.1" # for hatch
__version__ = "10.5.0" # for hatch
VERSION_STRING = __version__
version = VERSION_STRING.split("-")[0].split(".")
VERSION_MAJOR = int(version[0])
Expand Down Expand Up @@ -184,3 +184,5 @@
INFLUX_DB_BUCKET = "node-telemetry"

LOG_IN_CONSOLE = False

DEFAULT_DB_CONNECTION_POOL_SIZE = 10
13 changes: 13 additions & 0 deletions counterparty-core/counterpartycore/lib/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,19 @@ def handle_exception(exc_type, exc_value, exc_traceback):

sys.excepthook = handle_exception

return logger


def re_set_up(suffix=""):
return set_up(
verbose=config.VERBOSE,
quiet=config.QUIET,
log_file=config.LOG + suffix,
json_logs=config.JSON_LOGS,
max_log_file_size=config.MAX_LOG_FILE_SIZE,
max_log_file_rotations=config.MAX_LOG_FILE_ROTATIONS,
)


def isodt(epoch_time):
try:
Expand Down
Loading

0 comments on commit 22f14da

Please sign in to comment.