use revm::primitives::{Address, U256};
pub const STAKING_ADDRESS: Address = Address::new([
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00,
]);
pub mod namespace {
pub const CONSENSUS_STAKE: u8 = 0x04;
pub const SNAPSHOT_STAKE: u8 = 0x05;
pub const VAL_ID_SECP: u8 = 0x06;
pub const VAL_ID_BLS: u8 = 0x07;
pub const VAL_BITSET: u8 = 0x08;
pub const VAL_EXECUTION: u8 = 0x09;
pub const ACCUMULATOR: u8 = 0x0A;
pub const DELEGATOR: u8 = 0x0B;
pub const WITHDRAWAL_REQUEST: u8 = 0x0C;
}
pub mod global_slots {
use revm::primitives::U256;
pub const EPOCH: U256 = U256::from_limbs([1, 0, 0, 0]);
pub const IN_BOUNDARY: U256 = U256::from_limbs([2, 0, 0, 0]);
pub const LAST_VAL_ID: U256 = U256::from_limbs([3, 0, 0, 0]);
pub const PROPOSER_VAL_ID: U256 = U256::from_limbs([4, 0, 0, 0]);
}
pub mod valset_slots {
use revm::primitives::U256;
pub const EXECUTION: U256 = U256::from_be_slice(&[
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]);
pub const CONSENSUS: U256 = U256::from_be_slice(&[
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]);
pub const SNAPSHOT: U256 = U256::from_be_slice(&[
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]);
}
pub mod validator_offsets {
pub const STAKE: u8 = 0;
pub const ACCUMULATED_REWARD_PER_TOKEN: u8 = 1;
pub const COMMISSION: u8 = 2;
pub const KEYS: u8 = 3;
pub const ADDRESS_FLAGS: u8 = 6;
pub const UNCLAIMED_REWARDS: u8 = 7;
}
pub mod delegator_offsets {
pub const STAKE: u8 = 0;
pub const ACCUMULATED_REWARD_PER_TOKEN: u8 = 1;
pub const REWARDS: u8 = 2;
pub const DELTA_STAKE: u8 = 3;
pub const NEXT_DELTA_STAKE: u8 = 4;
pub const EPOCHS: u8 = 5;
pub const LIST_NODE: u8 = 6;
}
pub mod withdrawal_offsets {
pub const AMOUNT: u8 = 0;
pub const ACCUMULATOR: u8 = 1;
pub const EPOCH: u8 = 2;
}
pub fn validator_key(val_id: u64, slot: u8) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::VAL_EXECUTION;
key[1..9].copy_from_slice(&val_id.to_be_bytes());
U256::from_be_bytes(key) + U256::from(slot)
}
pub fn delegator_key(val_id: u64, delegator: &Address, slot: u8) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::DELEGATOR;
key[1..9].copy_from_slice(&val_id.to_be_bytes());
key[9..29].copy_from_slice(delegator.as_slice());
U256::from_be_bytes(key) + U256::from(slot)
}
pub fn withdrawal_key(val_id: u64, delegator: &Address, withdrawal_id: u8, slot: u8) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::WITHDRAWAL_REQUEST;
key[1..9].copy_from_slice(&val_id.to_be_bytes());
key[9..29].copy_from_slice(delegator.as_slice());
key[29] = withdrawal_id;
U256::from_be_bytes(key) + U256::from(slot)
}
pub fn consensus_view_key(val_id: u64, slot: u8) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::CONSENSUS_STAKE;
key[1..9].copy_from_slice(&val_id.to_be_bytes());
U256::from_be_bytes(key) + U256::from(slot)
}
pub fn snapshot_view_key(val_id: u64, slot: u8) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::SNAPSHOT_STAKE;
key[1..9].copy_from_slice(&val_id.to_be_bytes());
U256::from_be_bytes(key) + U256::from(slot)
}
pub fn accumulator_key(epoch: u64, val_id: u64, slot: u8) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::ACCUMULATOR;
key[1..9].copy_from_slice(&epoch.to_be_bytes());
key[9..17].copy_from_slice(&val_id.to_be_bytes());
U256::from_be_bytes(key) + U256::from(slot)
}
pub fn val_id_secp_key(address: &Address) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::VAL_ID_SECP;
key[1..21].copy_from_slice(address.as_slice());
U256::from_be_bytes(key)
}
pub fn val_id_bls_key(address: &Address) -> U256 {
let mut key = [0u8; 32];
key[0] = namespace::VAL_ID_BLS;
key[1..21].copy_from_slice(address.as_slice());
U256::from_be_bytes(key)
}
pub fn bitset_bucket_key(val_id: u64) -> U256 {
let bucket = val_id >> 8;
let mut key = [0u8; 32];
key[0] = namespace::VAL_BITSET;
let bucket_bytes = bucket.to_be_bytes();
key[1..9].copy_from_slice(&bucket_bytes);
U256::from_be_bytes(key)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_staking_address() {
let expected =
Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0x00]);
assert_eq!(STAKING_ADDRESS, expected);
}
#[test]
fn test_validator_key_format() {
let key = validator_key(1, 0);
let bytes = key.to_be_bytes::<32>();
assert_eq!(bytes[0], namespace::VAL_EXECUTION);
assert_eq!(&bytes[1..9], &1u64.to_be_bytes());
assert_eq!(&bytes[9..32], &[0u8; 23]);
let key_slot6 = validator_key(1, 6);
let bytes6 = key_slot6.to_be_bytes::<32>();
assert_eq!(bytes6[31], 6); }
#[test]
fn test_delegator_key_format() {
let delegator = Address::new([0x11; 20]);
let key = delegator_key(42, &delegator, 2);
let bytes = key.to_be_bytes::<32>();
assert_eq!(bytes[0], namespace::DELEGATOR);
assert_eq!(&bytes[1..9], &42u64.to_be_bytes());
assert_eq!(&bytes[9..29], delegator.as_slice());
assert_eq!(bytes[31], 2);
}
#[test]
fn test_withdrawal_key_format() {
let delegator = Address::new([0x22; 20]);
let key = withdrawal_key(100, &delegator, 5, 1);
let bytes = key.to_be_bytes::<32>();
assert_eq!(bytes[0], namespace::WITHDRAWAL_REQUEST);
assert_eq!(&bytes[1..9], &100u64.to_be_bytes());
assert_eq!(&bytes[9..29], delegator.as_slice());
assert_eq!(bytes[29], 5);
assert_eq!(bytes[31], 1);
}
}