Skip to content

Commit

Permalink
feat(protocol): implement Bridge.isMessageFailed (#13004)
Browse files Browse the repository at this point in the history
Co-authored-by: Roger <50648015+RogerLamTd@users.noreply.github.com>
Co-authored-by: jeff <113397187+cyberhorsey@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 21, 2023
1 parent 609e96f commit 45153d9
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 2 deletions.
14 changes: 14 additions & 0 deletions packages/protocol/contracts/bridge/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,20 @@ contract Bridge is EssentialContract, IBridge {
});
}

function isMessageFailed(
bytes32 msgHash,
uint256 destChainId,
bytes calldata proof
) public view virtual override returns (bool) {
return
LibBridgeStatus.isMessageFailed({
resolver: AddressResolver(this),
msgHash: msgHash,
destChainId: destChainId,
proof: proof
});
}

function getMessageStatus(
bytes32 msgHash
) public view virtual returns (LibBridgeStatus.MessageStatus) {
Expand Down
7 changes: 7 additions & 0 deletions packages/protocol/contracts/bridge/IBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ interface IBridge {
bytes calldata proof
) external view returns (bool);

/// Checks if a msgHash has been failed on the destination chain.
function isMessageFailed(
bytes32 msgHash,
uint256 destChainId,
bytes calldata proof
) external view returns (bool);

/// Returns the bridge state context.
function context() external view returns (Context memory context);
}
6 changes: 6 additions & 0 deletions packages/protocol/contracts/bridge/libs/LibBridgeData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pragma solidity ^0.8.9;

import "../../common/AddressResolver.sol";
import "../../libs/LibAddress.sol";
import "../../libs/LibBlockHeader.sol";
import "../../libs/LibMath.sol";
import "../IBridge.sol";

Expand All @@ -23,6 +24,11 @@ library LibBridgeData {
uint256[46] __gap;
}

struct StatusProof {
BlockHeader header;
bytes proof;
}

bytes32 internal constant MESSAGE_HASH_PLACEHOLDER = bytes32(uint256(1));
uint256 internal constant CHAINID_PLACEHOLDER = type(uint256).max;
address internal constant SRC_CHAIN_SENDER_PLACEHOLDER =
Expand Down
40 changes: 40 additions & 0 deletions packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@

pragma solidity ^0.8.9;

import "../../common/IHeaderSync.sol";
import "../../libs/LibBlockHeader.sol";
import "../../libs/LibTrieProof.sol";
import "./LibBridgeData.sol";

/**
* @author dantaik <dan@taiko.xyz>
*/
library LibBridgeStatus {
using LibBlockHeader for BlockHeader;

enum MessageStatus {
NEW,
RETRIABLE,
Expand Down Expand Up @@ -52,6 +59,39 @@ library LibBridgeStatus {
return keccak256(abi.encodePacked("MESSAGE_STATUS", msgHash));
}

function isMessageFailed(
AddressResolver resolver,
bytes32 msgHash,
uint256 destChainId,
bytes calldata proof
) internal view returns (bool) {
require(destChainId != block.chainid, "B:destChainId");
require(msgHash != 0, "B:msgHash");

LibBridgeData.StatusProof memory sp = abi.decode(
proof,
(LibBridgeData.StatusProof)
);
bytes32 syncedHeaderHash = IHeaderSync(resolver.resolve("taiko", false))
.getSyncedHeader(sp.header.height);

if (
syncedHeaderHash == 0 ||
syncedHeaderHash != sp.header.hashBlockHeader()
) {
return false;
}

return
LibTrieProof.verify({
stateRoot: sp.header.stateRoot,
addr: resolver.resolve(destChainId, "bridge", false),
slot: getMessageStatusSlot(msgHash),
value: bytes32(uint256(LibBridgeStatus.MessageStatus.FAILED)),
mkproof: sp.proof
});
}

function _setMessageStatus(bytes32 msgHash, MessageStatus status) private {
bytes32 slot = getMessageStatusSlot(msgHash);
uint256 value = uint256(status);
Expand Down
2 changes: 2 additions & 0 deletions packages/protocol/tasks/deploy_L1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,15 @@ async function deployBaseLibs(hre: any) {
}

async function deployBridge(hre: any, addressManager: string): Promise<any> {
const libTrieProof = await utils.deployContract(hre, "LibTrieProof");
const libBridgeRetry = await utils.deployContract(hre, "LibBridgeRetry");
const libBridgeProcess = await utils.deployContract(
hre,
"LibBridgeProcess"
);

const Bridge = await utils.deployContract(hre, "Bridge", {
LibTrieProof: libTrieProof.address,
LibBridgeRetry: libBridgeRetry.address,
LibBridgeProcess: libBridgeProcess.address,
});
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/test/libs/LibTrieProof.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ describe("integration:LibTrieProof", function () {
libraries: {
LibBridgeProcess: libBridgeProcess.address,
LibBridgeRetry: libBridgeRetry.address,
LibTrieProof: testLibTreProof.address,
},
});

Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/test/test_integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ docker run -d \
function waitTestNode {
echo "Waiting for test node: $1"
# Wait till the test node fully started
RETRIES=30
RETRIES=120
i=0
until curl \
--silent \
Expand Down
8 changes: 8 additions & 0 deletions packages/protocol/test/utils/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SignalService,
EtherVault,
TestHeaderSync,
LibTrieProof,
} from "../../typechain";
import { Message } from "./message";
import { Block, BlockHeader, getBlockHeader } from "./rpc";
Expand All @@ -16,6 +17,12 @@ async function deployBridge(
addressManager: AddressManager,
chainId: number
): Promise<{ bridge: Bridge; etherVault: EtherVault }> {
const libTrieProof: LibTrieProof = await (
await hardhatEthers.getContractFactory("LibTrieProof")
)
.connect(signer)
.deploy();

const libBridgeProcess = await (
await hardhatEthers.getContractFactory("LibBridgeProcess")
)
Expand All @@ -30,6 +37,7 @@ async function deployBridge(

const BridgeFactory = await hardhatEthers.getContractFactory("Bridge", {
libraries: {
LibTrieProof: libTrieProof.address,
LibBridgeProcess: libBridgeProcess.address,
LibBridgeRetry: libBridgeRetry.address,
},
Expand Down
3 changes: 2 additions & 1 deletion packages/protocol/utils/generate_genesis/taikoL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,12 @@ async function generateContractConfigs(
break;
case "Bridge":
if (
!addressMap.LibTrieProof ||
!addressMap.LibBridgeRetry ||
!addressMap.LibBridgeProcess
) {
throw new Error(
"LibBridgeRetry/LibBridgeProcess not initialized"
"LibTrieProof/LibBridgeRetry/LibBridgeProcess not initialized"
);
}

Expand Down

0 comments on commit 45153d9

Please sign in to comment.