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(protocol): fix singla service cannot be shared by multiple taiko L1/L2 contracts on the same chain bug #15807

Merged
merged 6 commits into from
Feb 15, 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
17 changes: 15 additions & 2 deletions packages/protocol/contracts/signal/SignalService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,36 +39,49 @@ contract SignalService is EssentialContract, ISignalService {
bytes[] storageProof;
}

uint256[50] private __gap;
mapping(address => bool) public isRelayerAuthorized;
uint256[49] private __gap;

event SnippetRelayed(
uint64 indexed chainid, bytes32 indexed kind, bytes32 data, bytes32 signal
);

event RelayerAuthorized(address indexed addr, bool authrized);

error SS_EMPTY_PROOF();
error SS_INVALID_APP();
error SS_INVALID_LAST_HOP_CHAINID();
error SS_INVALID_MID_HOP_CHAINID();
error SS_INVALID_PARAMS();
error SS_INVALID_SIGNAL();
error SS_LOCAL_CHAIN_DATA_NOT_FOUND();
error SS_UNAUTHORIZED();
error SS_UNSUPPORTED();

/// @dev Initializer to be called after being deployed behind a proxy.
function init(address _addressManager) external initializer {
__Essential_init(_addressManager);
}

/// @dev Authorize or deautohrize an address for calling relayChainData
/// @dev Note that addr is supposed to be TaikoL1 and TaikoL1 contracts deployed locally.
function authorizeRelayer(address addr, bool toAuthorize) external onlyOwner {
if (isRelayerAuthorized[addr] == toAuthorize) revert SS_INVALID_PARAMS();
isRelayerAuthorized[addr] = toAuthorize;

emit RelayerAuthorized(addr, toAuthorize);
}

/// @inheritdoc ISignalService
function relayChainData(
uint64 chainId,
bytes32 kind,
bytes32 data
)
external
onlyFromNamed("taiko")
returns (bytes32 slot)
{
if (!isRelayerAuthorized[msg.sender]) revert SS_UNAUTHORIZED();
return _relayChainData(chainId, kind, data);
}

Expand Down
5 changes: 4 additions & 1 deletion packages/protocol/script/DeployOnL1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ contract DeployOnL1 is DeployCapability {
addressNotNull(taikoL1Addr, "taikoL1Addr");
TaikoL1 taikoL1 = TaikoL1(payable(taikoL1Addr));

if (vm.envAddress("SHARED_ADDRESS_MANAGER") == address(0)) {
SignalService(signalServiceAddr).authorizeRelayer(taikoL1Addr, true);
}

uint64 l2ChainId = taikoL1.getConfig().chainId;
require(l2ChainId != block.chainid, "same chainid");

Expand All @@ -116,7 +120,6 @@ contract DeployOnL1 is DeployCapability {
copyRegister(rollupAddressManager, sharedAddressManager, "taiko_token");
copyRegister(rollupAddressManager, sharedAddressManager, "signal_service");
copyRegister(rollupAddressManager, sharedAddressManager, "bridge");
copyRegister(sharedAddressManager, rollupAddressManager, "taiko");

address proposer = vm.envAddress("PROPOSER");
if (proposer != address(0)) {
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/test/L1/TaikoL1TestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ abstract contract TaikoL1TestBase is TaikoTest {
data: abi.encodeCall(SignalService.init, address(addressManager))
})
);
ss.authorizeRelayer(address(L1), true);

pv = PseZkVerifier(
deployProxy({
Expand Down
18 changes: 11 additions & 7 deletions packages/protocol/test/L2/TaikoL2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ contract TestTaikoL2 is TaikoTest {
data: abi.encodeCall(AddressManager.init, ())
});

deployProxy({
name: "signal_service",
impl: address(new SignalService()),
data: abi.encodeCall(SignalService.init, (addressManager)),
registerTo: addressManager,
owner: address(0)
});
SignalService ss = SignalService(
deployProxy({
name: "signal_service",
impl: address(new SignalService()),
data: abi.encodeCall(SignalService.init, (addressManager)),
registerTo: addressManager,
owner: address(0)
})
);

uint64 gasExcess = 0;
uint8 quotient = 8;
Expand All @@ -55,6 +57,8 @@ contract TestTaikoL2 is TaikoTest {

L2.setConfigAndExcess(TaikoL2.Config(gasTarget, quotient), gasExcess);

ss.authorizeRelayer(address(L2), true);

gasExcess = 195_420_300_100;

vm.roll(block.number + 1);
Expand Down
18 changes: 11 additions & 7 deletions packages/protocol/test/L2/TaikoL2NoFeeCheck.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ contract TestTaikoL2NoFeeCheck is TaikoTest {
data: abi.encodeCall(AddressManager.init, ())
});

deployProxy({
name: "signal_service",
impl: address(new SignalService()),
data: abi.encodeCall(SignalService.init, (addressManager)),
registerTo: addressManager,
owner: address(0)
});
SignalService ss = SignalService(
deployProxy({
name: "signal_service",
impl: address(new SignalService()),
data: abi.encodeCall(SignalService.init, (addressManager)),
registerTo: addressManager,
owner: address(0)
})
);

uint64 gasExcess = 0;
uint8 quotient = 8;
Expand All @@ -55,6 +57,8 @@ contract TestTaikoL2NoFeeCheck is TaikoTest {

L2.setConfigAndExcess(TaikoL2.Config(gasTarget, quotient), gasExcess);

ss.authorizeRelayer(address(L2), true);

vm.roll(block.number + 1);
vm.warp(block.timestamp + 30);
}
Expand Down
9 changes: 8 additions & 1 deletion packages/protocol/test/signal/SignalService.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ contract TestSignalService is TaikoTest {
);

taiko = randAddress();
addressManager.setAddress(uint64(block.chainid), "taiko", taiko);
signalService.authorizeRelayer(taiko, true);
vm.stopPrank();
}

Expand Down Expand Up @@ -298,6 +298,13 @@ contract TestSignalService is TaikoTest {
signal: randBytes32(),
proof: abi.encode(proofs)
});

vm.prank(Alice);
signalService.authorizeRelayer(taiko, false);

vm.expectRevert(SignalService.SS_UNAUTHORIZED.selector);
vm.prank(taiko);
signalService.relayChainData(srcChainId, LibSignals.SIGNAL_ROOT, proofs[0].rootHash);
}

function test_SignalService_proveSignalReceived_one_hop_state_root() public {
Expand Down
6 changes: 3 additions & 3 deletions packages/protocol/utils/generate_genesis/taikoL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,6 @@ async function generateContractConfigs(
// AddressManager
addresses: {
[chainId]: {
[ethers.utils.hexlify(
ethers.utils.toUtf8Bytes("taiko"),
)]: addressMap.TaikoL2,
[ethers.utils.hexlify(
ethers.utils.toUtf8Bytes("bridge"),
)]: addressMap.Bridge,
Expand Down Expand Up @@ -464,6 +461,9 @@ async function generateContractConfigs(
_owner: ownerSecurityCouncil,
// AddressResolver
addressManager: addressMap.SharedAddressManager,
isRelayerAuthorized: {
[addressMap.TaikoL2]: true,
},
},
slots: {
[IMPLEMENTATION_SLOT]: addressMap.SignalServiceImpl,
Expand Down
Loading