-
Notifications
You must be signed in to change notification settings - Fork 0
Simplify Contract, accept direct RPC input #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9ceb8bb
f664766
b0d2c42
20c5bff
a00dff4
987abf1
abcab71
6f854e4
a9d1339
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,74 @@ arr_wrapper_impl_tree_hash_and_borsh!(PublicKeyBytes, PUBLIC_KEY_BYTES_LEN); | |
arr_wrapper_impl_tree_hash_and_borsh!(SignatureBytes, SIGNATURE_BYTES_LEN); | ||
arr_wrapper_impl_tree_hash_and_borsh!(SyncCommitteeBits, SYNC_COMMITTEE_BITS_SIZE_IN_BYTES); | ||
|
||
#[derive(Debug, Clone, BorshSchema)] | ||
pub struct ExtraData(pub Vec<u8>); | ||
|
||
impl tree_hash::TreeHash for ExtraData { | ||
fn tree_hash_type() -> tree_hash::TreeHashType { | ||
tree_hash::TreeHashType::List | ||
} | ||
|
||
fn tree_hash_packed_encoding(&self) -> tree_hash::PackedEncoding { | ||
unreachable!("List should never be packed.") | ||
} | ||
|
||
fn tree_hash_packing_factor() -> usize { | ||
unreachable!("List should never be packed.") | ||
} | ||
|
||
fn tree_hash_root(&self) -> tree_hash::Hash256 { | ||
let mut hasher = | ||
tree_hash::MerkleHasher::with_leaves(self.0.len().div_ceil(tree_hash::BYTES_PER_CHUNK)); | ||
|
||
for item in &self.0 { | ||
hasher.write(&item.tree_hash_packed_encoding()).unwrap(); | ||
} | ||
|
||
let root = hasher.finish().unwrap(); | ||
tree_hash::mix_in_length(&root, self.0.len()) | ||
} | ||
} | ||
|
||
// Add Borsh implementations | ||
impl borsh::BorshSerialize for ExtraData { | ||
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { | ||
BorshSerialize::serialize(&self.0, writer) | ||
} | ||
} | ||
|
||
impl borsh::BorshDeserialize for ExtraData { | ||
fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> { | ||
Ok(ExtraData(Vec::<u8>::deserialize_reader(reader)?)) | ||
} | ||
} | ||
|
||
#[cfg(not(target_arch = "wasm32"))] | ||
impl serde::Serialize for ExtraData { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: serde::Serializer, | ||
{ | ||
// Always serialize as hex string | ||
let hex_string = format!("0x{}", hex::encode(&self.0)); | ||
serializer.serialize_str(&hex_string) | ||
} | ||
} | ||
|
||
#[cfg(not(target_arch = "wasm32"))] | ||
impl<'de> serde::Deserialize<'de> for ExtraData { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
{ | ||
let hex_string = <std::string::String as Deserialize>::deserialize(deserializer)?; | ||
let hex_string = hex_string.strip_prefix("0x").unwrap_or(&hex_string); | ||
let bytes = hex::decode(hex_string) | ||
.map_err(|e| serde::de::Error::custom(format!("Invalid hex: {}", e)))?; | ||
Ok(ExtraData(bytes)) | ||
} | ||
} | ||
|
||
#[derive( | ||
Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize, tree_hash_derive::TreeHash, | ||
)] | ||
|
@@ -43,18 +111,62 @@ pub struct BeaconBlockHeader { | |
pub body_root: H256, | ||
} | ||
|
||
// New execution header structure for Electra | ||
#[derive( | ||
Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize, tree_hash_derive::TreeHash, | ||
)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct ExecutionHeader { | ||
pub parent_hash: H256, | ||
pub fee_recipient: H160, | ||
pub state_root: H256, | ||
pub receipts_root: H256, | ||
pub logs_bloom: Bloom, | ||
pub prev_randao: H256, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub block_number: u64, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub gas_limit: u64, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub gas_used: u64, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub timestamp: u64, | ||
pub extra_data: ExtraData, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub base_fee_per_gas: u64, | ||
pub block_hash: H256, | ||
pub transactions_root: H256, | ||
pub withdrawals_root: H256, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub blob_gas_used: u64, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub excess_blob_gas: u64, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How will we handle optional fields that may be added after the new network upgrade? or, for example, if we want to run the tests for blocks without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's why the specs have this weird implementation for get_lc_execution_root |
||
} | ||
|
||
// New combined header structure | ||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct AttestedHeader { | ||
pub beacon: BeaconBlockHeader, | ||
pub execution: ExecutionHeader, | ||
pub execution_branch: Vec<H256>, | ||
} | ||
|
||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct FinalizedHeader { | ||
pub beacon: BeaconBlockHeader, | ||
pub execution: ExecutionHeader, | ||
pub execution_branch: Vec<H256>, | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, tree_hash_derive::TreeHash)] | ||
pub struct ForkData { | ||
pub current_version: ForkVersion, | ||
pub genesis_validators_root: H256, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Clone, tree_hash_derive::TreeHash)] | ||
pub struct SigningData { | ||
pub object_root: H256, | ||
pub domain: H256, | ||
} | ||
|
||
/// This is used specifically for backwards-compatibility, storing state in the contract | ||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct ExtendedBeaconBlockHeader { | ||
|
@@ -63,17 +175,23 @@ pub struct ExtendedBeaconBlockHeader { | |
pub execution_block_hash: H256, | ||
} | ||
|
||
impl From<HeaderUpdate> for ExtendedBeaconBlockHeader { | ||
fn from(item: HeaderUpdate) -> Self { | ||
let root = item.beacon_header.tree_hash_root(); | ||
ExtendedBeaconBlockHeader { | ||
header: item.beacon_header, | ||
beacon_block_root: H256(root.0.into()), | ||
execution_block_hash: item.execution_block_hash, | ||
impl From<FinalizedHeader> for ExtendedBeaconBlockHeader { | ||
fn from(finalized_header: FinalizedHeader) -> Self { | ||
let beacon = finalized_header.beacon; | ||
Self { | ||
header: beacon.clone(), | ||
beacon_block_root: beacon.tree_hash_root().0.into(), | ||
execution_block_hash: finalized_header.execution.block_hash, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, PartialEq, Clone, tree_hash_derive::TreeHash)] | ||
pub struct SigningData { | ||
pub object_root: H256, | ||
pub domain: H256, | ||
} | ||
|
||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct SyncCommitteePublicKeys(pub Vec<PublicKeyBytes>); | ||
|
@@ -95,37 +213,70 @@ pub struct SyncAggregate { | |
pub sync_committee_signature: SignatureBytes, | ||
} | ||
|
||
// Updated light client update structure for Electra | ||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct SyncCommitteeUpdate { | ||
pub next_sync_committee: SyncCommittee, | ||
pub next_sync_committee_branch: Vec<H256>, | ||
pub struct LightClientUpdate { | ||
pub attested_header: AttestedHeader, | ||
pub next_sync_committee: Option<SyncCommittee>, | ||
pub next_sync_committee_branch: Option<Vec<H256>>, | ||
pub finalized_header: FinalizedHeader, | ||
pub finality_branch: Vec<H256>, | ||
pub sync_aggregate: SyncAggregate, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub signature_slot: Slot, | ||
} | ||
|
||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
// Version enum for different Ethereum fork versions | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct HeaderUpdate { | ||
pub beacon_header: BeaconBlockHeader, | ||
pub execution_block_hash: H256, | ||
pub execution_hash_branch: Vec<H256>, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(rename_all = "lowercase"))] | ||
pub enum LightClientVersion { | ||
Altair, | ||
Bellatrix, | ||
Capella, | ||
Deneb, | ||
Electra, | ||
} | ||
|
||
impl LightClientVersion { | ||
pub fn as_str(&self) -> &'static str { | ||
match self { | ||
LightClientVersion::Altair => "altair", | ||
LightClientVersion::Bellatrix => "bellatrix", | ||
LightClientVersion::Capella => "capella", | ||
LightClientVersion::Deneb => "deneb", | ||
LightClientVersion::Electra => "electra", | ||
} | ||
} | ||
} | ||
|
||
impl std::fmt::Display for LightClientVersion { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.as_str()) | ||
} | ||
} | ||
|
||
// Top-level wrapper with version (optional, for when you need versioning) | ||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct FinalizedHeaderUpdate { | ||
pub header_update: HeaderUpdate, | ||
pub finality_branch: Vec<H256>, | ||
pub struct VersionedLightClientUpdate { | ||
pub version: LightClientVersion, | ||
pub data: LightClientUpdate, | ||
} | ||
|
||
// For arrays of light client updates | ||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub struct LightClientUpdate { | ||
pub attested_beacon_header: BeaconBlockHeader, | ||
pub sync_aggregate: SyncAggregate, | ||
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))] | ||
pub signature_slot: Slot, | ||
pub finality_update: FinalizedHeaderUpdate, | ||
pub sync_committee_update: Option<SyncCommitteeUpdate>, | ||
pub struct LightClientUpdates(pub Vec<LightClientUpdate>); | ||
|
||
// Alternative: Version-specific data if structures differ significantly between versions | ||
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] | ||
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))] | ||
pub enum LightClientUpdateVariant { | ||
Electra(LightClientUpdate), | ||
// Future versions can be added here with different data structures | ||
// Deneb(DenebLightClientUpdate), | ||
} | ||
|
||
#[derive(Clone, BorshDeserialize, BorshSchema, BorshSerialize, Debug)] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this copied copied instead of using the
BlockHeader
https://github.com/Near-One/rainbow-bridge/blob/691af191297eb6d67fd637dedfe79f3315b8a8e9/contracts/near/eth-types/src/lib.rs#L150?We should somehow avoid reimplementing the same block header, we already have 3-4 different implementations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a different set of fields in the Beacon's Execution Header: