Skip to content

Commit 8b85724

Browse files
committed
feat(cli): Add run_from_logs cli command to replay blocks and transactions from a log file
1 parent d62211e commit 8b85724

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

hathor/cli/main.py

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def __init__(self) -> None:
5050
replay_logs,
5151
reset_event_queue,
5252
reset_feature_settings,
53+
run_from_logs,
5354
run_node,
5455
shell,
5556
stratum_mining,
@@ -91,6 +92,7 @@ def __init__(self) -> None:
9192
self.add_cmd('dev', 'x-export', db_export, 'EXPERIMENTAL: Export database to a simple format.')
9293
self.add_cmd('dev', 'x-import', db_import, 'EXPERIMENTAL: Import database from exported format.')
9394
self.add_cmd('dev', 'replay-logs', replay_logs, 'EXPERIMENTAL: re-play json logs as console printted')
95+
self.add_cmd('dev', 'run_from_logs', run_from_logs, 'replay the same blocks and transactions in the log')
9496

9597
def add_cmd(self, group: str, cmd: str, module: ModuleType, short_description: Optional[str] = None) -> None:
9698
self.command_list[cmd] = module

hathor/cli/run_from_logs.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright 2024 Hathor Labs
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import re
16+
import sys
17+
from argparse import ArgumentParser, FileType
18+
19+
from hathor.cli.run_node import RunNode
20+
21+
22+
class RunFromLogs(RunNode):
23+
def start_manager(self) -> None:
24+
pass
25+
26+
def register_signal_handlers(self) -> None:
27+
pass
28+
29+
@classmethod
30+
def create_parser(cls) -> ArgumentParser:
31+
parser = super().create_parser()
32+
parser.add_argument('--log-input', type=FileType('r', encoding='UTF-8'), default=sys.stdin, nargs='?',
33+
help='Where to read logs from, defaults to stdin.')
34+
return parser
35+
36+
def prepare(self, *, register_resources: bool = True) -> None:
37+
super().prepare(register_resources=False)
38+
39+
def run(self) -> None:
40+
from hathor.transaction.base_transaction import tx_or_block_from_bytes
41+
42+
pattern = r'new (tx|block) .*bytes=([^ ]*) '
43+
pattern = r'new (tx|block) .*bytes=([^ ]*) '
44+
compiled_pattern = re.compile(pattern)
45+
46+
while True:
47+
line_with_break = self._args.log_input.readline()
48+
if not line_with_break:
49+
break
50+
line = line_with_break.strip()
51+
52+
matches = compiled_pattern.findall(line)
53+
if len(matches) == 0:
54+
continue
55+
56+
assert len(matches) == 1
57+
_, vertex_bytes_hex = matches[0]
58+
59+
vertex_bytes = bytes.fromhex(vertex_bytes_hex)
60+
vertex = tx_or_block_from_bytes(vertex_bytes)
61+
self.manager.on_new_tx(vertex)
62+
63+
64+
def main():
65+
RunFromLogs().run()

0 commit comments

Comments
 (0)