zksync_node_api_server 29.13.0-non-semver-compat

ZKsync API server
use zksync_dal::{Connection, Core, CoreDal, DalError};
use zksync_system_constants::{
    message_root::{CHAIN_COUNT_KEY, CHAIN_INDEX_TO_ID_KEY, CHAIN_TREE_KEY},
    L2_MESSAGE_ROOT_ADDRESS,
};
use zksync_types::{
    h256_to_u256, l2_to_l1_log::CHAIN_ID_LEAF_PADDING, u256_to_h256, web3::keccak256,
    AccountTreeId, L2BlockNumber, StorageKey, H256, U256,
};
use zksync_web3_decl::error::Web3Error;

pub(super) async fn get_chain_count(
    connection: &mut Connection<'_, Core>,
    block_number: L2BlockNumber,
) -> anyhow::Result<u8> {
    let chain_count_key = CHAIN_COUNT_KEY;
    let chain_count_storage_key =
        message_root_log_key(H256::from_low_u64_be(chain_count_key as u64));
    let chain_count = connection
        .storage_web3_dal()
        .get_historical_value_unchecked(chain_count_storage_key.hashed_key(), block_number)
        .await
        .map_err(DalError::generalize)?;
    if h256_to_u256(chain_count) > u8::MAX.into() {
        anyhow::bail!("Chain count doesn't fit in `u8`");
    }
    Ok(chain_count.0[31])
}

pub(super) async fn get_chain_id_from_index(
    connection: &mut Connection<'_, Core>,
    chain_index: u8,
    block_number: L2BlockNumber,
) -> Result<H256, Web3Error> {
    let key = H256::from_slice(&keccak256(
        &[
            H256::from_low_u64_be(chain_index as u64).0,
            H256::from_low_u64_be(CHAIN_INDEX_TO_ID_KEY as u64).0,
        ]
        .concat(),
    ));
    let storage_key = message_root_log_key(key);
    let chain_id = connection
        .storage_web3_dal()
        .get_historical_value_unchecked(storage_key.hashed_key(), block_number)
        .await
        .map_err(DalError::generalize)?;
    Ok(chain_id)
}

pub(super) async fn get_chain_root_from_id(
    connection: &mut Connection<'_, Core>,
    chain_id: H256,
    block_number: L2BlockNumber,
) -> Result<H256, Web3Error> {
    let chain_tree_key = H256::from_slice(&keccak256(
        &[chain_id.0, H256::from_low_u64_be(CHAIN_TREE_KEY as u64).0].concat(),
    ));
    let chain_sides_len_key =
        u256_to_h256(h256_to_u256(chain_tree_key).overflowing_add(U256::one()).0);
    let chain_sides_len_storage_key = message_root_log_key(chain_sides_len_key);
    let chain_sides_len = connection
        .storage_web3_dal()
        .get_historical_value_unchecked(chain_sides_len_storage_key.hashed_key(), block_number)
        .await
        .map_err(DalError::generalize)?;

    let last_element_pos = {
        let length = h256_to_u256(chain_sides_len);
        assert!(
            length > U256::zero(),
            "_sides.length is zero, chain is not registered"
        );

        length - 1
    };
    let sides_data_start_key = H256(keccak256(chain_sides_len_key.as_bytes()));
    let chain_root_key = h256_to_u256(sides_data_start_key)
        .overflowing_add(last_element_pos)
        .0;
    let chain_root_storage_key = message_root_log_key(u256_to_h256(chain_root_key));
    let chain_root = connection
        .storage_web3_dal()
        .get_historical_value_unchecked(chain_root_storage_key.hashed_key(), block_number)
        .await
        .map_err(DalError::generalize)?;
    Ok(chain_root)
}

pub(super) fn chain_id_leaf_preimage(chain_root: H256, chain_id: H256) -> [u8; 96] {
    let mut full_preimage = [0u8; 96];

    full_preimage[0..32].copy_from_slice(CHAIN_ID_LEAF_PADDING.as_bytes());
    full_preimage[32..64].copy_from_slice(&chain_root.0);
    full_preimage[64..96].copy_from_slice(&chain_id.0);

    full_preimage
}

fn message_root_log_key(key: H256) -> StorageKey {
    let message_root = AccountTreeId::new(L2_MESSAGE_ROOT_ADDRESS);
    StorageKey::new(message_root, key)
}