Skip to content

Commit 4fa3363

Browse files
authored
Attempt to remove circular dependencies (#149)
1 parent ed5db97 commit 4fa3363

File tree

10 files changed

+94
-31
lines changed

10 files changed

+94
-31
lines changed
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
{num_publications:20,
2-
average_gas_used_publish: 44563}
1+
{ "num_publications": 20, "average_gas_used_publish": 43453 }

snapshots/TaikoInboxTest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"publish": "891278"
2+
"publish": "869078"
33
}

src/protocol/CheckpointTracker.sol

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import {ICommitmentStore} from "./ICommitmentStore.sol";
66
import {IInbox} from "./IInbox.sol";
77
import {IVerifier} from "./IVerifier.sol";
88

9-
contract CheckpointTracker is ICheckpointTracker {
9+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
10+
11+
contract CheckpointTracker is ICheckpointTracker, Ownable {
1012
/// @dev The number of delayed publications up to the proven checkpoint
1113
uint256 private _totalDelayedPublications;
1214

@@ -16,26 +18,31 @@ contract CheckpointTracker is ICheckpointTracker {
1618
IInbox public immutable inbox;
1719
IVerifier public immutable verifier;
1820
ICommitmentStore public immutable commitmentStore;
19-
address public immutable proverManager;
21+
22+
address public proverManager;
2023

2124
/// @param _genesis the checkpoint commitment describing the initial state of the rollup
2225
/// @param _inbox the inbox contract that contains the publication feed
2326
/// @param _verifier a contract that can verify the validity of a transition from one checkpoint to another
24-
/// @param _proverManager contract responsible for managing the prover auction
2527
/// @param _commitmentStore contract responsible storing historical commitments
26-
constructor(bytes32 _genesis, address _inbox, address _verifier, address _proverManager, address _commitmentStore) {
28+
constructor(bytes32 _genesis, address _inbox, address _verifier, address _commitmentStore) Ownable(msg.sender) {
2729
// set the genesis checkpoint commitment of the rollup - genesis is trusted to be correct
2830
require(_genesis != 0, ZeroGenesisCommitment());
2931
inbox = IInbox(_inbox);
3032
uint256 latestPublicationId = inbox.getNextPublicationId() - 1;
3133

3234
verifier = IVerifier(_verifier);
3335
commitmentStore = ICommitmentStore(_commitmentStore);
34-
proverManager = _proverManager;
3536

3637
_saveCommitment(latestPublicationId, _genesis);
3738
}
3839

40+
/// @inheritdoc ICheckpointTracker
41+
function updateProverManager(address _proverManager) external onlyOwner {
42+
proverManager = _proverManager;
43+
emit ProverManagerUpdated(_proverManager);
44+
}
45+
3946
/// @inheritdoc ICheckpointTracker
4047
/// @dev Accepts the last proven checkpoint (or an older one) as the start checkpoint. The reason we allow for an
4148
/// older checkpoint is to prevent cases where a prover spends time generating a larger proof and the checkpoint

src/protocol/ICheckpointTracker.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,17 @@ interface ICheckpointTracker {
4343
/// @param commitment the commitment of the latest proven checkpoint
4444
event CommitmentSaved(uint256 indexed publicationId, bytes32 commitment);
4545

46+
/// @notice Emitted when ProverManager is updated
47+
/// @param proverManager The address of the ProverManager contract
48+
event ProverManagerUpdated(address indexed proverManager);
49+
4650
/// @return _ The last proven publication ID
4751
function provenPublicationId() external view returns (uint256);
4852

53+
/// @notice Updates the address of the ProverManager contract
54+
/// @param _proverManager The address of the ProverManager contract
55+
function updateProverManager(address _proverManager) external;
56+
4957
/// @notice Verifies a transition between two checkpoints. Update the latest `provenCheckpoint` if possible
5058
/// @param start The initial checkpoint before the transition
5159
/// @param end The final checkpoint after the transition

src/protocol/IInbox.sol

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ interface IInbox {
1717
/// @param attributes The data contained within the publication
1818
event Published(bytes32 indexed pubHash, PublicationHeader header, bytes[] attributes);
1919

20+
/// @dev Event emitted when ProposerFees is initialized
21+
event ProposerFeesInitialized(address proposerFees);
22+
2023
/// @notice Publish blobs with anchor block information
2124
/// @param nBlobs Number of blobs to publish
2225
/// @param anchorBlockId The anchor block ID
@@ -35,4 +38,8 @@ interface IInbox {
3538
/// @param header The header to validate
3639
/// @return _ True if the header is valid, false otherwise
3740
function validateHeader(PublicationHeader calldata header) external view returns (bool);
41+
42+
/// @notice Updates the proposer fees contract address (prover manager contract)
43+
/// @param _proposerFees Address of the proposer fees contract
44+
function updateProposerFees(address _proposerFees) external;
3845
}

src/protocol/taiko_alethia/TaikoInbox.sol

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import {IInbox} from "../IInbox.sol";
1010
import {ILookahead} from "../ILookahead.sol";
1111
import {IProposerFees} from "../IProposerFees.sol";
1212

13-
contract TaikoInbox is IInbox, DelayedInclusionStore {
13+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
14+
15+
contract TaikoInbox is IInbox, DelayedInclusionStore, Ownable {
1416
/// @dev Caller is not the current preconfer
1517
error NotCurrentPreconfer();
1618

@@ -20,17 +22,14 @@ contract TaikoInbox is IInbox, DelayedInclusionStore {
2022
/// @dev Blockhash is not available for the anchor block
2123
error BlockhashUnavailable();
2224

23-
/// @dev Proposer fee set to zero address
24-
error ZeroProposerFees();
25-
2625
struct Metadata {
2726
uint256 anchorBlockId;
2827
bytes32 anchorBlockHash;
2928
bool isDelayedInclusion;
3029
}
3130

3231
ILookahead public immutable lookahead;
33-
IProposerFees public immutable proposerFees;
32+
IProposerFees public proposerFees;
3433
uint256 public immutable maxAnchorBlockIdOffset;
3534

3635
// attributes associated with the publication
@@ -43,23 +42,24 @@ contract TaikoInbox is IInbox, DelayedInclusionStore {
4342
/// @param _lookahead Address of the lookahead contract
4443
/// @param _blobRefRegistry Address of the blob reference registry contract
4544
/// @param _maxAnchorBlockIdOffset Maximum offset allowed for anchor block ID
46-
/// @param _proposerFees Address of the proposer fees contract (usually prover manager)
4745
/// @param _inclusionDelay How long before delayed inclusion must be processed
48-
constructor(
49-
address _lookahead,
50-
address _blobRefRegistry,
51-
uint256 _maxAnchorBlockIdOffset,
52-
address _proposerFees,
53-
uint256 _inclusionDelay
54-
) DelayedInclusionStore(_inclusionDelay, _blobRefRegistry) {
55-
require(_proposerFees != address(0), ZeroProposerFees());
46+
constructor(address _lookahead, address _blobRefRegistry, uint256 _maxAnchorBlockIdOffset, uint256 _inclusionDelay)
47+
DelayedInclusionStore(_inclusionDelay, _blobRefRegistry)
48+
Ownable(msg.sender)
49+
{
5650
lookahead = ILookahead(_lookahead);
5751
maxAnchorBlockIdOffset = _maxAnchorBlockIdOffset;
58-
proposerFees = IProposerFees(_proposerFees);
52+
5953
// guarantee there is always a previous hash
6054
_publicationHashes.push(0);
6155
}
6256

57+
/// @inheritdoc IInbox
58+
function updateProposerFees(address _proposerFees) external onlyOwner {
59+
proposerFees = IProposerFees(_proposerFees);
60+
emit ProposerFeesInitialized(_proposerFees);
61+
}
62+
6363
/// @inheritdoc IInbox
6464
function publish(uint256 nBlobs, uint64 anchorBlockId) external {
6565
if (address(lookahead) != address(0)) {
@@ -100,7 +100,9 @@ contract TaikoInbox is IInbox, DelayedInclusionStore {
100100
/// @param attributes The data to publish
101101
/// @param isDelayed Whether this is a delayed inclusion publication
102102
function _publish(bytes[] memory attributes, bool isDelayed) internal {
103-
proposerFees.payPublicationFee(msg.sender, isDelayed);
103+
if (address(proposerFees) != address(0)) {
104+
proposerFees.payPublicationFee(msg.sender, isDelayed);
105+
}
104106

105107
uint256 nAttributes = attributes.length;
106108
bytes32[] memory attributeHashes = new bytes32[](nAttributes);

test/CheckpointTracker.t.sol

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ pragma solidity ^0.8.28;
33

44
import {MockInbox} from "./mocks/MockInbox.sol";
55
import {MockVerifier} from "./mocks/MockVerifier.sol";
6+
7+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
68
import "forge-std/Test.sol";
79
import {CheckpointTracker} from "src/protocol/CheckpointTracker.sol";
810
import {ICheckpointTracker} from "src/protocol/ICheckpointTracker.sol";
@@ -15,6 +17,7 @@ contract CheckpointTrackerTest is Test {
1517
SignalService signalService;
1618
address proverManager = makeAddr("proverManager");
1719
bytes32 genesis = keccak256(abi.encode("genesis"));
20+
address deployer = makeAddr("deployer");
1821

1922
ICheckpointTracker.Checkpoint start;
2023
ICheckpointTracker.Checkpoint end;
@@ -24,13 +27,15 @@ contract CheckpointTrackerTest is Test {
2427
inbox = new MockInbox();
2528
verifier = new MockVerifier();
2629
signalService = new SignalService();
27-
tracker =
28-
new CheckpointTracker(genesis, address(inbox), address(verifier), proverManager, address(signalService));
30+
vm.startPrank(deployer);
31+
tracker = new CheckpointTracker(genesis, address(inbox), address(verifier), address(signalService));
32+
tracker.updateProverManager(address(proverManager));
33+
vm.stopPrank();
2934
}
3035

3136
function test_constructor_shouldRevertWithZeroGenesis() public {
3237
vm.expectRevert(ICheckpointTracker.ZeroGenesisCommitment.selector);
33-
new CheckpointTracker(bytes32(0), address(inbox), address(verifier), proverManager, address(signalService));
38+
new CheckpointTracker(bytes32(0), address(verifier), proverManager, address(signalService));
3439
}
3540

3641
function test_constructor_shouldSetExternalContracts() public view {
@@ -49,6 +54,38 @@ contract CheckpointTrackerTest is Test {
4954
assertEq(savedCommitment, genesis, "Did not save genesis");
5055
}
5156

57+
function test_updateProverManager_shouldSetProverManager() public {
58+
vm.startPrank(deployer);
59+
CheckpointTracker uninitializedTracker =
60+
new CheckpointTracker(genesis, address(inbox), address(verifier), address(signalService));
61+
uninitializedTracker.updateProverManager(proverManager);
62+
assertEq(address(uninitializedTracker.proverManager()), proverManager, "Did not set prover manager");
63+
}
64+
65+
function test_proveTransition_shouldSucceedWithNoProverManager() public {
66+
CheckpointTracker uninitializedTracker =
67+
new CheckpointTracker(genesis, address(inbox), address(verifier), address(signalService));
68+
_constructValidTransition();
69+
uninitializedTracker.proveTransition(start, end, proof);
70+
}
71+
72+
function test_initializeProverManager_onlyOwner() public {
73+
vm.prank(deployer);
74+
CheckpointTracker uninitializedTracker =
75+
new CheckpointTracker(genesis, address(inbox), address(verifier), address(signalService));
76+
77+
address notDeployer = makeAddr("notdeployer");
78+
vm.prank(notDeployer);
79+
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, notDeployer));
80+
uninitializedTracker.updateProverManager(proverManager);
81+
}
82+
83+
function test_updateProverManager_shouldUpdateProverManager() public {
84+
vm.prank(deployer);
85+
tracker.updateProverManager(makeAddr("newProverManager"));
86+
assertEq(address(tracker.proverManager()), makeAddr("newProverManager"), "Did not update prover manager");
87+
}
88+
5289
function test_proveTransition_shouldRevertIfNotCalledByProverManager() public {
5390
_constructValidTransition();
5491
vm.expectRevert(ICheckpointTracker.OnlyProverManager.selector);

test/Gas/Inbox.t.sol

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,8 @@ contract TaikoInboxTest is Test {
2424
uint256 inclusionDelay = uint256(10000000);
2525

2626
function setUp() public {
27-
MockProposerFees mockProposerFees = new MockProposerFees();
2827
blobRefRegistry = new BlobRefRegistry();
29-
taikoInbox = new TaikoInbox(
30-
lookaheadAddr, address(blobRefRegistry), maxAnchorBlockIdOffset, address(mockProposerFees), inclusionDelay
31-
);
28+
taikoInbox = new TaikoInbox(lookaheadAddr, address(blobRefRegistry), maxAnchorBlockIdOffset, inclusionDelay);
3229
}
3330

3431
function test_gas_TaikoPublishFunction() public ProposeMultiplePublications(10) {

test/mocks/MockCheckpointTracker.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ contract MockCheckpointTracker is ICheckpointTracker {
2424
return (nPublications, nDelayedPublications);
2525
}
2626

27+
function updateProverManager(address _proverManager) external {}
28+
2729
function setValid(bool isValid) external {
2830
valid = isValid;
2931
}

test/mocks/MockInbox.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ contract MockInbox is IInbox {
1616
revert NotImplemented();
1717
}
1818

19+
function updateProposerFees(address) external pure {
20+
revert NotImplemented();
21+
}
22+
1923
function getPublicationHash(uint256 id) external view returns (bytes32) {
2024
if (id >= numPublications) return 0;
2125
return keccak256(abi.encode("MockInbox", id));

0 commit comments

Comments
 (0)