Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass structured event log to ethereumInboundQueue.submit #1003

Merged
merged 27 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
967b2f0
Add support for message ids
vgeddes Nov 7, 2023
273542b
Add support for message IDs
vgeddes Nov 7, 2023
84d2a29
inbound-queue no longer depends on older legacy ethereum-related crates
vgeddes Nov 8, 2023
b0e408e
Use for generating unique message ids
vgeddes Nov 8, 2023
55787d9
foo
vgeddes Nov 8, 2023
f607876
Merge branch 'main' into message-id
vgeddes Nov 8, 2023
6f0eecb
Bump polkadot-sdk
vgeddes Nov 8, 2023
2118950
revert some changes that caused tests to fail
vgeddes Nov 8, 2023
75ccfa7
review feedback
vgeddes Nov 8, 2023
1186e92
more review feedback
vgeddes Nov 8, 2023
67a66b1
Update polkadot-sdk
vgeddes Nov 8, 2023
884355d
remove obsolete code
vgeddes Nov 8, 2023
2c303b2
Remove misc whitespace
vgeddes Nov 9, 2023
2fd9777
Add back tests I hastily removed
vgeddes Nov 9, 2023
9616e86
Merge branch 'message-id' into message-log
vgeddes Nov 9, 2023
468b6a1
Make everything work E2E
vgeddes Nov 9, 2023
0693278
Merge branch 'main' into message-id
vgeddes Nov 9, 2023
cf4a83f
Remove obsolete errors from ethereum-beacon-client
vgeddes Nov 9, 2023
167c4b5
Merge branch 'message-id' into message-log
vgeddes Nov 9, 2023
b18bc2a
fix clippy warning
vgeddes Nov 9, 2023
61f1f1d
update polkadot-sdk
vgeddes Nov 9, 2023
66bd206
Merge branch 'main' into message-log
vgeddes Nov 9, 2023
85dc7cd
fix clippy
vgeddes Nov 9, 2023
bda3f7a
unnecessary typeinfo
vgeddes Nov 10, 2023
4f23e5e
Merge branch 'main' into message-log
vgeddes Nov 10, 2023
64dac6d
Merge branch 'main' into message-log
vgeddes Nov 12, 2023
e23ac89
update polkadot-sdk
vgeddes Nov 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion parachain/Cargo.lock

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

42 changes: 20 additions & 22 deletions parachain/pallets/ethereum-beacon-client/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,33 @@
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
use super::*;

use snowbridge_core::inbound::VerificationError::{self, *};
use snowbridge_core::inbound::{
VerificationError::{self, *},
*,
};
use snowbridge_ethereum::Receipt;

