Skip to content

Commit

Permalink
Separate getters for two phases where Notary data is not yet trusted:
Browse files Browse the repository at this point in the history
- Notary in ongoing Dispute / slashed
- Notary recently won a Dispute
  • Loading branch information
ChiTimesChi committed Oct 30, 2023
1 parent 23a2803 commit 23ed1fe
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 10 deletions.
6 changes: 3 additions & 3 deletions packages/contracts-core/contracts/Destination.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ contract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {
bytes32 agentRoot,
ChainGas[] memory snapGas
) external onlyInbox returns (bool wasAccepted) {
if (_isInDispute(notaryIndex)) revert NotaryInDispute();
if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();
// First, try passing current agent merkle root
(bool rootPassed, bool rootPending) = passAgentRoot();
// Don't accept attestation, if the agent root was updated in LightManager,
Expand Down Expand Up @@ -128,7 +128,7 @@ contract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {
DestinationStatus memory status = destStatus;
// Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`
// So we just need to check the Dispute status of the Notary
if (_isInDispute(status.notaryIndex)) {
if (_notaryDisputeExists(status.notaryIndex)) {
// Remove the pending agent merkle root, as its signer is in dispute
_nextAgentRoot = oldRoot;
return (false, false);
Expand Down Expand Up @@ -175,7 +175,7 @@ contract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {
function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {
StoredGasData memory storedGasData = _storedGasData[domain];
// Check if there is a stored gas data for the domain, and if the notary who provided the data is not in dispute
if (storedGasData.submittedAt != 0 && !_isInDispute(storedGasData.notaryIndex)) {
if (storedGasData.submittedAt != 0 && !_notaryDisputeExists(storedGasData.notaryIndex)) {
gasData = storedGasData.gasData;
dataMaturity = block.timestamp - storedGasData.submittedAt;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts-core/contracts/Summit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ contract Summit is SnapshotHub, SummitEvents, InterfaceSummit {
uint256 paddedTips,
bytes memory rcptPayload
) external onlyInbox returns (bool wasAccepted) {
if (_isInDispute(rcptNotaryIndex)) revert NotaryInDispute();
if (_notaryDisputeExists(rcptNotaryIndex)) revert NotaryInDispute();
// This will revert if payload is not a receipt body
return _saveReceipt({
rcpt: rcptPayload.castToReceipt(),
Expand All @@ -138,7 +138,7 @@ contract Summit is SnapshotHub, SummitEvents, InterfaceSummit {
onlyInbox
returns (bytes memory attPayload)
{
if (_isInDispute(notaryIndex)) revert NotaryInDispute();
if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();
// This will revert if payload is not a snapshot
return _acceptNotarySnapshot(snapPayload.castToSnapshot(), agentRoot, notaryIndex, sigIndex);
}
Expand Down
27 changes: 23 additions & 4 deletions packages/contracts-core/contracts/base/AgentSecured.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.17;

// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════
import {DISPUTE_TIMEOUT_NOTARY} from "../libs/Constants.sol";
import {ChainContext} from "../libs/ChainContext.sol";
import {CallerNotAgentManager, CallerNotInbox} from "../libs/Errors.sol";
import {AgentStatus, DisputeFlag, DisputeStatus} from "../libs/Structures.sol";
Expand Down Expand Up @@ -105,9 +106,27 @@ abstract contract AgentSecured is MessagingBase, IAgentSecured {
return IAgentManager(agentManager).getAgent(index);
}

/// @dev Checks if the agent with the given index is in a dispute.
function _isInDispute(uint32 agentIndex) internal view returns (bool) {
// TODO: add timeout for Notaries that just won the dispute.
return _disputes[agentIndex].flag != DisputeFlag.None;
/// @dev Checks if a Dispute exists for the given Notary. This function returns true, if
/// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.
/// In both cases we can't trust Notary's data.
/// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and
/// `_notaryDisputeTimeout` return false.
function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {
return _disputes[notaryIndex].flag != DisputeFlag.None;
}

/// @dev Checks if a Notary recently won a Dispute and is still in the "post-dispute" timeout period.
/// In this period we still can't trust Notary's data, though we can optimistically assume that
/// that the data will be correct after the timeout (assuming no new Disputes are opened).
/// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and
/// `_notaryDisputeTimeout` return false.
function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {
DisputeStatus memory status = _disputes[notaryIndex];
// Exit early if Notary is in ongoing Dispute / slashed.
if (status.flag != DisputeFlag.None) return false;
// Check if Notary has been in any Dispute at all.
if (status.openedAt == 0) return false;
// Otherwise check if the Dispute timeout is still active.
return block.timestamp < status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;
}
}
2 changes: 1 addition & 1 deletion packages/contracts-core/contracts/hubs/ExecutionHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ abstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, Exec
// Check if snapshot root has been submitted
if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();
// Check that Notary who submitted the attestation is not in dispute
if (_isInDispute(rootData.notaryIndex)) revert NotaryInDispute();
if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();
}

/// @dev Formats the message execution receipt payload for the given hash and receipt data.
Expand Down

0 comments on commit 23ed1fe

Please sign in to comment.