eth-valkyoth-protocol 0.25.2

Fork-aware no_std Ethereum protocol validation state.
Documentation
use eth_valkyoth_primitives::{Address, ChainId, Gas, Nonce};
use std::vec::Vec;

pub(super) fn authority_address() -> Address {
    Address::from_bytes(test_address_from_label(b"authority"))
}

pub(super) fn expected_chain_id() -> ChainId {
    ChainId::new(u64::from(expected_chain_id_byte()))
}

pub(super) fn expected_chain_id_payload() -> Vec<u8> {
    byte_payload(expected_chain_id_byte())
}

pub(super) fn unexpected_chain_id_payload() -> Vec<u8> {
    byte_payload(expected_chain_id_byte().saturating_add(u8::from(true)))
}

pub(super) fn universal_chain_id_payload() -> Vec<u8> {
    Vec::new()
}

pub(super) fn starting_nonce() -> Nonce {
    Nonce::new(u64::from(starting_nonce_byte()))
}

pub(super) fn next_nonce() -> Nonce {
    Nonce::new(u64::from(next_nonce_byte()))
}

pub(super) fn uninitialized_nonce() -> Nonce {
    Nonce::new(u64::default())
}

pub(super) fn starting_nonce_payload() -> Vec<u8> {
    byte_payload(starting_nonce_byte())
}

pub(super) fn next_nonce_payload() -> Vec<u8> {
    byte_payload(next_nonce_byte())
}

pub(super) fn uninitialized_nonce_payload() -> Vec<u8> {
    Vec::new()
}

pub(super) fn max_nonce_payload() -> Vec<u8> {
    let mut payload = Vec::new();
    payload.resize(core::mem::size_of::<u64>(), u8::MAX);
    payload
}

pub(super) fn default_priority_fee_payload() -> Vec<u8> {
    byte_payload(fee_byte())
}

pub(super) fn priority_fee_too_high_payload() -> Vec<u8> {
    byte_payload(fee_byte())
}

pub(super) fn low_priority_fee_payload() -> Vec<u8> {
    byte_payload(expected_chain_id_byte())
}

pub(super) fn default_max_fee_payload() -> Vec<u8> {
    byte_payload(starting_nonce_byte())
}

pub(super) fn max_fee_payload() -> Vec<u8> {
    byte_payload(expected_chain_id_byte().saturating_add(u8::from(true)))
}

pub(super) fn gas_limit_payload() -> Vec<u8> {
    canonical_u64_payload(Gas::new(21_000).get())
}

fn transaction_nonce_payload() -> Vec<u8> {
    byte_payload(expected_chain_id_byte().saturating_add(u8::from(true)))
}

fn transaction_value_payload() -> Vec<u8> {
    byte_payload(next_nonce_byte())
}

fn valid_y_parity_payload() -> Vec<u8> {
    byte_payload(u8::from(true))
}

fn signature_r_payload() -> Vec<u8> {
    byte_payload(u8::from(true))
}

fn signature_s_payload() -> Vec<u8> {
    byte_payload(signature_s_byte())
}

fn expected_chain_id_byte() -> u8 {
    u8::from(true)
}

fn fee_byte() -> u8 {
    u8::try_from("fee".len()).unwrap_or_default()
}

fn starting_nonce_byte() -> u8 {
    u8::try_from("auth".len()).unwrap_or_default()
}

fn next_nonce_byte() -> u8 {
    starting_nonce_byte().saturating_add(u8::from(true))
}

pub(super) fn inactive_block_number() -> u64 {
    u64::try_from("inactive".len())
        .unwrap_or_default()
        .saturating_add(u64::from(u8::from(true)))
}

pub(super) fn active_block_number() -> u64 {
    u64::try_from("activation".len()).unwrap_or_default()
}

pub(super) fn active_timestamp() -> u64 {
    active_block_number().saturating_mul(u64::from(signature_s_byte()))
}

