Skip to content

Commit

Permalink
feat(beacon-network): add json-rpc method to get the latest finalized…
Browse files Browse the repository at this point in the history
… root (ethereum#1364)
  • Loading branch information
ogenev committed Aug 12, 2024
1 parent e7a534d commit 61f06ba
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 10 deletions.
86 changes: 86 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions trin-beacon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description = "Beacon network subprotocol for Trin."
authors = ["https://github.com/ethereum/trin/graphs/contributors"]

[dependencies]
alloy-primitives = "0.7.0"
anyhow = "1.0.68"
chrono = "0.4.38"
discv5 = { version = "0.4.1", features = ["serde"] }
Expand All @@ -30,6 +31,8 @@ trin-metrics = { path = "../trin-metrics" }
trin-storage = { path = "../trin-storage" }
trin-validation = { path = "../trin-validation" }
utp-rs = { git = "https://github.com/ethereum/utp", tag = "v0.1.0-alpha.13" }
mockall = "0.13.0"
mockall_double = "0.3.1"

[dev-dependencies]
serde_yaml = "0.9.33"
Expand Down
2 changes: 1 addition & 1 deletion trin-beacon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ mod sync;
mod test_utils;
pub mod validation;

use mockall_double::double;
use std::sync::Arc;

use tokio::{
sync::{broadcast, mpsc, RwLock},
task::JoinHandle,
Expand Down
3 changes: 1 addition & 2 deletions trin-beacon/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::sync::Arc;

use parking_lot::RwLock as PLRwLock;
use std::sync::Arc;
use tokio::sync::{Mutex, RwLock};
use tracing::error;
use utp_rs::socket::UtpSocket;
Expand Down
48 changes: 41 additions & 7 deletions trin-beacon/src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use alloy_primitives::B256;
use anyhow::anyhow;
use chrono::Duration;
use ssz::Decode;
use std::sync::Arc;

use ethportal_api::{
consensus::fork::ForkName,
types::content_value::beacon::{
Expand All @@ -13,9 +11,13 @@ use ethportal_api::{
BeaconContentKey,
};
use light_client::consensus::rpc::portal_rpc::expected_current_slot;
use mockall_double::double;
use ssz::{Decode, Encode};
use std::sync::Arc;
use tokio::sync::RwLock;

use trin_validation::{
merkle::proof::verify_merkle_proof,
oracle::HeaderOracle,
validator::{ValidationResult, Validator},
};
Expand Down Expand Up @@ -157,7 +159,34 @@ impl Validator<BeaconContentKey> for BeaconValidator {
));
}

// TODO: Validate the historical summaries with proof against current state root
// Verify the historical summaries against the latest finalized state root
let latest_finalized_root = self
.header_oracle
.read()
.await
.get_finalized_state_root()
.await?;
let historical_summaries_state_proof = fork_versioned_historical_summaries
.historical_summaries_with_proof
.proof;
let historical_summaries_root = fork_versioned_historical_summaries
.historical_summaries_with_proof
.historical_summaries
.as_ssz_bytes();
let historical_summaries_root = B256::try_from(&historical_summaries_root[..])
.map_err(|err| anyhow!("Invalid historical summaries root: {:?}", err))?;

if !verify_merkle_proof(
historical_summaries_root,
&historical_summaries_state_proof,
5,
59, // 31 + 28 = 59
latest_finalized_root,
) {
return Err(anyhow!(
"Merkle proof validation failed for HistoricalSummariesProof"
));
}
}
}

Expand Down Expand Up @@ -347,11 +376,16 @@ mod tests {
"Light client optimistic update is not from the recent fork. Expected deneb, got capella"
);
}

#[tokio::test]
async fn test_validate_historical_summaries_with_proof() {
let validator = BeaconValidator {
header_oracle: Arc::new(RwLock::new(HeaderOracle::default())),
};
let mut mock_oracle = MockHeaderOracle::new();
mock_oracle
.expect_get_finalized_state_root()
.returning(|| Ok(B256::from_slice(&[0x12, 0x34])));
let header_oracle = Arc::new(RwLock::new(mock_oracle));
let validator = BeaconValidator { header_oracle };

let summaries_with_proof = test_utils::get_history_summaries_with_proof();
let content = summaries_with_proof.as_ssz_bytes();
let content_key =
Expand Down
1 change: 1 addition & 0 deletions trin-validation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ ssz_types = { git = "https://github.com/KolbyML/ssz_types.git", rev = "2a5922de7
tokio = { version = "1.14.0", features = ["full"] }
tree_hash = { git = "https://github.com/KolbyML/tree_hash.git", rev = "8aaf8bb4184148768d48e2cfbbdd0b95d1da8730" }
tree_hash_derive = { git = "https://github.com/KolbyML/tree_hash.git", rev = "8aaf8bb4184148768d48e2cfbbdd0b95d1da8730" }
mockall = "0.13.0"

[dev-dependencies]
alloy-rlp = "0.3.4"
Expand Down
19 changes: 19 additions & 0 deletions trin-validation/src/oracle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use alloy_primitives::B256;
use anyhow::anyhow;
use enr::NodeId;
use mockall::{automock, mock};
use serde_json::Value;
use tokio::sync::mpsc;

Expand Down Expand Up @@ -177,6 +178,24 @@ impl HeaderOracle {

Ok(enr)
}

/// Return latest finalized root of the beacon state.
pub async fn get_finalized_state_root(&self) -> anyhow::Result<B256> {
let endpoint = BeaconEndpoint::FinalizedStateRoot;
let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
let request = BeaconJsonRpcRequest { endpoint, resp };
let tx = self.beacon_jsonrpc_tx()?;
tx.send(request)?;

let state_root = match resp_rx.recv().await {
Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
None => return Err(anyhow!("No response from Beacon network")),
};

let state_root: B256 = serde_json::from_value(state_root)?;

Ok(state_root)
}
}

#[cfg(test)]
Expand Down

0 comments on commit 61f06ba

Please sign in to comment.