Skip to content

Commit 1fe053a

Browse files
committed
feat(nano): Add HTTP API and CLI to re-run blocks and nano transactions
1 parent e93c8bc commit 1fe053a

File tree

12 files changed

+1812
-3
lines changed

12 files changed

+1812
-3
lines changed

hathor/builder/resources_builder.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ def create_resources(self) -> server.Site:
260260
BlueprintSourceCodeResource,
261261
NanoContractHistoryResource,
262262
NanoContractStateResource,
263+
NCDryRunResource,
263264
)
264265
nc_resource = Resource()
265266
root.putChild(b'nano_contract', nc_resource)
@@ -273,6 +274,7 @@ def create_resources(self) -> server.Site:
273274
nc_resource.putChild(b'state', NanoContractStateResource(self.manager))
274275
nc_resource.putChild(b'creation', NCCreationResource(self.manager))
275276
nc_resource.putChild(b'logs', NCExecLogsResource(self.manager))
277+
nc_resource.putChild(b'dry_run', NCDryRunResource(self.manager))
276278

277279
if self._args.enable_debug_api:
278280
debug_resource = Resource()

hathor/nanocontracts/execution/block_executor.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ def __init__(
132132
def execute_block(
133133
self,
134134
block: Block,
135+
*,
136+
dry_run: bool = False,
135137
) -> Iterator[NCBlockEffect]:
136138
"""Execute block as generator, yielding effects without applying them.
137139
@@ -140,6 +142,8 @@ def execute_block(
140142
141143
Args:
142144
block: The block to execute.
145+
dry_run: If True, allows re-executing a block that has already been executed.
146+
This is useful for debugging and inspection without modifying state.
143147
144148
Yields:
145149
NCBlockEffect instances representing each step of execution.
@@ -151,7 +155,8 @@ def execute_block(
151155

152156
meta = block.get_metadata()
153157
assert not meta.voided_by
154-
assert meta.nc_block_root_id is None
158+
if not dry_run:
159+
assert meta.nc_block_root_id is None
155160

156161
parent = block.get_block_parent()
157162
parent_meta = parent.get_metadata()
@@ -163,9 +168,11 @@ def execute_block(
163168
if not tx.is_nano_contract():
164169
continue
165170
tx_meta = tx.get_metadata()
166-
assert tx_meta.nc_execution in {None, NCExecutionState.PENDING}
171+
if not dry_run:
172+
assert tx_meta.nc_execution in {None, NCExecutionState.PENDING}
167173
if tx_meta.voided_by:
168-
assert NC_EXECUTION_FAIL_ID not in tx_meta.voided_by
174+
if not dry_run:
175+
assert NC_EXECUTION_FAIL_ID not in tx_meta.voided_by
169176
nc_calls.append(tx)
170177

171178
nc_sorted_calls = self._nc_calls_sorter(block, nc_calls) if nc_calls else []

0 commit comments

Comments
 (0)