From 5d59e6a0d8412d1a73356b10fde8bf64dede2561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 11 Sep 2024 17:48:06 +0200 Subject: [PATCH] Kernel: Unit tests for signal encoding and decoding --- .../kernel/src/dal_slot_import_signal.rs | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) diff --git a/etherlink/kernel_evm/kernel/src/dal_slot_import_signal.rs b/etherlink/kernel_evm/kernel/src/dal_slot_import_signal.rs index 611317508978..97784eb2be13 100644 --- a/etherlink/kernel_evm/kernel/src/dal_slot_import_signal.rs +++ b/etherlink/kernel_evm/kernel/src/dal_slot_import_signal.rs @@ -103,3 +103,269 @@ impl Decodable for DalSlotImportSignals { Ok(DalSlotImportSignals { signals, signature }) } } + +#[cfg(test)] +mod tests { + use super::{ + DalSlotImportSignals, DalSlotIndicesList, DalSlotIndicesOfLevel, + UnsignedDalSlotSignals, + }; + use rlp::{Decodable, DecoderError, Encodable}; + use tezos_crypto_rs::hash::UnknownSignature; + use tezos_ethereum::rlp_helpers::FromRlpBytes; + + #[derive(PartialEq, Debug, Clone)] + pub enum RlpTree { + Val(Vec), + List(Vec), + } + + impl Decodable for RlpTree { + fn decode(decoder: &rlp::Rlp) -> Result { + if decoder.is_list() { + let l: Vec = decoder.as_list()?; + Ok(RlpTree::List(l)) + } else { + let s: Vec = decoder.as_val()?; + Ok(RlpTree::Val(s)) + } + } + } + + impl Encodable for RlpTree { + fn rlp_append(&self, stream: &mut rlp::RlpStream) { + match self { + RlpTree::List(trees) => { + stream.begin_list(trees.len()); + for tree in trees { + stream.append(tree); + } + } + RlpTree::Val(bytes) => { + stream.append(bytes); + } + }; + } + } + + fn index_expected(v: u8, tree: RlpTree) { + let encoded = v.rlp_bytes(); + let encoded_as_tree: RlpTree = + FromRlpBytes::from_rlp_bytes(&encoded).expect("should decode as tree"); + assert_eq!( + encoded_as_tree, tree, + "Encoding gave unexpected result, source: {:?}, expected: {:?}, actual: {:?}", + v, tree, encoded_as_tree + ); + + let v2: u8 = + FromRlpBytes::from_rlp_bytes(&encoded).expect("Index should be decodable"); + assert_eq!(v, v2); + } + + fn indices_expected(v: Vec, tree: RlpTree) { + let v = DalSlotIndicesList(v); + let encoded = v.rlp_bytes(); + let encoded_as_tree: RlpTree = + FromRlpBytes::from_rlp_bytes(&encoded).expect("should decode as tree"); + assert_eq!( + encoded_as_tree, tree, + "Encoding gave unexpected result, source: {:?}, expected: {:?}, actual: {:?}", + v, tree, encoded_as_tree + ); + + let v2: DalSlotIndicesList = + FromRlpBytes::from_rlp_bytes(&encoded).expect("Indices should be decodable"); + assert_eq!(v, v2); + } + + fn indices_roundtrip(v: Vec) { + let v = DalSlotIndicesList(v); + let bytes = v.rlp_bytes(); + let v2: DalSlotIndicesList = + FromRlpBytes::from_rlp_bytes(&bytes).expect("Indices should be decodable"); + assert_eq!(v, v2, "Roundtrip failed for indices: {:?}", v); + } + + fn indices_of_level_roundtrip(published_level: u32, slot_indices: Vec) { + let slot_indices = DalSlotIndicesList(slot_indices); + let v = DalSlotIndicesOfLevel { + published_level, + slot_indices, + }; + let bytes = v.rlp_bytes(); + let v2: DalSlotIndicesOfLevel = FromRlpBytes::from_rlp_bytes(&bytes) + .expect("Slot indices of level should be decodable"); + assert_eq!(v, v2, "Roundtrip failed for slot indices of level: {:?}", v); + } + + fn unsigned_signals_roundtrip(v: UnsignedDalSlotSignals) { + let bytes = v.rlp_bytes(); + let v2: UnsignedDalSlotSignals = FromRlpBytes::from_rlp_bytes(&bytes) + .expect("Unsigned signals should be decodable"); + assert_eq!(v, v2, "Roundtrip failed for unsigned signals: {:?}", v); + + let signature = UnknownSignature::from_base58_check( + "sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3" + ).expect("signature decoding should work"); + + let v3 = DalSlotImportSignals { + signals: v, + signature, + }; + let bytes = v3.rlp_bytes(); + let v4: DalSlotImportSignals = FromRlpBytes::from_rlp_bytes(&bytes) + .expect("Signed signals should be decodable"); + assert_eq!(v3, v4, "Roundtrip failed for signed signals: {:?}", v3) + } + + #[test] + fn indices_roundtrip_tests() { + indices_roundtrip(vec![]); + indices_roundtrip(vec![0]); + indices_roundtrip(vec![1]); + indices_roundtrip(vec![0, 1]); + } + + #[test] + fn index_expected_zero() { + index_expected(0, RlpTree::Val(vec![])); + } + + #[test] + fn index_expected_one() { + index_expected(1, RlpTree::Val(vec![1])); + } + + #[test] + fn index_expected_128() { + index_expected(128, RlpTree::Val(vec![128])); + } + + #[test] + fn indices_expected_empty() { + indices_expected(vec![], RlpTree::List(vec![])); + } + + #[test] + fn indices_expected_zero() { + indices_expected(vec![0], RlpTree::List(vec![RlpTree::Val(vec![])])); + } + + #[test] + fn indices_expected_one() { + indices_expected(vec![1], RlpTree::List(vec![RlpTree::Val(vec![1])])); + } + + #[test] + fn indices_expected_zero_zero() { + indices_expected( + vec![0, 0], + RlpTree::List(vec![RlpTree::Val(vec![]), RlpTree::Val(vec![])]), + ); + } + + #[test] + fn indices_expected_zero_one() { + indices_expected( + vec![0, 1], + RlpTree::List(vec![RlpTree::Val(vec![]), RlpTree::Val(vec![1])]), + ); + } + + #[test] + fn indices_expected_one_one() { + indices_expected( + vec![1, 1], + RlpTree::List(vec![RlpTree::Val(vec![1]), RlpTree::Val(vec![1])]), + ); + } + + #[test] + fn indices_expected_one_one_one_one() { + indices_expected( + vec![1, 1, 1, 1], + RlpTree::List(vec![ + RlpTree::Val(vec![1]), + RlpTree::Val(vec![1]), + RlpTree::Val(vec![1]), + RlpTree::Val(vec![1]), + ]), + ); + } + + #[test] + fn indices_expected_zero_zero_zero_zero() { + indices_expected( + vec![0, 0, 0, 0], + RlpTree::List(vec![ + RlpTree::Val(vec![]), + RlpTree::Val(vec![]), + RlpTree::Val(vec![]), + RlpTree::Val(vec![]), + ]), + ); + } + + #[test] + fn indices_of_level_roundtrip_tests() { + indices_of_level_roundtrip(0, vec![]); + indices_of_level_roundtrip(0, vec![0]); + indices_of_level_roundtrip(0, vec![1]); + indices_of_level_roundtrip(0, vec![0, 1]); + indices_of_level_roundtrip(100, vec![]); + indices_of_level_roundtrip(100, vec![0]); + indices_of_level_roundtrip(100, vec![1]); + indices_of_level_roundtrip(100, vec![0, 1]); + } + + #[test] + fn roundtrip_empty() { + let v = UnsignedDalSlotSignals(vec![]); + unsigned_signals_roundtrip(v); + } + + #[test] + fn roundtrip_single_empty() { + let indices_of_level = DalSlotIndicesOfLevel { + published_level: 0, + slot_indices: DalSlotIndicesList(vec![]), + }; + + let v = UnsignedDalSlotSignals(vec![indices_of_level]); + unsigned_signals_roundtrip(v); + } + + #[test] + fn roundtrip_single_zero() { + let indices_of_level = DalSlotIndicesOfLevel { + published_level: 0, + slot_indices: DalSlotIndicesList(vec![0]), + }; + + let v = UnsignedDalSlotSignals(vec![indices_of_level]); + unsigned_signals_roundtrip(v); + } + + #[test] + fn roundtrip_single_one() { + let indices_of_level = DalSlotIndicesOfLevel { + published_level: 0, + slot_indices: DalSlotIndicesList(vec![1]), + }; + + let v = UnsignedDalSlotSignals(vec![indices_of_level]); + unsigned_signals_roundtrip(v); + } + + #[test] + fn roundtrip_single_zero_one() { + let indices_of_level = DalSlotIndicesOfLevel { + published_level: 0, + slot_indices: DalSlotIndicesList(vec![0, 1]), + }; + + let v = UnsignedDalSlotSignals(vec![indices_of_level]); + unsigned_signals_roundtrip(v); + } +} -- GitLab