Skip to content

Commit

Permalink
Test message limits: max numMsg and msgSize
Browse files Browse the repository at this point in the history
  • Loading branch information
tmpolaczyk committed Nov 13, 2024
1 parent 90c2446 commit 72f296c
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 35 deletions.
61 changes: 36 additions & 25 deletions pallets/external-validator-slashes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,36 +281,47 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::force_inject_slash())]
pub fn root_test_send_msg_to_eth(
origin: OriginFor<T>,
message_id: H256,
payload: H256,
nonce: H256,
num_msgs: u32,
msg_size: u32,
) -> DispatchResult {
ensure_root(origin)?;

// Example command, this should be something like "ReportSlashes"
let command = Command::Test(payload.as_ref().to_vec());

// Validate
let channel_id: ChannelId = snowbridge_core::PRIMARY_GOVERNANCE_CHANNEL;

let outbound_message = Message {
id: Some(message_id),
channel_id,
command,
};
for i in 0..num_msgs {
// Make sure each message has a different payload
let mut payload = sp_core::blake2_256((nonce, i).encode().as_ref()).to_vec();
// Extend with zeros until msg_size is reached
payload.resize(msg_size as usize, 0);
// Example command, this should be something like "ReportSlashes"
let command = Command::Test(payload);

// Validate
let channel_id: ChannelId = snowbridge_core::PRIMARY_GOVERNANCE_CHANNEL;

let outbound_message = Message {
id: None,
channel_id,
command,
};

// validate the message
// Ignore fee because for now only root can send messages
let (ticket, _fee) =
T::ValidateMessage::validate(&outbound_message).map_err(|err| {
log::error!(
"root_test_send_msg_to_eth: validation of message {i} failed. {err:?}"
);
crate::pallet::Error::<T>::EthereumValidateFail
})?;

// validate the message
// Ignore fee because for now only root can send messages
let (ticket, _fee) =
T::ValidateMessage::validate(&outbound_message).map_err(|err| {
log::error!("root_test_send_msg_to_eth: validation of message failed. {err:?}");
Error::<T>::EthereumValidateFail
// Deliver
T::OutboundQueue::deliver(ticket).map_err(|err| {
log::error!(
"root_test_send_msg_to_eth: delivery of message {i} failed. {err:?}"
);
crate::pallet::Error::<T>::EthereumDeliverFail
})?;

// Deliver
T::OutboundQueue::deliver(ticket).map_err(|err| {
log::error!("root_test_send_msg_to_eth: delivery of message failed. {err:?}");
Error::<T>::EthereumDeliverFail
})?;
}

Ok(())
}
Expand Down
188 changes: 185 additions & 3 deletions test/suites/dev-tanssi-relay/slashes/test_slashes_eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ describeSuite({
polkadotJs = context.polkadotJs();
alice = context.keyring.alice;
});

it({
id: "E01",
title: "Test using rootTestSendMsgToEth",
test: async function () {
await jumpToSession(context, 1);

// Send test message to ethereum
const msgId = "0x0000000000000000000000000000000000000000000000000000000000000001";
const payloadH256 = "0x0000000000000000000000000000000000000000000000000000000000000002";
const nonce = "0x0000000000000000000000000000000000000000000000000000000000000000";
const numMsg = 1;
const msgSize = 32;
const tx = await polkadotJs.tx.sudo
.sudo(polkadotJs.tx.externalValidatorSlashes.rootTestSendMsgToEth(msgId, payloadH256))
.sudo(polkadotJs.tx.externalValidatorSlashes.rootTestSendMsgToEth(nonce, numMsg, msgSize))
.signAsync(alice);
await context.createBlock([tx]);

Expand All @@ -36,6 +38,13 @@ describeSuite({
expect(otherLogs.length).to.be.equal(1);
const logHex = otherLogs[0]["other"];

await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 1,
Processed: 1,
MessageQueued: 1,
});

// Also a MessagesCommitted event with the same hash as the digest log
const events = await polkadotJs.query.system.events();
const ev1 = events.filter((a) => {
Expand Down Expand Up @@ -74,6 +83,139 @@ describeSuite({
expect(otherLogs.length).to.be.equal(1);
const logHex = otherLogs[0]["other"];

await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 1,
Processed: 1,
MessageQueued: 1,
});

// Also a MessagesCommitted event with the same hash as the digest log
const events = await polkadotJs.query.system.events();
const ev1 = events.filter((a) => {
return a.event.method == "MessagesCommitted";
});
expect(ev1.length).to.be.equal(1);
const ev1Data = ev1[0].event.data[0].toJSON();

// logHex == 0x00 + ev1Data
// Example:
// logHex: 0x0064cf0ef843ad5a26c2cc27cf345fe0fd8b72cd6297879caa626c4d72bbe4f9b0
// ev1Data: 0x64cf0ef843ad5a26c2cc27cf345fe0fd8b72cd6297879caa626c4d72bbe4f9b0
const prefixedEv1Data = `0x00${ev1Data.slice(2)}`;
expect(prefixedEv1Data).to.be.equal(logHex);
},
});

it({
id: "E03",
title: "Send too big message using rootTestSendMsgToEth",
test: async function () {
await jumpToSession(context, 1);

// Send test message to ethereum
const nonce = "0x0000000000000000000000000000000000000000000000000000000000000000";
const numMsg = 1;
// TODO: the limit should be 2048 bytes, not 1921
const msgSize = 1921;
const tx = await polkadotJs.tx.sudo
.sudo(polkadotJs.tx.externalValidatorSlashes.rootTestSendMsgToEth(nonce, numMsg, msgSize))
.signAsync(alice);
await context.createBlock([tx]);

await expectEventCount(polkadotJs, {
MessagesCommitted: 0,
MessageAccepted: 0,
Processed: 0,
MessageQueued: 0,
});

// Also a MessagesCommitted event with the same hash as the digest log
const events = await polkadotJs.query.system.events();
const ev1 = events.filter((a) => {
return a.event.method == "Sudid";
});
expect(ev1.length).to.be.equal(1);
const ev1Data = ev1[0].event.data[0].toJSON();
expect(ev1Data["err"]).toBeTruthy();
},
});

it({
id: "E04",
title: "Send message of max size using rootTestSendMsgToEth",
test: async function () {
await jumpToSession(context, 1);

// Send test message to ethereum
const nonce = "0x0000000000000000000000000000000000000000000000000000000000000000";
const numMsg = 1;
const msgSize = 1920;
const tx = await polkadotJs.tx.sudo
.sudo(polkadotJs.tx.externalValidatorSlashes.rootTestSendMsgToEth(nonce, numMsg, msgSize))
.signAsync(alice);
await context.createBlock([tx]);

// Should have resulted in a new "other" digest log being included in the block
const baseHeader = await polkadotJs.rpc.chain.getHeader();
const allLogs = baseHeader.digest.logs.map((x) => x.toJSON());
const otherLogs = allLogs.filter((x) => x["other"]);
expect(otherLogs.length).to.be.equal(1);
const logHex = otherLogs[0]["other"];

await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 1,
Processed: 1,
MessageQueued: 1,
});

// Also a MessagesCommitted event with the same hash as the digest log
const events = await polkadotJs.query.system.events();
const ev1 = events.filter((a) => {
return a.event.method == "MessagesCommitted";
});
expect(ev1.length).to.be.equal(1);
const ev1Data = ev1[0].event.data[0].toJSON();

// logHex == 0x00 + ev1Data
// Example:
// logHex: 0x0064cf0ef843ad5a26c2cc27cf345fe0fd8b72cd6297879caa626c4d72bbe4f9b0
// ev1Data: 0x64cf0ef843ad5a26c2cc27cf345fe0fd8b72cd6297879caa626c4d72bbe4f9b0
const prefixedEv1Data = `0x00${ev1Data.slice(2)}`;
expect(prefixedEv1Data).to.be.equal(logHex);
},
});

it({
id: "E05",
title: "Send 100 messages using rootTestSendMsgToEth",
test: async function () {
await jumpToSession(context, 1);

// Send test message to ethereum
const nonce = "0x0000000000000000000000000000000000000000000000000000000000000000";
const numMsg = 100;
const msgSize = 32;
const tx = await polkadotJs.tx.sudo
.sudo(polkadotJs.tx.externalValidatorSlashes.rootTestSendMsgToEth(nonce, numMsg, msgSize))
.signAsync(alice);
await context.createBlock([tx]);

// Should have resulted in a new "other" digest log being included in the block
const baseHeader = await polkadotJs.rpc.chain.getHeader();
const allLogs = baseHeader.digest.logs.map((x) => x.toJSON());
const otherLogs = allLogs.filter((x) => x["other"]);
expect(otherLogs.length).to.be.equal(1);
const logHex = otherLogs[0]["other"];

await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 32,
Processed: 32,
MessageQueued: 100,
});

// Also a MessagesCommitted event with the same hash as the digest log
const events = await polkadotJs.query.system.events();
const ev1 = events.filter((a) => {
Expand All @@ -88,7 +230,47 @@ describeSuite({
// ev1Data: 0x64cf0ef843ad5a26c2cc27cf345fe0fd8b72cd6297879caa626c4d72bbe4f9b0
const prefixedEv1Data = `0x00${ev1Data.slice(2)}`;
expect(prefixedEv1Data).to.be.equal(logHex);

// Next block will have 32 events more
await context.createBlock();
await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 32,
Processed: 32,
MessageQueued: 0,
});

// Total so far: 64
await context.createBlock();
await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 32,
Processed: 32,
MessageQueued: 0,
});

// Total so far: 96, missing last 4
await context.createBlock();
await expectEventCount(polkadotJs, {
MessagesCommitted: 1,
MessageAccepted: 4,
Processed: 4,
MessageQueued: 0,
});
},
});
},
});

async function expectEventCount(polkadotJs, eventCounts: Record<string, number>): Promise<void> {
const events = await polkadotJs.query.system.events();

for (const [eventMethod, expectedCount] of Object.entries(eventCounts)) {
const matchingEvents = events.filter(({ event }) => event.method === eventMethod);

expect(
matchingEvents.length,
`Expected ${expectedCount} occurrences of event '${eventMethod}', but found ${matchingEvents.length}`
).to.equal(expectedCount);
}
}
7 changes: 4 additions & 3 deletions typescript-api/src/dancelight/interfaces/augment-api-tx.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions typescript-api/src/dancelight/interfaces/lookup.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions typescript-api/src/dancelight/interfaces/types-lookup.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 72f296c

Please sign in to comment.