661ef65de8
* Add intermediate structures for bytes conversion * Expose byte conversion methods from `Eth1Service` * Add eth1 ssz containers * Fix type errors * Load eth1 cache on restart * Fix compile errors * Update Cargo.lock * Add comments and minor formatting * Add test for eth1 cache persistence * Restrict Deposit and Block cache field visibility * Add checks * Fix `SszDepositCache` check * Implement Encode/Decode directly on `BlockCache`
109 lines
5.3 KiB
Rust
109 lines
5.3 KiB
Rust
use super::http::Log;
|
|
use ssz::Decode;
|
|
use ssz_derive::{Decode, Encode};
|
|
use types::{DepositData, Hash256, PublicKeyBytes, SignatureBytes};
|
|
|
|
/// The following constants define the layout of bytes in the deposit contract `DepositEvent`. The
|
|
/// event bytes are formatted according to the Ethereum ABI.
|
|
const PUBKEY_START: usize = 192;
|
|
const PUBKEY_LEN: usize = 48;
|
|
const CREDS_START: usize = PUBKEY_START + 64 + 32;
|
|
const CREDS_LEN: usize = 32;
|
|
const AMOUNT_START: usize = CREDS_START + 32 + 32;
|
|
const AMOUNT_LEN: usize = 8;
|
|
const SIG_START: usize = AMOUNT_START + 32 + 32;
|
|
const SIG_LEN: usize = 96;
|
|
const INDEX_START: usize = SIG_START + 96 + 32;
|
|
const INDEX_LEN: usize = 8;
|
|
|
|
/// A fully parsed eth1 deposit contract log.
|
|
#[derive(Debug, PartialEq, Clone, Encode, Decode)]
|
|
pub struct DepositLog {
|
|
pub deposit_data: DepositData,
|
|
/// The block number of the log that included this `DepositData`.
|
|
pub block_number: u64,
|
|
/// The index included with the deposit log.
|
|
pub index: u64,
|
|
}
|
|
|
|
impl DepositLog {
|
|
/// Attempts to parse a raw `Log` from the deposit contract into a `DepositLog`.
|
|
pub fn from_log(log: &Log) -> Result<Self, String> {
|
|
let bytes = &log.data;
|
|
|
|
let pubkey = bytes
|
|
.get(PUBKEY_START..PUBKEY_START + PUBKEY_LEN)
|
|
.ok_or_else(|| "Insufficient bytes for pubkey".to_string())?;
|
|
let withdrawal_credentials = bytes
|
|
.get(CREDS_START..CREDS_START + CREDS_LEN)
|
|
.ok_or_else(|| "Insufficient bytes for withdrawal credential".to_string())?;
|
|
let amount = bytes
|
|
.get(AMOUNT_START..AMOUNT_START + AMOUNT_LEN)
|
|
.ok_or_else(|| "Insufficient bytes for amount".to_string())?;
|
|
let signature = bytes
|
|
.get(SIG_START..SIG_START + SIG_LEN)
|
|
.ok_or_else(|| "Insufficient bytes for signature".to_string())?;
|
|
let index = bytes
|
|
.get(INDEX_START..INDEX_START + INDEX_LEN)
|
|
.ok_or_else(|| "Insufficient bytes for index".to_string())?;
|
|
|
|
let deposit_data = DepositData {
|
|
pubkey: PublicKeyBytes::from_ssz_bytes(pubkey)
|
|
.map_err(|e| format!("Invalid pubkey ssz: {:?}", e))?,
|
|
withdrawal_credentials: Hash256::from_ssz_bytes(withdrawal_credentials)
|
|
.map_err(|e| format!("Invalid withdrawal_credentials ssz: {:?}", e))?,
|
|
amount: u64::from_ssz_bytes(amount)
|
|
.map_err(|e| format!("Invalid amount ssz: {:?}", e))?,
|
|
signature: SignatureBytes::from_ssz_bytes(signature)
|
|
.map_err(|e| format!("Invalid signature ssz: {:?}", e))?,
|
|
};
|
|
|
|
Ok(DepositLog {
|
|
deposit_data,
|
|
block_number: log.block_number,
|
|
index: u64::from_ssz_bytes(index).map_err(|e| format!("Invalid index ssz: {:?}", e))?,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub mod tests {
|
|
use super::*;
|
|
use crate::http::Log;
|
|
|
|
/// The data from a deposit event, using the v0.8.3 version of the deposit contract.
|
|
pub const EXAMPLE_LOG: &[u8] = &[
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 167, 108, 6, 69, 88, 17, 3, 51, 6, 4, 158, 232, 82,
|
|
248, 218, 2, 71, 219, 55, 102, 86, 125, 136, 203, 36, 77, 64, 213, 43, 52, 175, 154, 239,
|
|
50, 142, 52, 201, 77, 54, 239, 0, 229, 22, 46, 139, 120, 62, 240, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 64, 89, 115, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 140, 74, 175, 158, 209, 20, 206,
|
|
30, 63, 215, 238, 113, 60, 132, 216, 211, 100, 186, 202, 71, 34, 200, 160, 225, 212, 213,
|
|
119, 88, 51, 80, 101, 74, 2, 45, 78, 153, 12, 192, 44, 51, 77, 40, 10, 72, 246, 34, 193,
|
|
187, 22, 95, 4, 211, 245, 224, 13, 162, 21, 163, 54, 225, 22, 124, 3, 56, 14, 81, 122, 189,
|
|
149, 250, 251, 159, 22, 77, 94, 157, 197, 196, 253, 110, 201, 88, 193, 246, 136, 226, 221,
|
|
18, 113, 232, 105, 100, 114, 103, 237, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
];
|
|
|
|
#[test]
|
|
fn can_parse_example_log() {
|
|
let log = Log {
|
|
block_number: 42,
|
|
data: EXAMPLE_LOG.to_vec(),
|
|
};
|
|
DepositLog::from_log(&log).expect("should decode log");
|
|
}
|
|
}
|