Modify `Dispatch`, `Process` and add `DispatchId`, `ProcessId` (#1360)

* Modify Dispatch, Process and add DispatchId, ProcessId

* Update rust mailbox

* Update sdk

* Improve unit tests
pull/1378/head
Yorke Rhodes 2 years ago committed by GitHub
parent 6046ce68ef
commit 5b5ce88b72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 54
      rust/chains/hyperlane-ethereum/abis/Mailbox.abi.json
  2. 2
      rust/chains/hyperlane-ethereum/src/mailbox.rs
  3. 54
      solidity/contracts/Mailbox.sol
  4. 3
      solidity/test/lib/mailboxes.ts
  5. 23
      solidity/test/mailbox.test.ts
  6. 2
      solidity/update_abis.sh
  7. 2
      typescript/sdk/src/core/HyperlaneCore.ts
  8. 12
      typescript/sdk/src/core/TestCoreApp.ts
  9. 4
      typescript/sdk/src/core/message.ts

@ -26,10 +26,22 @@
{ {
"anonymous": false, "anonymous": false,
"inputs": [ "inputs": [
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"indexed": true,
"internalType": "uint32",
"name": "destination",
"type": "uint32"
},
{ {
"indexed": true, "indexed": true,
"internalType": "bytes32", "internalType": "bytes32",
"name": "messageId", "name": "recipient",
"type": "bytes32" "type": "bytes32"
}, },
{ {
@ -42,6 +54,19 @@
"name": "Dispatch", "name": "Dispatch",
"type": "event" "type": "event"
}, },
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "messageId",
"type": "bytes32"
}
],
"name": "DispatchId",
"type": "event"
},
{ {
"anonymous": false, "anonymous": false,
"inputs": [ "inputs": [
@ -77,16 +102,41 @@
{ {
"anonymous": false, "anonymous": false,
"inputs": [ "inputs": [
{
"indexed": true,
"internalType": "uint32",
"name": "origin",
"type": "uint32"
},
{ {
"indexed": true, "indexed": true,
"internalType": "bytes32", "internalType": "bytes32",
"name": "messageId", "name": "sender",
"type": "bytes32" "type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "recipient",
"type": "address"
} }
], ],
"name": "Process", "name": "Process",
"type": "event" "type": "event"
}, },
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "messageId",
"type": "bytes32"
}
],
"name": "ProcessId",
"type": "event"
},
{ {
"inputs": [], "inputs": [],
"name": "MAX_MESSAGE_BODY_BYTES", "name": "MAX_MESSAGE_BODY_BYTES",

@ -126,7 +126,7 @@ where
async fn fetch_delivered_messages(&self, from: u32, to: u32) -> Result<Vec<(H256, LogMeta)>> { async fn fetch_delivered_messages(&self, from: u32, to: u32) -> Result<Vec<(H256, LogMeta)>> {
Ok(self Ok(self
.contract .contract
.process_filter() .process_id_filter()
.from_block(from) .from_block(from)
.to_block(to) .to_block(to)
.query_with_meta() .query_with_meta()

@ -59,16 +59,41 @@ contract Mailbox is
/** /**
* @notice Emitted when a new message is dispatched via Hyperlane * @notice Emitted when a new message is dispatched via Hyperlane
* @param messageId The unique message identifier * @param sender The address that dispatched the message
* @param destination The destination domain of the message
* @param recipient The message recipient address on `destination`
* @param message Raw bytes of message * @param message Raw bytes of message
*/ */
event Dispatch(bytes32 indexed messageId, bytes message); event Dispatch(
address indexed sender,
uint32 indexed destination,
bytes32 indexed recipient,
bytes message
);
/** /**
* @notice Emitted when a Hyperlane message is delivered * @notice Emitted when a new message is dispatched via Hyperlane
* @param messageId The unique message identifier * @param messageId The unique message identifier
*/ */
event Process(bytes32 indexed messageId); event DispatchId(bytes32 indexed messageId);
/**
* @notice Emitted when a Hyperlane message is processed
* @param messageId The unique message identifier
*/
event ProcessId(bytes32 indexed messageId);
/**
* @notice Emitted when a Hyperlane message is delivered
* @param origin The origin domain of the message
* @param sender The message sender address on `origin`
* @param recipient The address that handled the message
*/
event Process(
uint32 indexed origin,
bytes32 indexed sender,
address indexed recipient
);
// ============ Constructor ============ // ============ Constructor ============
@ -122,7 +147,13 @@ contract Mailbox is
// Insert the message ID into the merkle tree. // Insert the message ID into the merkle tree.
bytes32 _id = _message.id(); bytes32 _id = _message.id();
tree.insert(_id); tree.insert(_id);
emit Dispatch(_id, _message); emit Dispatch(
msg.sender,
_destinationDomain,
_recipientAddress,
_message
);
emit DispatchId(_id);
return _id; return _id;
} }
@ -153,13 +184,12 @@ contract Mailbox is
require(_ism.verify(_metadata, _message), "!module"); require(_ism.verify(_metadata, _message), "!module");
// Deliver the message to the recipient. // Deliver the message to the recipient.
uint32 _origin = _message.origin(); uint32 origin = _message.origin();
IMessageRecipient(_message.recipientAddress()).handle( bytes32 sender = _message.sender();
_origin, address recipient = _message.recipientAddress();
_message.sender(), IMessageRecipient(recipient).handle(origin, sender, _message.body());
_message.body() emit Process(origin, sender, recipient);
); emit ProcessId(_id);
emit Process(_id);
} }
// ============ Public Functions ============ // ============ Public Functions ============

@ -40,12 +40,13 @@ export const dispatchMessageAndReturnProof = async (
messageStr: string, messageStr: string,
): Promise<MessageAndProof> => { ): Promise<MessageAndProof> => {
const nonce = await mailbox.count(); const nonce = await mailbox.count();
const { message, messageId } = await dispatchMessage( const { message } = await dispatchMessage(
mailbox, mailbox,
destination, destination,
utils.addressToBytes32(recipient), utils.addressToBytes32(recipient),
messageStr, messageStr,
); );
const messageId = utils.messageId(message);
const proof = await mailbox.proof(); const proof = await mailbox.proof();
return { return {
proof: { proof: {

@ -70,17 +70,14 @@ describe('Mailbox', async () => {
it('Dispatches a message', async () => { it('Dispatches a message', async () => {
// Send message with signer address as msg.sender // Send message with signer address as msg.sender
const recipientBytes = utils.addressToBytes32(recipient.address);
await expect( await expect(
mailbox mailbox.connect(signer).dispatch(destDomain, recipientBytes, body),
.connect(signer)
.dispatch(
destDomain,
utils.addressToBytes32(recipient.address),
body,
),
) )
.to.emit(mailbox, 'Dispatch') .to.emit(mailbox, 'Dispatch')
.withArgs(id, message); .withArgs(signer.address, destDomain, recipientBytes, message)
.to.emit(mailbox, 'DispatchId')
.withArgs(utils.messageId(message));
}); });
it('Returns the id of the dispatched message', async () => { it('Returns the id of the dispatched message', async () => {
@ -120,7 +117,15 @@ describe('Mailbox', async () => {
}); });
it('processes a message', async () => { it('processes a message', async () => {
await expect(mailbox.process('0x', message)).to.emit(mailbox, 'Process'); await expect(mailbox.process('0x', message))
.to.emit(mailbox, 'Process')
.withArgs(
originDomain,
utils.addressToBytes32(signer.address),
recipient,
)
.to.emit(mailbox, 'ProcessId')
.withArgs(id);
expect(await mailbox.delivered(id)).to.be.true; expect(await mailbox.delivered(id)).to.be.true;
}); });

@ -9,4 +9,4 @@ copy() {
jq .abi < artifacts/contracts/"$1".sol/"$CONTRACT_NAME".json > ../rust/chains/hyperlane-ethereum/abis/"$CONTRACT_NAME".abi.json jq .abi < artifacts/contracts/"$1".sol/"$CONTRACT_NAME".json > ../rust/chains/hyperlane-ethereum/abis/"$CONTRACT_NAME".abi.json
} }
copy Mailbox && copy isms/MultisigIsm && copy InterchainGasPaymaster copy Mailbox && copy InterchainGasPaymaster && copy isms/MultisigIsm

@ -120,7 +120,7 @@ export class HyperlaneCore<
): Promise<ethers.ContractReceipt> { ): Promise<ethers.ContractReceipt> {
const id = utils.messageId(message.message); const id = utils.messageId(message.message);
const { mailbox, chainConnection } = this.getDestination(message); const { mailbox, chainConnection } = this.getDestination(message);
const filter = mailbox.filters.Process(id); const filter = mailbox.filters.ProcessId(id);
return new Promise<ethers.ContractReceipt>((resolve, reject) => { return new Promise<ethers.ContractReceipt>((resolve, reject) => {
mailbox.once(filter, (emittedId, event) => { mailbox.once(filter, (emittedId, event) => {

@ -53,16 +53,14 @@ export class TestCoreApp<
const dispatchFilter = outbox.filters.Dispatch(); const dispatchFilter = outbox.filters.Dispatch();
const dispatches = await outbox.queryFilter(dispatchFilter); const dispatches = await outbox.queryFilter(dispatchFilter);
for (const dispatch of dispatches) { for (const dispatch of dispatches) {
const message = utils.parseMessage(dispatch.args.message); const destination = dispatch.args.destination;
const destination = message.destination;
if (destination === chainMetadata[origin].id) { if (destination === chainMetadata[origin].id) {
throw new Error('Dispatched message to local domain'); throw new Error('Dispatched message to local domain');
} }
const destinationChain = DomainIdToChainName[destination]; const destinationChain = DomainIdToChainName[destination] as TestChain;
const inbox: TestMailbox = const inbox = this.getContracts(destinationChain).mailbox.contract;
// @ts-ignore const id = utils.messageId(dispatch.args.message);
this.getContracts(destinationChain).mailbox.contract; const delivered = await inbox.delivered(id);
const delivered = await inbox.delivered(dispatch.args.messageId);
if (!delivered) { if (!delivered) {
const response = await inbox.process('0x', dispatch.args.message); const response = await inbox.process('0x', dispatch.args.message);
const destinationResponses = responses.get(destinationChain) || []; const destinationResponses = responses.get(destinationChain) || [];

@ -368,9 +368,9 @@ export class HyperlaneMessage {
} }
/** /**
* The messageId committed to the tree in the Outbox contract. * The messageId committed to the tree in the Mailbox contract.
*/ */
get id(): string { get id(): string {
return this.dispatch.event.args.messageId; return utils.messageId(this.dispatch.event.args.message);
} }
} }

Loading…
Cancel
Save