Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0f45ec5
feat: separate performance collection and distribution
vgorkavenko Oct 17, 2025
962a076
Merge remote-tracking branch 'origin/csm-next' into feat/performance-…
vgorkavenko Oct 21, 2025
453effb
fix: lock
vgorkavenko Oct 21, 2025
485fe91
fix: black
vgorkavenko Oct 21, 2025
d9e5888
Merge remote-tracking branch 'origin/csm-next' into feat/performance-…
vgorkavenko Oct 22, 2025
8d86ca7
fix: already processed epochs
vgorkavenko Oct 22, 2025
9e2c951
feat: ChainConverter
vgorkavenko Oct 23, 2025
6e95c01
refactor: types
vgorkavenko Oct 27, 2025
46decb1
feat: better logging
vgorkavenko Oct 27, 2025
39d50d2
feat: additional validation
vgorkavenko Oct 27, 2025
d689979
refactor: db
vgorkavenko Oct 28, 2025
fa5ed3c
feat: `epochs_demand`
vgorkavenko Oct 29, 2025
a5d07f7
fix: `missing_epochs_in`
vgorkavenko Nov 4, 2025
1653943
fix: logic, logging
vgorkavenko Nov 4, 2025
aa871b3
fix: csm.execute_module
vgorkavenko Nov 4, 2025
2a70199
feat: add `_post` for http_provider
vgorkavenko Nov 4, 2025
db10267
fix: SafeBorder SafeBorder inheritance issue
vgorkavenko Nov 4, 2025
0925e5f
fix: remove TODOs
vgorkavenko Nov 4, 2025
84b2e47
feat: add `PERFORMANCE_COLLECTOR_DB_CONNECTION_TIMEOUT`
vgorkavenko Nov 4, 2025
b08865a
feat: use finalized epoch if no demands
vgorkavenko Nov 7, 2025
baf8c83
fix: `validate_state`
vgorkavenko Nov 10, 2025
e72cff2
WIP: `test_csm_module.py`
vgorkavenko Nov 10, 2025
1d2fb60
WIP: `test_csm_module.py`
vgorkavenko Nov 10, 2025
e9758b0
fix: linter
vgorkavenko Nov 10, 2025
f932b99
fix: `define_epochs_to_process_range`
vgorkavenko Nov 11, 2025
13330ea
fix: `define_epochs_to_process_range`. Simple AI tests
vgorkavenko Nov 11, 2025
84ff68e
fix: remove `DEFAULT_EPOCHS_STEP_TO_COLLECT`
vgorkavenko Nov 12, 2025
6adb0ae
fix: review
vgorkavenko Nov 14, 2025
cc080b3
fix: review
vgorkavenko Nov 28, 2025
1203448
fix: remove old tests
vgorkavenko Nov 28, 2025
3efa8b9
fix: imports in test
vgorkavenko Nov 28, 2025
90c790e
fix: test_csm_module
vgorkavenko Nov 28, 2025
d95584f
fix: linter
vgorkavenko Dec 2, 2025
f676fa0
fix: some tests
vgorkavenko Dec 2, 2025
9c1c902
fix: fork tests
vgorkavenko Dec 2, 2025
53aac86
fix: review
vgorkavenko Dec 11, 2025
58ddd0e
fix: errors
vgorkavenko Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
453 changes: 428 additions & 25 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ oz-merkle-tree = { git = "https://github.com/lidofinance/oz-merkle-tree", rev =
multiformats = "^0.3.1"
protobuf="^6.31.1"
dag-cbor="^0.3.3"
fastapi = "^0.121.3"
uvicorn = "^0.38.0"
sqlmodel = "^0.0.27"
psycopg2-binary = "^2.9.11"
prometheus-fastapi-instrumentator = "^7.1.0"

[tool.poetry.group.dev.dependencies]
base58 = "^2.1.1"
Expand Down
1 change: 1 addition & 0 deletions src/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
# https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#time-parameters
SLOTS_PER_HISTORICAL_ROOT = 2**13 # 8192
# https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#sync-committee
SYNC_COMMITTEE_SIZE = 512
EPOCHS_PER_SYNC_COMMITTEE_PERIOD = 256
# https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#domain-types
DOMAIN_DEPOSIT_TYPE = bytes.fromhex("03000000") # 0x03000000
Expand Down
30 changes: 25 additions & 5 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from src.modules.csm.csm import CSOracle
from src.modules.ejector.ejector import Ejector
from src.providers.ipfs import IPFSProvider, Kubo, LidoIPFS, Pinata, Storacha
from src.modules.performance.collector.collector import PerformanceCollector
from src.types import OracleModule
from src.utils.build import get_build_info
from src.utils.exception import IncompatibleException
Expand All @@ -29,6 +30,7 @@
LidoValidatorsProvider,
TransactionUtils,
)
from src.web3py.extensions.performance import PerformanceClientModule
from src.web3py.types import Web3
from decimal import getcontext

Expand Down Expand Up @@ -75,6 +77,9 @@ def main(module_name: OracleModule):
logger.info({'msg': 'Initialize IPFS providers.'})
ipfs = IPFS(web3, ipfs_providers(), retries=variables.HTTP_REQUEST_RETRY_COUNT_IPFS)

logger.info({'msg': 'Initialize Performance Collector client.'})
performance = PerformanceClientModule(variables.PERFORMANCE_COLLECTOR_URI)

logger.info({'msg': 'Check configured providers.'})
if Version(kac.get_status().appVersion) < constants.ALLOWED_KAPI_VERSION:
raise IncompatibleException(f'Incompatible KAPI version. Required >= {constants.ALLOWED_KAPI_VERSION}.')
Expand All @@ -89,12 +94,13 @@ def main(module_name: OracleModule):
'cc': lambda: cc, # type: ignore[dict-item]
'kac': lambda: kac, # type: ignore[dict-item]
'ipfs': lambda: ipfs, # type: ignore[dict-item]
'performance': lambda: performance, # type: ignore[dict-item]
})

logger.info({'msg': 'Initialize prometheus metrics.'})
init_metrics()

instance: Accounting | Ejector | CSOracle
instance: Accounting | Ejector | CSOracle | PerformanceCollector
if module_name == OracleModule.ACCOUNTING:
logger.info({'msg': 'Initialize Accounting module.'})
instance = Accounting(web3)
Expand All @@ -104,10 +110,15 @@ def main(module_name: OracleModule):
elif module_name == OracleModule.CSM:
logger.info({'msg': 'Initialize CSM performance oracle module.'})
instance = CSOracle(web3)
elif module_name == OracleModule.PERFORMANCE_COLLECTOR:
logger.info({'msg': 'Initialize Performance Collector module.'})
# FIXME: web3 object is overkill. only CONSENSUS_CLIENT_URI needed here.
instance = PerformanceCollector(web3)
else:
raise ValueError(f'Unexpected arg: {module_name=}.')

instance.check_contract_configs()
if module_name != OracleModule.PERFORMANCE_COLLECTOR:
instance.check_contract_configs()

if variables.DAEMON:
instance.run_as_daemon()
Expand Down Expand Up @@ -174,7 +185,6 @@ def ipfs_providers() -> Iterator[IPFSProvider]:
)



if __name__ == '__main__':
module_name_arg = sys.argv[-1]
if module_name_arg not in OracleModule:
Expand All @@ -183,12 +193,22 @@ def ipfs_providers() -> Iterator[IPFSProvider]:
raise ValueError(msg)

module = OracleModule(module_name_arg)

if module is OracleModule.CHECK:
errors = variables.check_uri_required_variables()
variables.raise_from_errors(errors)

sys.exit(check())

errors = variables.check_all_required_variables(module)
if module is OracleModule.PERFORMANCE_WEB_SERVER:
from src.modules.performance.web.server import serve
errors = variables.check_perf_web_server_required_variables()
variables.raise_from_errors(errors)
logger.info({'msg': f'Starting Performance Web Server on port {variables.PERFORMANCE_WEB_SERVER_API_PORT}'})
sys.exit(serve())

if module is OracleModule.PERFORMANCE_COLLECTOR:
errors = variables.check_perf_collector_required_variables()
else:
errors = variables.check_all_required_variables(module)
variables.raise_from_errors(errors)
main(module)
8 changes: 8 additions & 0 deletions src/metrics/prometheus/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ class Status(Enum):
buckets=requests_buckets,
)

PERFORMANCE_REQUESTS_DURATION = Histogram(
'performance_requests_duration',
'Duration of requests to Performance Collector API',
['endpoint', 'code', 'domain'],
namespace=PROMETHEUS_PREFIX,
buckets=requests_buckets,
)

KEYS_API_REQUESTS_DURATION = Histogram(
'keys_api_requests_duration',
'Duration of requests to Keys API',
Expand Down
Loading
Loading