impl<T: Config> Verifier for Pallet<T> {
/// Verify a message by verifying the existence of the corresponding
/// Ethereum log in a block. Returns the log if successful. The execution header containing
/// the log should be in the beacon client storage, meaning it has been verified and is an
/// ancestor of a finalized beacon block.
fn verify(message: &Message) -> Result<(), VerificationError> {
fn verify(event_log: &Log, proof: &Proof) -> Result<(), VerificationError> {
log::info!(
target: "ethereum-beacon-client",
"💫 Verifying message with block hash {}",
message.proof.block_hash,
proof.block_hash,
);

let header =
<ExecutionHeaderBuffer<T>>::get(message.proof.block_hash).ok_or(HeaderNotFound)?;
let header = <ExecutionHeaderBuffer<T>>::get(proof.block_hash).ok_or(HeaderNotFound)?;

let receipt = match Self::verify_receipt_inclusion(header.receipts_root, &message.proof) {
let receipt = match Self::verify_receipt_inclusion(header.receipts_root, proof) {
Ok(receipt) => receipt,
Err(err) => {
log::error!(
target: "ethereum-beacon-client",
"💫 Verification of receipt inclusion failed for block {}: {:?}",
message.proof.block_hash,
proof.block_hash,
err
);
return Err(err)
Expand All @@ -36,35 +38,31 @@ impl<T: Config> Verifier for Pallet<T> {
log::trace!(
target: "ethereum-beacon-client",
"💫 Verified receipt inclusion for transaction at index {} in block {}",
message.proof.tx_index, message.proof.block_hash,
proof.tx_index, proof.block_hash,
);

let log = match rlp::decode(&message.data) {
Ok(log) => log,
Err(err) => {
log::error!(
target: "ethereum-beacon-client",
"💫 RLP log decoded failed {}: {:?}",
message.proof.block_hash,
err
);
return Err(InvalidLog)
},
event_log.validate().map_err(|_| InvalidLog)?;

// Convert snowbridge_core::inbound::Log to snowbridge_ethereum::Log.
let event_log = snowbridge_ethereum::Log {
address: event_log.address,
topics: event_log.topics.clone(),
data: event_log.data.clone(),
};

if !receipt.contains_log(&log) {
if !receipt.contains_log(&event_log) {
log::error!(
target: "ethereum-beacon-client",
"💫 Event log not found in receipt for transaction at index {} in block {}",
message.proof.tx_index, message.proof.block_hash,
proof.tx_index, proof.block_hash,
);
return Err(LogNotFound)
}

log::info!(
target: "ethereum-beacon-client",
"💫 Receipt verification successful for {}",
message.proof.block_hash,
proof.block_hash,
);

Ok(())
Expand Down
5 changes: 1 addition & 4 deletions parachain/pallets/ethereum-beacon-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ use primitives::{
CompactBeaconState, CompactExecutionHeader, ExecutionHeaderState, ForkData, ForkVersion,
ForkVersions, PublicKeyPrepared, SigningData,
};
use snowbridge_core::{
inbound::{Message, Proof, Verifier},
BasicOperatingMode, RingBufferMap,
};
use snowbridge_core::{BasicOperatingMode, RingBufferMap};
use sp_core::H256;
use sp_std::prelude::*;
pub use weights::WeightInfo;
Expand Down
22 changes: 15 additions & 7 deletions parachain/pallets/ethereum-beacon-client/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub mod minimal {
use crate::config;
use hex_literal::hex;
use primitives::CompactExecutionHeader;
use snowbridge_core::inbound::{Message, Proof};
use snowbridge_core::inbound::{Log, Proof};
use sp_runtime::BuildStorage;
use std::{fs::File, path::PathBuf};

Expand Down Expand Up @@ -141,10 +141,18 @@ pub mod minimal {
load_fixture("next-finalized-header-update.minimal.json").unwrap()
}

pub fn get_message_verification_payload() -> Message {
Message {
data: hex!("f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").to_vec(),
proof: Proof {
pub fn get_message_verification_payload() -> (Log, Proof) {
(
Log {
address: hex!("ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0").into(),
topics: vec![
hex!("1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad").into(),
hex!("00000000000000000000000000000000000000000000000000000000000003e8").into(),
hex!("0000000000000000000000000000000000000000000000000000000000000001").into(),
],
data: hex!("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").into(),
},
Proof {
block_hash: hex!("05aaa60b0f27cce9e71909508527264b77ee14da7b5bf915fcc4e32715333213").into(),
tx_index: 0,
data: (vec![
Expand All @@ -156,8 +164,8 @@ pub mod minimal {
hex!("f851a0b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646a060a634b9280e3a23fb63375e7bbdd9ab07fd379ab6a67e2312bbc112195fa358808080808080808080808080808080").to_vec(),
hex!("f9030820b9030402f90300018301d6e2b9010000000000000800000000000020040008000000000000000000000000400000008000000000000000000000000000000000000000000000000000000000042010000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000002000000000000000000000000200000000000000200000000000100000000040000001000200008000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000f901f5f87a942ffa5ecdbe006d30397c7636d3e015eee251369ff842a0c965575a00553e094ca7c5d14f02e107c258dda06867cbf9e0e69f80e71bbcc1a000000000000000000000000000000000000000000000000000000000000003e8a000000000000000000000000000000000000000000000000000000000000003e8f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000f858948cf6147918a5cbb672703f879f385036f8793a24e1a01449abf21e49fd025f33495e77f7b1461caefdd3d4bb646424a3f445c4576a5ba0000000000000000000000000440edffa1352b13227e8ee646f3ea37456dec701").to_vec(),
]),
},
}
}
)
}

pub fn get_message_verification_header() -> CompactExecutionHeader {
Expand Down
57 changes: 36 additions & 21 deletions parachain/pallets/ethereum-beacon-client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -911,73 +911,88 @@ fn submit_execution_header_not_finalized() {
#[test]
fn verify_message() {
let header = get_message_verification_header();
let message = get_message_verification_payload();
let block_hash = message.proof.block_hash;
let (event_log, proof) = get_message_verification_payload();
let block_hash = proof.block_hash;

new_tester().execute_with(|| {
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
assert_ok!(EthereumBeaconClient::verify(&message));
assert_ok!(EthereumBeaconClient::verify(&event_log, &proof));
});
}

#[test]
fn verify_message_missing_header() {
let message = get_message_verification_payload();
let (event_log, proof) = get_message_verification_payload();

new_tester().execute_with(|| {
assert_err!(EthereumBeaconClient::verify(&message), VerificationError::HeaderNotFound);
assert_err!(
EthereumBeaconClient::verify(&event_log, &proof),
VerificationError::HeaderNotFound
);
});
}

#[test]
fn verify_message_invalid_proof() {
let header = get_message_verification_header();
let mut message = get_message_verification_payload();
message.proof.data.1[0] = TEST_HASH.into();
let block_hash = message.proof.block_hash;
let (event_log, mut proof) = get_message_verification_payload();
proof.data.1[0] = TEST_HASH.into();
let block_hash = proof.block_hash;

new_tester().execute_with(|| {
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
assert_err!(EthereumBeaconClient::verify(&message), VerificationError::InvalidProof);
assert_err!(
EthereumBeaconClient::verify(&event_log, &proof),
VerificationError::InvalidProof
);
});
}

#[test]
fn verify_message_invalid_receipts_root() {
let mut header = get_message_verification_header();
let message = get_message_verification_payload();
let block_hash = message.proof.block_hash;
let (event_log, proof) = get_message_verification_payload();
let block_hash = proof.block_hash;
header.receipts_root = TEST_HASH.into();

new_tester().execute_with(|| {
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
assert_err!(EthereumBeaconClient::verify(&message), VerificationError::InvalidProof);
assert_err!(
EthereumBeaconClient::verify(&event_log, &proof),
VerificationError::InvalidProof
);
});
}

#[test]
fn verify_message_invalid_message_data() {
fn verify_message_invalid_log() {
let header = get_message_verification_header();
let mut message = get_message_verification_payload();
let block_hash = message.proof.block_hash;
message.data = TEST_HASH.into();
let (mut event_log, proof) = get_message_verification_payload();
let block_hash = proof.block_hash;
event_log.topics = vec![H256::zero(); 10];

new_tester().execute_with(|| {
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
assert_err!(EthereumBeaconClient::verify(&message), VerificationError::InvalidLog);
assert_err!(
EthereumBeaconClient::verify(&event_log, &proof),
VerificationError::InvalidLog
);
});
}

#[test]
fn verify_message_receipt_does_not_contain_log() {
let header = get_message_verification_header();
let mut message = get_message_verification_payload();
let block_hash = message.proof.block_hash;
message.data = hex!("f9013c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000002b8c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000068000f000000000000000101d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec70100000101001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0000e8890423c78a0000000000000000000000000000000000000000000000000000000000000000").to_vec();
let (mut event_log, proof) = get_message_verification_payload();
let block_hash = proof.block_hash;
event_log.data = hex!("f9013c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000002b8c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000068000f000000000000000101d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec70100000101001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0000e8890423c78a0000000000000000000000000000000000000000000000000000000000000000").to_vec();

new_tester().execute_with(|| {
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
assert_err!(EthereumBeaconClient::verify(&message), VerificationError::LogNotFound);
assert_err!(
EthereumBeaconClient::verify(&event_log, &proof),
VerificationError::LogNotFound
);
});
}

Expand Down
12 changes: 10 additions & 2 deletions parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use hex_literal::hex;
use snowbridge_beacon_primitives::CompactExecutionHeader;
use snowbridge_core::inbound::{Message, Proof};
use snowbridge_core::inbound::{Log, Message, Proof};
use sp_std::vec;

pub struct InboundQueueTest {
Expand All @@ -17,7 +17,15 @@ pub fn make_create_message() -> InboundQueueTest {
receipts_root: hex!("0115ab735d37c5e4cdb0374d8bb547c6dd6ccaa996d996d1eabc5399a719219e").into(),
},
message: Message {
data: hex!("f8fc94eda338e4dc46038493b885327842fd3e301cab39f863a05066fbba677e15936860e04088ca4cad3acd4c19706962196a5346f1457f7169a000000000000000000000000000000000000000000000000000000000000003e8a0afad3c9777134532ae230b4fad334eef2e0dacbb965920412a7eaa59b07d640fb88000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001e000f000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d0000").to_vec(),
event_log: Log {
address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(),
topics: vec![
hex!("5066fbba677e15936860e04088ca4cad3acd4c19706962196a5346f1457f7169").into(),
hex!("00000000000000000000000000000000000000000000000000000000000003e8").into(),
hex!("afad3c9777134532ae230b4fad334eef2e0dacbb965920412a7eaa59b07d640f").into(),
],
data: hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001e000f000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d0000").into(),
},
proof: Proof {
block_hash: hex!("5f465744c166e9d10dc0031942a59ff82b640053253da517a1b576afdadb0363").into(),
tx_index: 0,
Expand Down
18 changes: 6 additions & 12 deletions parachain/pallets/inbound-queue/src/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
use snowbridge_core::ParaId;
use snowbridge_core::{inbound::Log, ParaId};

use sp_core::{RuntimeDebug, H160, H256};
use sp_std::{convert::TryFrom, prelude::*};

use alloy_primitives::{Address, Bytes, B256};
use alloy_rlp::RlpDecodable;
use alloy_primitives::B256;
use alloy_sol_types::{sol, SolEvent};

#[derive(RlpDecodable, RuntimeDebug)]
pub struct Log {
pub address: Address,
pub topics: Vec<B256>,
pub data: Bytes,
}

sol! {
event OutboundMessageAccepted(uint256 indexed destination, uint64 nonce, bytes32 indexed messageID, bytes payload);
}
Expand All @@ -42,11 +34,13 @@ impl TryFrom<Log> for Envelope {
type Error = EnvelopeDecodeError;

fn try_from(log: Log) -> Result<Self, Self::Error> {
let event = OutboundMessageAccepted::decode_log(log.topics, &log.data, true)
let topics: Vec<B256> = log.topics.iter().map(|x| B256::from_slice(x.as_ref())).collect();

let event = OutboundMessageAccepted::decode_log(topics, &log.data, true)
.map_err(|_| EnvelopeDecodeError)?;

Ok(Self {
gateway: H160::from(log.address.as_ref()),
gateway: log.address,
dest: event.destination.saturating_to::<u32>().into(),
nonce: event.nonce,
message_id: H256::from(event.messageID.as_ref()),
Expand Down
14 changes: 6 additions & 8 deletions parachain/pallets/inbound-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ pub mod weights;
#[cfg(test)]
mod test;

use alloy_rlp::Decodable as RlpDecodable;
use codec::{Decode, DecodeAll, Encode};
use envelope::{Envelope, Log};
use envelope::Envelope;
use frame_support::{
traits::{
fungible::{Inspect, Mutate},
Expand Down Expand Up @@ -213,13 +212,12 @@ pub mod pallet {
ensure!(!Self::operating_mode().is_halted(), Error::<T>::Halted);

// submit message to verifier for verification
T::Verifier::verify(&message).map_err(|e| Error::<T>::Verification(e))?;
T::Verifier::verify(&message.event_log, &message.proof)
.map_err(|e| Error::<T>::Verification(e))?;

let log = Log::decode(&mut message.data.as_slice())
.map_err(|_| Error::<T>::InvalidEnvelope)?;

// Decode log into an Envelope
let envelope = Envelope::try_from(log).map_err(|_| Error::<T>::InvalidEnvelope)?;
// Decode event log into an Envelope
let envelope =
Envelope::try_from(message.event_log).map_err(|_| Error::<T>::InvalidEnvelope)?;

// Verify that the message was submitted from the known Gateway contract
ensure!(T::GatewayAddress::get() == envelope.gateway, Error::<T>::InvalidGateway,);
Expand Down
Loading
Loading