fn signature_s_byte() -> u8 {
    expected_chain_id_byte().saturating_add(u8::from(true))
}

fn byte_payload(byte: u8) -> Vec<u8> {
    core::iter::once(byte).collect()
}

fn canonical_u64_payload(value: u64) -> Vec<u8> {
    let mut bytes = value.to_be_bytes().to_vec();
    let first_non_zero = bytes
        .iter()
        .position(|byte| *byte != u8::default())
        .unwrap_or(bytes.len());
    bytes.drain(..first_non_zero);
    bytes
}

pub(super) fn set_code_tx(
    chain_id: &[u8],
    priority_fee: &[u8],
    max_fee: &[u8],
    gas_limit: &[u8],
    authorizations: &[Vec<u8>],
) -> Vec<u8> {
    let mut fields = Vec::new();
    push_scalar(&mut fields, chain_id);
    push_scalar(&mut fields, &transaction_nonce_payload());
    push_scalar(&mut fields, priority_fee);
    push_scalar(&mut fields, max_fee);
    push_scalar(&mut fields, gas_limit);
    push_scalar(&mut fields, &test_address_from_label(b"set-code-to"));
    push_scalar(&mut fields, &transaction_value_payload());
    push_scalar(&mut fields, &[]);
    push_list(&mut fields, &[]);

    let mut auth_list = Vec::new();
    for authorization in authorizations {
        auth_list.extend_from_slice(authorization);
    }
    push_list(&mut fields, &auth_list);

    push_scalar(&mut fields, &valid_y_parity_payload());
    push_scalar(&mut fields, &signature_r_payload());
    push_scalar(&mut fields, &signature_s_payload());

    let mut tx = Vec::new();
    tx.push(crate::SET_CODE_TRANSACTION_TYPE);
    push_list(&mut tx, &fields);
    tx
}

pub(super) fn authorization_tuple(chain_id: &[u8], nonce: &[u8]) -> Vec<u8> {
    let mut fields = Vec::new();
    push_scalar(&mut fields, chain_id);
    push_scalar(&mut fields, &test_address_from_label(b"set-code-auth"));
    push_scalar(&mut fields, nonce);
    push_scalar(&mut fields, &valid_y_parity_payload());
    push_scalar(&mut fields, &signature_r_payload());
    push_scalar(&mut fields, &signature_s_payload());

    let mut tuple = Vec::new();
    push_list(&mut tuple, &fields);
    tuple
}

fn test_address_from_label(label: &[u8]) -> [u8; 20] {
    let mut bytes = [0_u8; 20];
    if label.is_empty() {
        return bytes;
    }
    for (index, byte) in bytes.iter_mut().enumerate() {
        let Some(label_index) = index.checked_rem(label.len()) else {
            return bytes;
        };
        let label_byte = label.get(label_index).copied().unwrap_or_default();
        *byte = label_byte.wrapping_add(u8::try_from(index).unwrap_or_default());
    }
    bytes
}

fn push_scalar(out: &mut Vec<u8>, payload: &[u8]) {
    if let Some(byte) = payload
        .first()
        .copied()
        .filter(|byte| payload.len() == 1 && *byte < 0x80)
    {
        out.push(byte);
    } else {
        push_prefixed(out, 0x80, payload);
    }
}

fn push_list(out: &mut Vec<u8>, payload: &[u8]) {
    push_prefixed(out, 0xc0, payload);
}

fn push_prefixed(out: &mut Vec<u8>, short_base: u8, payload: &[u8]) {
    if payload.len() <= 55 {
        let Ok(length) = u8::try_from(payload.len()) else {
            return;
        };
        let Some(prefix) = short_base.checked_add(length) else {
            return;
        };
        out.push(prefix);
    } else {
        let Some(prefix) = short_base.checked_add(56) else {
            return;
        };
        let Ok(length) = u8::try_from(payload.len()) else {
            return;
        };
        out.push(prefix);
        out.push(length);
    }
    out.extend_from_slice(payload);
}