The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/solidity/contracts/isms/multisig/AbstractMerkleRootMultisigI...

65 lines
2.3 KiB

Make merkle proofs optional on multisig ISM (#2173) ### Description Validators currently sign `(root, index)` checkpoints and during verification, a `message` is passed as calldata, an `id()` is derived, and a `proof` of `id()` at `index` in `root` is verified This provides “all or nothing” censorship resistance guarantees because a validator can only sign roots to allow any contained messages to be processed. We have considered alternatives where validators sign `message` directly and we lose censorship resistance in exchange for eliminating merkle proof verification gas costs. However, if validators sign `(root, index, message)` tuples, we can skip merkle proof verification on the destination chain while still maintaining censorship resistance by providing two valid metadata formats: 1. existing validator signatures and merkle proof verification of inclusion 2. including merkle proof verification for pathway where validators are censoring `message` It’s worth noting the validator is required to index event data to produce this new signature format. However, this does not require historical indexing and new validators being spun up can simply begin indexing from tip. See https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2187 for validator changes See https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2248 for relayer and e2e test changes ### Drive-by changes Merkle index also optional ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2192 ### Backward compatibility - new ISM deployment is necessary (we could upgrade implementation in theory) - Validator and relayer upgrades ### Testing Unit (fuzz) Tests, E2E tests
2 years ago
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
// ============ Internal Imports ============
import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol";
import {AbstractMultisigIsm} from "./AbstractMultisigIsm.sol";
import {MerkleRootMultisigIsmMetadata} from "../../libs/isms/MerkleRootMultisigIsmMetadata.sol";
import {Message} from "../../libs/Message.sol";
import {MerkleLib} from "../../libs/Merkle.sol";
import {CheckpointLib} from "../../libs/CheckpointLib.sol";
/**
* @title MerkleRootMultisigIsm
* @notice Provides abstract logic for verifying signatures on a merkle root
* and a merkle proof of message inclusion in that root.
* @dev Implement and use if you want strong censorship resistance guarantees.
* @dev May be adapted in future to support batch message verification against a single root.
*/
abstract contract AbstractMerkleRootMultisigIsm is AbstractMultisigIsm {
// ============ Constants ============
// solhint-disable-next-line const-name-snakecase
uint8 public constant moduleType =
uint8(IInterchainSecurityModule.Types.MERKLE_ROOT_MULTISIG);
/**
* @inheritdoc AbstractMultisigIsm
*/
function digest(bytes calldata _metadata, bytes calldata _message)
internal
pure
override
returns (bytes32)
{
// We verify a merkle proof of (messageId, index) I to compute root J
bytes32 _root = MerkleLib.branchRoot(
Message.id(_message),
MerkleRootMultisigIsmMetadata.proof(_metadata),
Message.nonce(_message)
);
// We provide (messageId, index) J in metadata for digest derivation
return
CheckpointLib.digest(
Message.origin(_message),
MerkleRootMultisigIsmMetadata.originMailbox(_metadata),
_root,
MerkleRootMultisigIsmMetadata.index(_metadata),
MerkleRootMultisigIsmMetadata.messageId(_metadata)
);
}
/**
* @inheritdoc AbstractMultisigIsm
*/
function signatureAt(bytes calldata _metadata, uint256 _index)
internal
pure
virtual
override
returns (bytes memory signature)
{
return MerkleRootMultisigIsmMetadata.signatureAt(_metadata, _index);
}
}