Skip to content

Commit

Permalink
feat!: add epoch length to consensus contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
guidanoli committed Aug 7, 2024
1 parent 73fbcea commit 7f27379
Show file tree
Hide file tree
Showing 18 changed files with 351 additions and 65 deletions.
9 changes: 9 additions & 0 deletions .changeset/popular-ghosts-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@cartesi/rollups": major
---

Added an `epochLength` parameter to functions of:

- `IAuthorityFactory`
- `ISelfHostedApplicationFactory`
- `IQuorumFactory`
5 changes: 5 additions & 0 deletions .changeset/six-schools-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/rollups": minor
---

Added a `getEpochLength` function to `IConsensus` interface.
15 changes: 15 additions & 0 deletions contracts/consensus/AbstractConsensus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ import {IConsensus} from "./IConsensus.sol";
/// @dev This contract was designed to be inherited by implementations of the `IConsensus` interface
/// that only need a simple mechanism of storage and retrieval of accepted claims.
abstract contract AbstractConsensus is IConsensus {
/// @notice The epoch length
uint256 private immutable _epochLength;

/// @notice Indexes accepted claims by application contract address.
mapping(address => mapping(bytes32 => bool)) private _acceptedClaims;

/// @param epochLength The epoch length
/// @dev Reverts if the epoch length is zero.
constructor(uint256 epochLength) {
require(epochLength > 0, "epoch length must not be zero");
_epochLength = epochLength;
}

/// @inheritdoc IConsensus
function wasClaimAccepted(
address appContract,
Expand All @@ -20,6 +30,11 @@ abstract contract AbstractConsensus is IConsensus {
return _acceptedClaims[appContract][claim];
}

/// @inheritdoc IConsensus
function getEpochLength() public view override returns (uint256) {
return _epochLength;
}

/// @notice Accept a claim.
/// @param appContract The application contract address
/// @param lastProcessedBlockNumber The number of the last processed block
Expand Down
5 changes: 5 additions & 0 deletions contracts/consensus/IConsensus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@ interface IConsensus {
address appContract,
bytes32 claim
) external view returns (bool);

/// @notice Get the epoch length, in number of base layer blocks.
/// @dev The epoch number of a block is defined as
/// the integer division of the block number by the epoch length.
function getEpochLength() external view returns (uint256);
}
7 changes: 6 additions & 1 deletion contracts/consensus/authority/Authority.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import {AbstractConsensus} from "../AbstractConsensus.sol";
/// For more information on `Ownable`, please consult OpenZeppelin's official documentation.
contract Authority is AbstractConsensus, Ownable {
/// @param initialOwner The initial contract owner
constructor(address initialOwner) Ownable(initialOwner) {}
/// @param epochLength The epoch length
/// @dev Reverts if the epoch length is zero.
constructor(
address initialOwner,
uint256 epochLength
) AbstractConsensus(epochLength) Ownable(initialOwner) {}

/// @notice Submit a claim.
/// @param appContract The application contract address
Expand Down
14 changes: 10 additions & 4 deletions contracts/consensus/authority/AuthorityFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import {Authority} from "./Authority.sol";
/// @notice Allows anyone to reliably deploy a new `Authority` contract.
contract AuthorityFactory is IAuthorityFactory {
function newAuthority(
address authorityOwner
address authorityOwner,
uint256 epochLength
) external override returns (Authority) {
Authority authority = new Authority(authorityOwner);
Authority authority = new Authority(authorityOwner, epochLength);

emit AuthorityCreated(authority);

Expand All @@ -23,9 +24,13 @@ contract AuthorityFactory is IAuthorityFactory {

function newAuthority(
address authorityOwner,
uint256 epochLength,
bytes32 salt
) external override returns (Authority) {
Authority authority = new Authority{salt: salt}(authorityOwner);
Authority authority = new Authority{salt: salt}(
authorityOwner,
epochLength
);

emit AuthorityCreated(authority);

Expand All @@ -34,6 +39,7 @@ contract AuthorityFactory is IAuthorityFactory {

function calculateAuthorityAddress(
address authorityOwner,
uint256 epochLength,
bytes32 salt
) external view override returns (address) {
return
Expand All @@ -42,7 +48,7 @@ contract AuthorityFactory is IAuthorityFactory {
keccak256(
abi.encodePacked(
type(Authority).creationCode,
abi.encode(authorityOwner)
abi.encode(authorityOwner, epochLength)
)
)
);
Expand Down
12 changes: 11 additions & 1 deletion contracts/consensus/authority/IAuthorityFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,40 @@ interface IAuthorityFactory {

/// @notice Deploy a new authority.
/// @param authorityOwner The initial authority owner
/// @param epochLength The epoch length
/// @return The authority
/// @dev On success, MUST emit an `AuthorityCreated` event.
/// @dev Reverts if the authority owner address is zero.
function newAuthority(address authorityOwner) external returns (Authority);
/// @dev Reverts if the epoch length is zero.
function newAuthority(
address authorityOwner,
uint256 epochLength
) external returns (Authority);

/// @notice Deploy a new authority deterministically.
/// @param authorityOwner The initial authority owner
/// @param epochLength The epoch length
/// @param salt The salt used to deterministically generate the authority address
/// @return The authority
/// @dev On success, MUST emit an `AuthorityCreated` event.
/// @dev Reverts if the authority owner address is zero.
/// @dev Reverts if the epoch length is zero.
function newAuthority(
address authorityOwner,
uint256 epochLength,
bytes32 salt
) external returns (Authority);

/// @notice Calculate the address of an authority to be deployed deterministically.
/// @param authorityOwner The initial authority owner
/// @param epochLength The epoch length
/// @param salt The salt used to deterministically generate the authority address
/// @return The deterministic authority address
/// @dev Beware that only the `newAuthority` function with the `salt` parameter
/// is able to deterministically deploy an authority.
function calculateAuthorityAddress(
address authorityOwner,
uint256 epochLength,
bytes32 salt
) external view returns (address);
}
12 changes: 11 additions & 1 deletion contracts/consensus/quorum/IQuorumFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,40 @@ interface IQuorumFactory {

/// @notice Deploy a new quorum.
/// @param validators the list of validators
/// @param epochLength The epoch length
/// @return The quorum
/// @dev On success, MUST emit a `QuorumCreated` event.
/// @dev Duplicates in the `validators` array are ignored.
function newQuorum(address[] calldata validators) external returns (Quorum);
/// @dev Reverts if the epoch length is zero.
function newQuorum(
address[] calldata validators,
uint256 epochLength
) external returns (Quorum);

/// @notice Deploy a new quorum deterministically.
/// @param validators the list of validators
/// @param epochLength The epoch length
/// @param salt The salt used to deterministically generate the quorum address
/// @return The quorum
/// @dev On success, MUST emit a `QuorumCreated` event.
/// @dev Duplicates in the `validators` array are ignored.
/// @dev Reverts if the epoch length is zero.
function newQuorum(
address[] calldata validators,
uint256 epochLength,
bytes32 salt
) external returns (Quorum);

/// @notice Calculate the address of a quorum to be deployed deterministically.
/// @param validators the list of validators
/// @param epochLength The epoch length
/// @param salt The salt used to deterministically generate the quorum address
/// @return The deterministic quorum address
/// @dev Beware that only the `newQuorum` function with the `salt` parameter
/// is able to deterministically deploy a quorum.
function calculateQuorumAddress(
address[] calldata validators,
uint256 epochLength,
bytes32 salt
) external view returns (address);
}
7 changes: 6 additions & 1 deletion contracts/consensus/quorum/Quorum.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ contract Quorum is AbstractConsensus {
private _votes;

/// @param validators The array of validator addresses
/// @param epochLength The epoch length
/// @dev Duplicates in the `validators` array are ignored.
constructor(address[] memory validators) {
/// @dev Reverts if the epoch length is zero.
constructor(
address[] memory validators,
uint256 epochLength
) AbstractConsensus(epochLength) {
uint256 n;
for (uint256 i; i < validators.length; ++i) {
address validator = validators[i];
Expand Down
11 changes: 7 additions & 4 deletions contracts/consensus/quorum/QuorumFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import {Quorum} from "./Quorum.sol";
/// @notice Allows anyone to reliably deploy a new `Quorum` contract.
contract QuorumFactory is IQuorumFactory {
function newQuorum(
address[] calldata validators
address[] calldata validators,
uint256 epochLength
) external override returns (Quorum) {
Quorum quorum = new Quorum(validators);
Quorum quorum = new Quorum(validators, epochLength);

emit QuorumCreated(quorum);

Expand All @@ -23,9 +24,10 @@ contract QuorumFactory is IQuorumFactory {

function newQuorum(
address[] calldata validators,
uint256 epochLength,
bytes32 salt
) external override returns (Quorum) {
Quorum quorum = new Quorum{salt: salt}(validators);
Quorum quorum = new Quorum{salt: salt}(validators, epochLength);

emit QuorumCreated(quorum);

Expand All @@ -34,6 +36,7 @@ contract QuorumFactory is IQuorumFactory {

function calculateQuorumAddress(
address[] calldata validators,
uint256 epochLength,
bytes32 salt
) external view override returns (address) {
return
Expand All @@ -42,7 +45,7 @@ contract QuorumFactory is IQuorumFactory {
keccak256(
abi.encodePacked(
type(Quorum).creationCode,
abi.encode(validators)
abi.encode(validators, epochLength)
)
)
);
Expand Down
5 changes: 5 additions & 0 deletions contracts/dapp/ISelfHostedApplicationFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ interface ISelfHostedApplicationFactory {

/// @notice Deploy new application and authority contracts deterministically.
/// @param authorityOwner The initial authority owner
/// @param epochLength The epoch length
/// @param appOwner The initial Application owner
/// @param templateHash The initial machine state hash
/// @param salt The salt used to deterministically generate the addresses
/// @return The application contract
/// @return The authority contract
/// @dev Reverts if the authority owner address is zero.
/// @dev Reverts if the application owner address is zero.
/// @dev Reverts if the epoch length is zero.
function deployContracts(
address authorityOwner,
uint256 epochLength,
address appOwner,
bytes32 templateHash,
bytes32 salt
Expand All @@ -40,13 +43,15 @@ interface ISelfHostedApplicationFactory {
/// @notice Calculate the addresses of the application and authority contracts
/// to be deployed deterministically.
/// @param authorityOwner The initial authority owner
/// @param epochLength The epoch length
/// @param appOwner The initial Application owner
/// @param templateHash The initial machine state hash
/// @param salt The salt used to deterministically generate the addresses
/// @return The application address
/// @return The authority address
function calculateAddresses(
address authorityOwner,
uint256 epochLength,
address appOwner,
bytes32 templateHash,
bytes32 salt
Expand Down
9 changes: 8 additions & 1 deletion contracts/dapp/SelfHostedApplicationFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,16 @@ contract SelfHostedApplicationFactory is ISelfHostedApplicationFactory {

function deployContracts(
address authorityOwner,
uint256 epochLength,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external returns (Application application, Authority authority) {
authority = _authorityFactory.newAuthority(authorityOwner, salt);
authority = _authorityFactory.newAuthority(
authorityOwner,
epochLength,
salt
);

application = _applicationFactory.newApplication(
authority,
Expand All @@ -63,12 +68,14 @@ contract SelfHostedApplicationFactory is ISelfHostedApplicationFactory {

function calculateAddresses(
address authorityOwner,
uint256 epochLength,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external view returns (address application, address authority) {
authority = _authorityFactory.calculateAuthorityAddress(
authorityOwner,
epochLength,
salt
);

Expand Down
Loading

0 comments on commit 7f27379

Please sign in to comment.