mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
feat: 🏗️ Setup smart contracts structure for messages Substrate->Eth (#8)
This PR: - Sets up an interface for message passing from a Substrate chain to the Ethereum. - Adds a diagram for understanding how messages are validated.
This commit is contained in:
parent
7a4d441fd9
commit
70a034fab7
5 changed files with 140 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -16,6 +16,7 @@ Cargo.lock
|
|||
# IDE directories
|
||||
.vscode/
|
||||
.idea/
|
||||
.zed/
|
||||
|
||||
# cspell
|
||||
cspell.json
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 832 KiB |
BIN
contracts/resources/MessageProofs.png
Normal file
BIN
contracts/resources/MessageProofs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 504 KiB |
63
contracts/src/interfaces/IBeefyMessageVerifier.sol
Normal file
63
contracts/src/interfaces/IBeefyMessageVerifier.sol
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
interface IBeefyMessageVerifierErrors {}
|
||||
|
||||
interface IBeefyMessageVerifierEvents {}
|
||||
|
||||
/// @dev An BEEFY MMRLeaf without the `leaf_extra field.
|
||||
/// Reference: https://github.com/paritytech/polkadot-sdk/blob/1abdb7f39cada4840d795b9b721631a3cfe53174/substrate/primitives/consensus/beefy/src/mmr.rs#L53
|
||||
struct BeefyMMRLeafPartial {
|
||||
uint8 version;
|
||||
uint32 parentNumber;
|
||||
bytes32 parentHash;
|
||||
uint64 nextAuthoritySetID;
|
||||
uint32 nextAuthoritySetLen;
|
||||
bytes32 nextAuthoritySetRoot;
|
||||
}
|
||||
|
||||
/// @dev Parameters used to verify a proof generated by https://github.com/paritytech/polkadot-sdk/blob/1abdb7f39cada4840d795b9b721631a3cfe53174/substrate/utils/binary-merkle-tree/src/lib.rs#L144
|
||||
struct SubstrateBinaryMerkleProof {
|
||||
uint256 position;
|
||||
uint256 width;
|
||||
bytes32[] proof;
|
||||
}
|
||||
|
||||
/// @dev Parameters used to verify a that a BEEFY MMRLeaf is part of the latest BEEFY MMR Root.
|
||||
/// Reference: https://github.com/Snowfork/snowbridge/blob/069177d6c6d44c5a1478ae2f14051c0b3bd7a69a/contracts/src/BeefyClient.sol#L399
|
||||
struct BeefyMMRProof {
|
||||
bytes32[] proof;
|
||||
uint256 leafProofOrder;
|
||||
}
|
||||
|
||||
interface IBeefyMessageVerifier is IBeefyMessageVerifierErrors, IBeefyMessageVerifierEvents {
|
||||
/**
|
||||
* @notice Verifies a message passed through the "Extra Leaf Data" field of a BEEFY MMRLeaf.
|
||||
* @dev The message has to be a part of the committed messages in a BEEFY MMRLeaf, that
|
||||
* is part of the latest BEEFY MMR Root that the validators have signed and finalised.
|
||||
* @dev To prove that the message is part of the committed messages, three proofs are required:
|
||||
* 1. A proof that the message is part of a message commitment in the BEEFY MMRLeaf.
|
||||
* 2. A proof that the message commitment is part of the BEEFY MMRLeaf.
|
||||
* 3. A proof that the BEEFY MMRLeaf is part of the latest BEEFY MMR Root.
|
||||
* @dev For more a diagram on these three layers of proofs, see:
|
||||
* https://github.com/Moonsong-Labs/datahaven/blob/main/contracts/resources/MessageProofs.png
|
||||
* @dev For more details on BEEFY, see: https://wiki.polkadot.network/docs/learn-consensus#bridging-beefy
|
||||
* @dev For more details on the MMRLeaf specification, see: https://spec.polkadot.network/sect-finality#defn-beefy-payload
|
||||
* @dev For more details on the verification of the MMRLeaf, see Snowbridge's docs: https://docs.snowbridge.network/architecture/verification/polkadot
|
||||
* @param message The message to verify.
|
||||
* @param messageProof The proof that the message is part of a message commitment in the BEEFY MMRLeaf.
|
||||
* @param messageId The ID that identifies the kind of message being passed through the "Extra Leaf Data" field of the BEEFY MMRLeaf.
|
||||
* @param messageCommitmentProof The proof that the message commitment is part of the BEEFY MMRLeaf.
|
||||
* @param partialBeefyLeaf The partial BEEFY leaf (without the `leaf_extra` field which contains the root of the message commitments).
|
||||
* @param beefyLeafProof The proof that the BEEFY MMRLeaf is part of the latest BEEFY MMR Root.
|
||||
* @return isValid Whether the message is valid.
|
||||
*/
|
||||
function verifyBeefyMessage(
|
||||
bytes calldata message,
|
||||
bytes calldata messageProof,
|
||||
bytes32 messageId,
|
||||
SubstrateBinaryMerkleProof calldata messageCommitmentProof,
|
||||
BeefyMMRLeafPartial calldata partialBeefyLeaf,
|
||||
BeefyMMRProof calldata beefyLeafProof
|
||||
) external view returns (bool);
|
||||
}
|
||||
76
contracts/src/middleware/ServiceMessageDispatcher.sol
Normal file
76
contracts/src/middleware/ServiceMessageDispatcher.sol
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
|
||||
import "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol";
|
||||
|
||||
import "../interfaces/IBeefyMessageVerifier.sol";
|
||||
|
||||
contract ServiceMessageDispatcher is IBeefyMessageVerifier, Initializable, OwnableUpgradeable {
|
||||
bytes32 public constant VALIDATOR_POINTS_MESSAGE_ID = keccak256("VALIDATOR_POINTS");
|
||||
bytes32 public constant SLASH_MESSAGE_ID = keccak256("SLASH");
|
||||
|
||||
/// @notice A mapping of message IDs to external verifiers.
|
||||
/// @dev The external verifier is a contract that implements the `IBeefyMessageVerifier` interface.
|
||||
/// @dev This provides a way to delegate the verification of unknown message IDs to an external contract,
|
||||
/// thus extending the functionality of this contract without the need to modify the contract.
|
||||
mapping(bytes32 => address) public messageIdToExternalVerifier;
|
||||
|
||||
function initialize() public initializer {
|
||||
__Ownable_init();
|
||||
}
|
||||
|
||||
function verifyValidatorPointsMessage(
|
||||
bytes calldata, // message,
|
||||
bytes calldata, // messageProof,
|
||||
SubstrateBinaryMerkleProof calldata, // messageCommitmentProof,
|
||||
BeefyMMRLeafPartial calldata, // partialBeefyLeaf,
|
||||
BeefyMMRProof calldata // beefyLeafProof
|
||||
) public view returns (bool) {
|
||||
// TODO: Implement the logic to verify the validator points message
|
||||
return true;
|
||||
}
|
||||
|
||||
function verifySlashMessage(
|
||||
bytes calldata, // message,
|
||||
bytes calldata, // messageProof,
|
||||
SubstrateBinaryMerkleProof calldata, // messageCommitmentProof,
|
||||
BeefyMMRLeafPartial calldata, // partialBeefyLeaf,
|
||||
BeefyMMRProof calldata // beefyLeafProof
|
||||
) public view returns (bool) {
|
||||
// TODO: Implement the logic to verify the slash message
|
||||
return true;
|
||||
}
|
||||
|
||||
function verifyBeefyMessage(
|
||||
bytes calldata message,
|
||||
bytes calldata messageProof,
|
||||
bytes32 messageId,
|
||||
SubstrateBinaryMerkleProof calldata messageCommitmentProof,
|
||||
BeefyMMRLeafPartial calldata partialBeefyLeaf,
|
||||
BeefyMMRProof calldata beefyLeafProof
|
||||
) external view override returns (bool) {
|
||||
// For known message IDs, we can verify it here.
|
||||
if (messageId == VALIDATOR_POINTS_MESSAGE_ID) {
|
||||
return verifyValidatorPointsMessage(
|
||||
message, messageProof, messageCommitmentProof, partialBeefyLeaf, beefyLeafProof
|
||||
);
|
||||
} else if (messageId == SLASH_MESSAGE_ID) {
|
||||
return verifySlashMessage(
|
||||
message, messageProof, messageCommitmentProof, partialBeefyLeaf, beefyLeafProof
|
||||
);
|
||||
} else if (messageIdToExternalVerifier[messageId] != address(0)) {
|
||||
// For unknown message IDs, we delegate the verification to an external verifier, if there is one registered.
|
||||
return IBeefyMessageVerifier(messageIdToExternalVerifier[messageId]).verifyBeefyMessage(
|
||||
message,
|
||||
messageProof,
|
||||
messageId,
|
||||
messageCommitmentProof,
|
||||
partialBeefyLeaf,
|
||||
beefyLeafProof
|
||||
);
|
||||
}
|
||||
// Unknown message IDs are not supported.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue