mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-17 03:42:46 +00:00
## Issue Addressed Resolves #3015 ## Proposed Changes Add JWT token based authentication to engine api requests. The jwt secret key is read from the provided file and is used to sign tokens that are used for authenticated communication with the EL node. - [x] Interop with geth (synced `merge-devnet-4` with the `merge-kiln-v2` branch on geth) - [x] Interop with other EL clients (nethermind on `merge-devnet-4`) - [x] ~Implement `zeroize` for jwt secrets~ - [x] Add auth server tests with `mock_execution_layer` - [x] Get auth working with the `execution_engine_integration` tests Co-authored-by: Paul Hauner <paul@paulhauner.com>
145 lines
3.7 KiB
Rust
145 lines
3.7 KiB
Rust
use async_trait::async_trait;
|
|
use eth1::http::RpcError;
|
|
use reqwest::StatusCode;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
pub const LATEST_TAG: &str = "latest";
|
|
|
|
use crate::engines::ForkChoiceState;
|
|
pub use json_structures::TransitionConfigurationV1;
|
|
pub use types::{Address, EthSpec, ExecutionBlockHash, ExecutionPayload, Hash256, Uint256};
|
|
|
|
pub mod auth;
|
|
pub mod http;
|
|
pub mod json_structures;
|
|
|
|
pub type PayloadId = [u8; 8];
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
Reqwest(reqwest::Error),
|
|
Auth(auth::Error),
|
|
BadResponse(String),
|
|
RequestFailed(String),
|
|
InvalidExecutePayloadResponse(&'static str),
|
|
JsonRpc(RpcError),
|
|
Json(serde_json::Error),
|
|
ServerMessage { code: i64, message: String },
|
|
Eip155Failure,
|
|
IsSyncing,
|
|
ExecutionBlockNotFound(ExecutionBlockHash),
|
|
ExecutionHeadBlockNotFound,
|
|
ParentHashEqualsBlockHash(ExecutionBlockHash),
|
|
PayloadIdUnavailable,
|
|
TransitionConfigurationMismatch,
|
|
}
|
|
|
|
impl From<reqwest::Error> for Error {
|
|
fn from(e: reqwest::Error) -> Self {
|
|
if matches!(
|
|
e.status(),
|
|
Some(StatusCode::UNAUTHORIZED) | Some(StatusCode::FORBIDDEN)
|
|
) {
|
|
Error::Auth(auth::Error::InvalidToken)
|
|
} else {
|
|
Error::Reqwest(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::Error> for Error {
|
|
fn from(e: serde_json::Error) -> Self {
|
|
Error::Json(e)
|
|
}
|
|
}
|
|
|
|
impl From<auth::Error> for Error {
|
|
fn from(e: auth::Error) -> Self {
|
|
Error::Auth(e)
|
|
}
|
|
}
|
|
|
|
/// A generic interface for an execution engine API.
|
|
#[async_trait]
|
|
pub trait EngineApi {
|
|
async fn upcheck(&self) -> Result<(), Error>;
|
|
|
|
async fn get_block_by_number<'a>(
|
|
&self,
|
|
block_by_number: BlockByNumberQuery<'a>,
|
|
) -> Result<Option<ExecutionBlock>, Error>;
|
|
|
|
async fn get_block_by_hash<'a>(
|
|
&self,
|
|
block_hash: ExecutionBlockHash,
|
|
) -> Result<Option<ExecutionBlock>, Error>;
|
|
|
|
async fn new_payload_v1<T: EthSpec>(
|
|
&self,
|
|
execution_payload: ExecutionPayload<T>,
|
|
) -> Result<PayloadStatusV1, Error>;
|
|
|
|
async fn get_payload_v1<T: EthSpec>(
|
|
&self,
|
|
payload_id: PayloadId,
|
|
) -> Result<ExecutionPayload<T>, Error>;
|
|
|
|
async fn forkchoice_updated_v1(
|
|
&self,
|
|
forkchoice_state: ForkChoiceState,
|
|
payload_attributes: Option<PayloadAttributes>,
|
|
) -> Result<ForkchoiceUpdatedResponse, Error>;
|
|
|
|
async fn exchange_transition_configuration_v1(
|
|
&self,
|
|
transition_configuration: TransitionConfigurationV1,
|
|
) -> Result<TransitionConfigurationV1, Error>;
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum PayloadStatusV1Status {
|
|
Valid,
|
|
Invalid,
|
|
Syncing,
|
|
Accepted,
|
|
InvalidBlockHash,
|
|
InvalidTerminalBlock,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct PayloadStatusV1 {
|
|
pub status: PayloadStatusV1Status,
|
|
pub latest_valid_hash: Option<ExecutionBlockHash>,
|
|
pub validation_error: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
|
|
#[serde(untagged)]
|
|
pub enum BlockByNumberQuery<'a> {
|
|
Tag(&'a str),
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ExecutionBlock {
|
|
#[serde(rename = "hash")]
|
|
pub block_hash: ExecutionBlockHash,
|
|
#[serde(rename = "number", with = "eth2_serde_utils::u64_hex_be")]
|
|
pub block_number: u64,
|
|
pub parent_hash: ExecutionBlockHash,
|
|
pub total_difficulty: Uint256,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct PayloadAttributes {
|
|
pub timestamp: u64,
|
|
pub prev_randao: Hash256,
|
|
pub suggested_fee_recipient: Address,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct ForkchoiceUpdatedResponse {
|
|
pub payload_status: PayloadStatusV1,
|
|
pub payload_id: Option<PayloadId>,
|
|
}
|