Skip to content

eth-wire signature propagation #329

@frisitano

Description

@frisitano

Describe the feature

ScrollNetworkBuilder

We need the reth network to have access to the rollup-node Database. As such, we should introduce an Arc<Database> in the ScrollNetworkBuilder.

/// The network builder for Scroll.
#[derive(Debug, Default)]
pub struct ScrollNetworkBuilder {
/// Additional `RLPx` sub-protocols to be added to the network.
scroll_sub_protocols: RlpxSubProtocols,
}
impl ScrollNetworkBuilder {
/// Create a new [`ScrollNetworkBuilder`] with default configuration.
pub fn new() -> Self {
Self { scroll_sub_protocols: RlpxSubProtocols::default() }
}

This should become something like:

/// The network builder for Scroll.
#[derive(Debug, Default)]
pub struct ScrollNetworkBuilder {
    /// Additional `RLPx` sub-protocols to be added to the network.
    scroll_sub_protocols: RlpxSubProtocols,
    /// A reference to the rollup-node `Database`.
    rollup_node_db: Arc<Database>,
}

impl ScrollNetworkBuilder {
    /// Create a new [`ScrollNetworkBuilder`] with default configuration.
    pub fn new(database: Arc<Database>) -> Self {
        Self { scroll_sub_protocols: RlpxSubProtocols::default(), rollup_node_db: database }
    }

The Database type should be sourced from here.

Received block header transformation

We should then modify the header transformation to be something like this:

/// An implementation of a [`HeaderTransform`] for Scroll.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct ScrollHeaderTransform<ChainSpec> {
chain_spec: ChainSpec,
}
impl<ChainSpec: ScrollHardforks + Debug + Send + Sync + 'static> ScrollHeaderTransform<ChainSpec> {
/// Returns a new instance of the [`ScrollHeaderTransform`] from the provider chain spec.
pub const fn new(chain_spec: ChainSpec) -> Self {
Self { chain_spec }
}
/// Returns a new [`ScrollHeaderTransform`] as a [`HeaderTransform`] trait object.
pub fn boxed<H: BlockHeader>(chain_spec: ChainSpec) -> Box<dyn HeaderTransform<H>> {
Box::new(Self { chain_spec })
}
}
impl<H: BlockHeader, ChainSpec: ScrollHardforks + Debug + Send + Sync> HeaderTransform<H>
for ScrollHeaderTransform<ChainSpec>
{
fn map(&self, mut header: H) -> H {
if self.chain_spec.is_euclid_v2_active_at_timestamp(header.timestamp()) {
// clear the extra data field.
*header.extra_data_mut() = Default::default()
}
header
}
}

// This is the incorrect type please find the correct type in the context.
const SCROLL_SIGNER: PublicKey = PublicKey::from_hex("...");
/// An implementation of a [`HeaderTransform`] for Scroll.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct ScrollHeaderTransform<ChainSpec> {
    chain_spec: ChainSpec,
    db: Arc<Database>,
}

impl<ChainSpec: ScrollHardforks + Debug + Send + Sync + 'static> ScrollHeaderTransform<ChainSpec> {
    /// Returns a new instance of the [`ScrollHeaderTransform`] from the provider chain spec.
    pub const fn new(chain_spec: ChainSpec, db: Arc<Database>) -> Self {
        Self { chain_spec, db }
    }

    /// Returns a new [`ScrollHeaderTransform`] as a [`HeaderTransform`] trait object.
    pub fn boxed<H: BlockHeader>(chain_spec: ChainSpec, db: Arc<Database>) -> Box<dyn HeaderTransform<H>> {
        Box::new(Self { chain_spec, db })
    }
}

impl<H: BlockHeader, ChainSpec: ScrollHardforks + Debug + Send + Sync> HeaderTransform<H>
    for ScrollHeaderTransform<ChainSpec>
{
    fn map(&self, mut header: H) -> H {
        if self.chain_spec.is_euclid_v2_active_at_timestamp(header.timestamp()) {
            // clear the extra data field.
            let signaturue = std::mem::take(header.extra_data_mut());
            if signature.verify(SCROLL_SIGNER).expect("Signature verification failed") {
                self.db.insert_signature(header.hash_slow(), signature);
            }
        }
        header
    }
}

Sent Block Header Transformation

In a similar way to how we have introduced the transformation struct for received headers. We should introduce a type that transforms the block header responses sent over the eth-wire protocol. This transform should read the signature from the database and add it to the extra_data field.

The transformer should be included here:

/// Returns the list of requested headers
fn get_headers_response(&self, request: GetBlockHeaders) -> Vec<C::Header> {
let GetBlockHeaders { start_block, limit, skip, direction } = request;
let mut headers = Vec::new();
let mut block: BlockHashOrNumber = match start_block {
BlockHashOrNumber::Hash(start) => start.into(),
BlockHashOrNumber::Number(num) => {
let Some(hash) = self.client.block_hash(num).unwrap_or_default() else {
return headers
};
hash.into()
}
};
let skip = skip as u64;
let mut total_bytes = 0;
for _ in 0..limit {
if let Some(header) = self.client.header_by_hash_or_number(block).unwrap_or_default() {
let number = header.number();
let parent_hash = header.parent_hash();
total_bytes += header.length();
headers.push(header);
if headers.len() >= MAX_HEADERS_SERVE || total_bytes > SOFT_RESPONSE_LIMIT {
break
}

Additional context

No response

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions