Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: get_consensus_state_for_member before initial epoch #559

Merged
merged 2 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
44 changes: 23 additions & 21 deletions src/modules/submodules/consensus.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@
from src.utils.cache import global_lru_cache as lru_cache
from src.web3py.types import Web3


logger = logging.getLogger(__name__)


# Initial epoch is in the future. Revert signature: '0xcd0883ea'
InitialEpochIsYetToArriveRevert = Web3.keccak(text="InitialEpochIsYetToArrive()")[:4].hex()

Expand Down Expand Up @@ -135,25 +133,29 @@ def get_member_info(self, blockstamp: BlockStamp) -> MemberInfo:
current_frame_consensus_report = current_frame_member_report = ZERO_HASH

if variables.ACCOUNT:
(
# Current frame's reference slot.
_, # current_frame_ref_slot
# Consensus report for the current frame, if any. Zero bytes otherwise.
current_frame_consensus_report,
# Whether the provided address is a member of the oracle committee.
is_member,
# Whether the oracle committee member is in the fast line members subset of the current reporting frame.
is_fast_lane,
# Whether the oracle committee member is allowed to submit a report at the moment of the call.
_, # can_report
# The last reference slot for which the member submitted a report.
last_member_report_ref_slot,
# The hash reported by the member for the current frame, if any.
current_frame_member_report,
) = consensus_contract.get_consensus_state_for_member(
variables.ACCOUNT.address,
blockstamp.block_hash,
)
try:
(
# Current frame's reference slot.
_, # current_frame_ref_slot
# Consensus report for the current frame, if any. Zero bytes otherwise.
current_frame_consensus_report,
# Whether the provided address is a member of the oracle committee.
is_member,
# Whether the oracle committee member is in the fast line members subset of the current reporting frame.
is_fast_lane,
# Whether the oracle committee member is allowed to submit a report at the moment of the call.
_, # can_report
# The last reference slot for which the member submitted a report.
last_member_report_ref_slot,
# The hash reported by the member for the current frame, if any.
current_frame_member_report,
) = consensus_contract.get_consensus_state_for_member(
variables.ACCOUNT.address,
blockstamp.block_hash,
)
except ContractCustomError as revert:
if revert.data != InitialEpochIsYetToArriveRevert:
raise revert

is_submit_member = self._is_submit_member(blockstamp)

Expand Down
28 changes: 25 additions & 3 deletions tests/modules/submodules/consensus/test_consensus.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,41 @@ def test_get_frame_custom_exception(web3, consensus):
consensus.get_initial_or_current_frame(bs)


@pytest.fixture()
def use_account(request):
if request.param:
request.getfixturevalue("set_submit_account")
else:
request.getfixturevalue("set_no_account")


@pytest.mark.unit
def test_first_frame_is_not_yet_started(web3, consensus, caplog, set_no_account):
@pytest.mark.parametrize(
"use_account", [True, False], ids=['with_account', "without_account"], indirect=["use_account"]
)
def test_first_frame_is_not_yet_started(web3, consensus, caplog, use_account):
bs = ReferenceBlockStampFactory.build()

consensus_contract = Mock(get_current_frame=Mock(side_effect=ContractCustomError('0xcd0883ea', '0xcd0883ea')))
err = ContractCustomError('0xcd0883ea', '0xcd0883ea')
consensus_contract = Mock(
get_current_frame=Mock(side_effect=err), get_consensus_state_for_member=Mock(side_effect=err)
)
consensus._get_consensus_contract = Mock(return_value=consensus_contract)
consensus._is_submit_member = Mock(return_value=True)
consensus.get_frame_config = Mock(return_value=FrameConfigFactory.build(initial_epoch=5, epochs_per_frame=10))
consensus.get_chain_config = Mock(return_value=ChainConfigFactory.build())

first_frame = consensus.get_initial_or_current_frame(bs)
member_info = consensus.get_member_info(bs)

assert first_frame.ref_slot == 5 * 32 - 1
assert first_frame.report_processing_deadline_slot == (5 + 10) * 32 - 1
assert member_info.is_submit_member
assert member_info.is_report_member
assert member_info.is_fast_lane
assert member_info.current_frame_consensus_report == ZERO_HASH
assert member_info.current_frame_member_report == ZERO_HASH
assert member_info.current_frame_ref_slot == first_frame.ref_slot
assert member_info.deadline_slot == first_frame.report_processing_deadline_slot


@pytest.mark.unit
Expand Down
Loading