Skip to content

Commit 503a856

Browse files
authored
fix: leader appeal uses stored contract snapshot (#983)
1 parent 5001964 commit 503a856

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

backend/consensus/base.py

+27-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from abc import ABC, abstractmethod
1212
import threading
1313
import random
14+
from copy import deepcopy
1415

1516
from sqlalchemy.orm import Session
1617
from backend.consensus.vrf import get_validators_for_transaction
@@ -1034,6 +1035,12 @@ async def process_leader_appeal(
10341035
)
10351036
transaction.appeal_undetermined = True
10361037

1038+
context.contract_snapshot_supplier = (
1039+
lambda: context.contract_snapshot_factory(
1040+
context.transaction.to_address
1041+
)
1042+
)
1043+
10371044
# Begin state transitions starting from PendingState
10381045
state = PendingState()
10391046
while True:
@@ -1597,16 +1604,21 @@ async def handle(self, context):
15971604
if context.transaction.leader_only:
15981605
context.remaining_validators = []
15991606

1600-
# Create a contract snapshot for the transaction
1601-
contract_snapshot_supplier = lambda: context.contract_snapshot_factory(
1602-
context.transaction.to_address
1603-
)
1607+
# Create a contract snapshot for the transaction if not exists
1608+
if context.transaction.contract_snapshot:
1609+
contract_snapshot = deepcopy(context.transaction.contract_snapshot)
1610+
else:
1611+
contract_snapshot_supplier = lambda: context.contract_snapshot_factory(
1612+
context.transaction.to_address
1613+
)
1614+
context.contract_snapshot_supplier = contract_snapshot_supplier
1615+
contract_snapshot = contract_snapshot_supplier()
16041616

16051617
# Create a leader node for executing the transaction
16061618
leader_node = context.node_factory(
16071619
leader,
16081620
ExecutionMode.LEADER,
1609-
contract_snapshot_supplier(),
1621+
contract_snapshot,
16101622
None,
16111623
context.msg_handler,
16121624
context.contract_snapshot_factory,
@@ -1626,7 +1638,6 @@ async def handle(self, context):
16261638

16271639
# Set the validators and other context attributes
16281640
context.num_validators = len(context.remaining_validators) + 1
1629-
context.contract_snapshot_supplier = contract_snapshot_supplier
16301641
context.votes = votes
16311642

16321643
# Transition to the CommittingState
@@ -1991,9 +2002,10 @@ async def handle(self, context):
19912002
leaders_contract_snapshot = context.contract_snapshot_supplier()
19922003

19932004
# Set the contract snapshot for the transaction for a future rollback
1994-
context.transactions_processor.set_transaction_contract_snapshot(
1995-
context.transaction.hash, leaders_contract_snapshot.to_dict()
1996-
)
2005+
if not context.transaction.contract_snapshot:
2006+
context.transactions_processor.set_transaction_contract_snapshot(
2007+
context.transaction.hash, leaders_contract_snapshot.to_dict()
2008+
)
19972009

19982010
# Do not deploy or update the contract if the execution failed
19992011
if leader_receipt.execution_result == ExecutionResultStatus.SUCCESS:
@@ -2093,6 +2105,12 @@ async def handle(self, context):
20932105
else:
20942106
consensus_round = "Undetermined"
20952107

2108+
# Save the contract snapshot for potential future appeals
2109+
if not context.transaction.contract_snapshot:
2110+
context.transactions_processor.set_transaction_contract_snapshot(
2111+
context.transaction.hash, context.contract_snapshot_supplier().to_dict()
2112+
)
2113+
20962114
# Set the transaction result with the current consensus data
20972115
context.transactions_processor.set_transaction_result(
20982116
context.transaction.hash,

0 commit comments

Comments
 (0)