diff --git a/Node/src/ethereum_l1/execution_layer.rs b/Node/src/ethereum_l1/execution_layer.rs index f68a4c0..4b93d7e 100644 --- a/Node/src/ethereum_l1/execution_layer.rs +++ b/Node/src/ethereum_l1/execution_layer.rs @@ -6,7 +6,7 @@ use alloy::{ providers::ProviderBuilder, signers::{ local::{LocalSigner, PrivateKeySigner}, - SignerSync, + Signature, SignerSync, }, sol, sol_types::SolValue, @@ -286,6 +286,12 @@ impl ExecutionLayer { Ok(signature.as_bytes()) } + pub fn recover_address_from_msg(&self, msg: &[u8], signature: &[u8]) -> Result { + let signature = Signature::try_from(signature)?; + let address = signature.recover_address_from_msg(msg)?; + Ok(address) + } + pub async fn prove_incorrect_preconfirmation( &self, _block_id: u64, diff --git a/Node/src/node/mod.rs b/Node/src/node/mod.rs index 5dd7bfe..c9a4222 100644 --- a/Node/src/node/mod.rs +++ b/Node/src/node/mod.rs @@ -121,14 +121,25 @@ impl Node { Some(p2p_message) = p2p_to_node_rx.recv() => { let msg: PreconfirmationMessage = p2p_message.into(); tracing::debug!("Node received message from p2p: {:?}", msg); - // add to preconfirmation map - preconfirmed_blocks.lock().await.insert(msg.block_height, msg.proof); - // advance head - if let Err(e) = taiko - .advance_head_to_new_l2_block(msg.tx_lists, msg.gas_used) - .await { - tracing::error!("Failed to advance head: {}", e); + // TODO check valid preconfer + // check hash + if let Ok(hash) = L2TxListsCommit::from_preconf(msg.block_height, msg.tx_list_bytes).hash() { + if hash == msg.proof.commit_hash { + // check signature + if let Ok(_) = ethereum_l1.execution_layer.recover_address_from_msg(&msg.proof.commit_hash, &msg.proof.signature) { + // Add to preconfirmation map + preconfirmed_blocks.lock().await.insert(msg.block_height, msg.proof); + // Advance head + if let Err(e) = taiko.advance_head_to_new_l2_block(msg.tx_lists, msg.gas_used).await { + tracing::error!("Failed to advance head: {}", e); + } + } else { + tracing::error!("Failed to check signature"); + } } + } else { + tracing::warn!("Hash mismatch or failed to calculate hash."); + } } } } @@ -141,8 +152,7 @@ impl Node { ) -> Result<(), Error> { let preconfirmed_blocks = preconfirmed_blocks.lock().await; if let Some(block) = preconfirmed_blocks.get(&block_proposed.block_id) { - //TODO: verify the signature? - + //Signature is already verified on precof insertion if block.commit_hash != block_proposed.tx_list_hash { info!( "Block tx_list_hash is not correct for block_id: {}. Calling proof of incorrect preconfirmation.", @@ -228,6 +238,7 @@ impl Node { let preconf_message = PreconfirmationMessage { block_height: new_block_height, tx_lists: pending_tx_lists.tx_lists.clone(), + tx_list_bytes: pending_tx_lists.tx_list_bytes[0].clone(), //TODO: handle rest tx lists gas_used: self.gas_used, proof: proof.clone(), }; diff --git a/Node/src/utils/commit.rs b/Node/src/utils/commit.rs index 743dca8..2ddf201 100644 --- a/Node/src/utils/commit.rs +++ b/Node/src/utils/commit.rs @@ -5,19 +5,36 @@ use secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey}; use serde::{Deserialize, Serialize}; use tiny_keccak::{Hasher, Keccak}; +// TODO add chain id to taiko +const CHAIN_ID: [u8; 32] = [0u8; 32]; +//https://github.com/NethermindEth/Taiko-Preconf-AVS/blob/caf9fbbde0dd84947af5a7b26610ffd38525d932/SmartContracts/src/avs/PreconfTaskManager.sol#L175 #[derive(Serialize, Deserialize)] pub struct L2TxListsCommit { + pub block_height: [u8; 32], + pub chain_id: [u8; 32], pub tx_list_bytes: Vec, - pub parent_meta_hash: [u8; 32], - pub block_height: u64, } impl L2TxListsCommit { pub fn new(reply: &RPCReplyL2TxLists, block_height: u64) -> Self { + let block_height_bytes = block_height.to_le_bytes(); // Convert u64 to a [u8; 8] array + let mut block_height = [0u8; 32]; + block_height[24..].copy_from_slice(&block_height_bytes); L2TxListsCommit { + block_height, + chain_id: CHAIN_ID, tx_list_bytes: reply.tx_list_bytes[0].clone(), // TODO check for other indexes - parent_meta_hash: reply.parent_meta_hash, + } + } + + pub fn from_preconf(block_height: u64, tx_list_bytes: Vec) -> Self { + let block_height_bytes = block_height.to_le_bytes(); // Convert u64 to a [u8; 8] array + let mut block_height = [0u8; 32]; + block_height[24..].copy_from_slice(&block_height_bytes); + L2TxListsCommit { block_height, + chain_id: CHAIN_ID, + tx_list_bytes, } } } @@ -49,8 +66,8 @@ mod tests { fn test_hash() { let commit = L2TxListsCommit { tx_list_bytes: vec![1, 2, 3, 4, 5], - parent_meta_hash: [0u8; 32], - block_height: 1, + chain_id: [0u8; 32], + block_height: [0u8; 32], }; let hash_result = commit.hash(); @@ -61,10 +78,12 @@ mod tests { #[test] fn test_sign() { + let mut block_height = [0u8; 32]; + block_height[31] = 1; let commit = L2TxListsCommit { tx_list_bytes: vec![1, 2, 3, 4, 5], - parent_meta_hash: [0u8; 32], - block_height: 1, + chain_id: [0u8; 32], + block_height, }; let private_key = "c87509a1c067bbde78beb793e6fa950b8d9c7f7bd5a8b16bf0d3a1a5b9bdfd3b"; diff --git a/Node/src/utils/preconfirmation_message.rs b/Node/src/utils/preconfirmation_message.rs index 0c7f52b..f787355 100644 --- a/Node/src/utils/preconfirmation_message.rs +++ b/Node/src/utils/preconfirmation_message.rs @@ -6,6 +6,7 @@ use serde_json::Value; pub struct PreconfirmationMessage { pub block_height: u64, pub tx_lists: Value, + pub tx_list_bytes: Vec, pub gas_used: u64, pub proof: PreconfirmationProof, }