From abd09b3a52b5c9796d163d9172d5fea15dd00ba0 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:16:18 +0100 Subject: [PATCH 01/11] remove useless main --- Cargo.lock | 4 ---- Cargo.toml | 6 +----- src/main.rs | 3 --- 3 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 src/main.rs diff --git a/Cargo.lock b/Cargo.lock index a2e824b..809049f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -810,10 +810,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "coral" -version = "0.1.0" - [[package]] name = "coral-cli" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 830522c..d5a2ca4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,5 @@ -[package] -name = "coral" -version = "0.1.0" -edition = "2021" - [workspace] +resolver = "2" members = [ "coral-lib", "coral-cli", diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} From 23497113ee78659e079455c3a20fb90a2c6a175d Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Fri, 23 Feb 2024 12:09:51 +0100 Subject: [PATCH 02/11] import coral-lib beacon and utils code + dep updates --- Cargo.lock | 116 ++++---- coral-lib/Cargo.toml | 15 +- coral-lib/src/lib.rs | 2 + .../services/beacon/attestation_rewards.rs | 48 ++++ coral-lib/src/services/beacon/client.rs | 78 ++++++ coral-lib/src/services/beacon/fetch_block.rs | 77 ++++++ .../src/services/beacon/fetch_genesis.rs | 40 +++ .../beacon/fetch_puffer_validator_stats.rs | 247 ++++++++++++++++++ .../src/services/beacon/fetch_state_root.rs | 37 +++ .../src/services/beacon/fetch_validator.rs | 79 ++++++ .../src/services/beacon/fetch_validators.rs | 123 +++++++++ coral-lib/src/services/beacon/mock_client.rs | 118 +++++++++ coral-lib/src/services/beacon/mod.rs | 34 +++ coral-lib/src/services/beacon/submit_exit.rs | 60 +++++ .../beacon/types/attestation_rewards.rs | 31 +++ .../src/services/beacon/types/beacon_block.rs | 99 +++++++ .../src/services/beacon/types/genesis.rs | 52 ++++ coral-lib/src/services/beacon/types/mod.rs | 24 ++ .../src/services/beacon/types/state_root.rs | 74 ++++++ .../services/beacon/types/state_root_test.rs | 76 ++++++ .../src/services/beacon/types/validator.rs | 73 ++++++ .../beacon/types/validator_balance.rs | 12 + coral-lib/src/services/mod.rs | 1 + coral-lib/src/utils/abi/abi_test.rs | 95 +++++++ coral-lib/src/utils/abi/intel_report.rs | 233 +++++++++++++++++ coral-lib/src/utils/abi/mod.rs | 10 + coral-lib/src/utils/abi/rave_evidence.rs | 106 ++++++++ coral-lib/src/utils/abi/validator_key_data.rs | 95 +++++++ coral-lib/src/utils/encoding.rs | 69 +++++ coral-lib/src/utils/encoding_test.rs | 0 coral-lib/src/utils/ethereum.rs | 96 +++++++ coral-lib/src/utils/mod.rs | 8 + coral-lib/src/utils/parse.rs | 48 ++++ coral-lib/src/utils/serialize.rs | 27 ++ coral-lib/src/utils/ssl.rs | 107 ++++++++ coral-lib/src/utils/validator.rs | 79 ++++++ coral-lib/src/utils/wallet.rs | 80 ++++++ 37 files changed, 2515 insertions(+), 54 deletions(-) create mode 100644 coral-lib/src/services/beacon/attestation_rewards.rs create mode 100644 coral-lib/src/services/beacon/client.rs create mode 100644 coral-lib/src/services/beacon/fetch_block.rs create mode 100644 coral-lib/src/services/beacon/fetch_genesis.rs create mode 100644 coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs create mode 100644 coral-lib/src/services/beacon/fetch_state_root.rs create mode 100644 coral-lib/src/services/beacon/fetch_validator.rs create mode 100644 coral-lib/src/services/beacon/fetch_validators.rs create mode 100644 coral-lib/src/services/beacon/mock_client.rs create mode 100644 coral-lib/src/services/beacon/mod.rs create mode 100644 coral-lib/src/services/beacon/submit_exit.rs create mode 100644 coral-lib/src/services/beacon/types/attestation_rewards.rs create mode 100644 coral-lib/src/services/beacon/types/beacon_block.rs create mode 100644 coral-lib/src/services/beacon/types/genesis.rs create mode 100644 coral-lib/src/services/beacon/types/mod.rs create mode 100644 coral-lib/src/services/beacon/types/state_root.rs create mode 100644 coral-lib/src/services/beacon/types/state_root_test.rs create mode 100644 coral-lib/src/services/beacon/types/validator.rs create mode 100644 coral-lib/src/services/beacon/types/validator_balance.rs create mode 100644 coral-lib/src/services/mod.rs create mode 100644 coral-lib/src/utils/abi/abi_test.rs create mode 100644 coral-lib/src/utils/abi/intel_report.rs create mode 100644 coral-lib/src/utils/abi/mod.rs create mode 100644 coral-lib/src/utils/abi/rave_evidence.rs create mode 100644 coral-lib/src/utils/abi/validator_key_data.rs create mode 100644 coral-lib/src/utils/encoding.rs create mode 100644 coral-lib/src/utils/encoding_test.rs create mode 100644 coral-lib/src/utils/ethereum.rs create mode 100644 coral-lib/src/utils/mod.rs create mode 100644 coral-lib/src/utils/parse.rs create mode 100644 coral-lib/src/utils/serialize.rs create mode 100644 coral-lib/src/utils/ssl.rs create mode 100644 coral-lib/src/utils/validator.rs create mode 100644 coral-lib/src/utils/wallet.rs diff --git a/Cargo.lock b/Cargo.lock index 809049f..0253372 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -251,12 +251,12 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09dbe0e490df5da9d69b36dca48a76635288a82f92eca90024883a56202026d" +checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" dependencies = [ "async-trait", - "axum-core 0.4.2", + "axum-core 0.4.3", "bytes", "futures-util", "http 1.0.0", @@ -302,9 +302,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c8503f93e6d144ee5690907ba22db7ba79ab001a932ab99034f0fe836b3df" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", @@ -384,9 +384,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.6" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -745,7 +745,7 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bech32", "bs58", "digest 0.10.7", @@ -814,7 +814,7 @@ dependencies = [ name = "coral-cli" version = "0.1.0" dependencies = [ - "axum 0.7.3", + "axum 0.7.4", "chrono", "clap", "clap_complete", @@ -839,7 +839,8 @@ dependencies = [ name = "coral-lib" version = "0.1.0" dependencies = [ - "axum 0.7.3", + "axum 0.7.4", + "base64 0.21.7", "ethers", "reqwest", "serde", @@ -1195,7 +1196,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bytes", "hex", "k256", @@ -1417,9 +1418,9 @@ dependencies = [ [[package]] name = "ethers" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5344eea9b20effb5efeaad29418215c4d27017639fd1f908260f59cbbd226e" +checksum = "6c7cd562832e2ff584fa844cd2f6e5d4f35bbe11b28c7c9b8df957b2e1d0c701" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -1433,9 +1434,9 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" +checksum = "35dc9a249c066d17e8947ff52a4116406163cf92c7f0763cb8c001760b26403f" dependencies = [ "ethers-core", "once_cell", @@ -1445,9 +1446,9 @@ dependencies = [ [[package]] name = "ethers-contract" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0111ead599d17a7bff6985fd5756f39ca7033edc79a31b23026a8d5d64fa95cd" +checksum = "43304317c7f776876e47f2f637859f6d0701c1ec7930a150f169d5fbe7d76f5a" dependencies = [ "const-hex", "ethers-contract-abigen", @@ -1464,9 +1465,9 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51258120c6b47ea9d9bec0d90f9e8af71c977fbefbef8213c91bfed385fe45eb" +checksum = "f9f96502317bf34f6d71a3e3d270defaa9485d754d789e15a8e04a84161c95eb" dependencies = [ "Inflector", "const-hex", @@ -1488,9 +1489,9 @@ dependencies = [ [[package]] name = "ethers-contract-derive" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936e7a0f1197cee2b62dc89f63eff3201dbf87c283ff7e18d86d38f83b845483" +checksum = "452ff6b0a64507ce8d67ffd48b1da3b42f03680dcf5382244e9c93822cbbf5de" dependencies = [ "Inflector", "const-hex", @@ -1504,9 +1505,9 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" +checksum = "aab3cef6cc1c9fd7f787043c81ad3052eff2b96a3878ef1526aa446311bdbfc9" dependencies = [ "arrayvec", "bytes", @@ -1534,9 +1535,9 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abbac2c890bdbe0f1b8e549a53b00e2c4c1de86bb077c1094d1f38cdf9381a56" +checksum = "16d45b981f5fa769e1d0343ebc2a44cfa88c9bc312eb681b676318b40cef6fb1" dependencies = [ "chrono", "ethers-core", @@ -1550,9 +1551,9 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681ece6eb1d10f7cf4f873059a77c04ff1de4f35c63dd7bccde8f438374fcb93" +checksum = "145211f34342487ef83a597c1e69f0d3e01512217a7c72cc8a25931854c7dca0" dependencies = [ "async-trait", "auto_impl", @@ -1577,13 +1578,13 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" +checksum = "fb6b15393996e3b8a78ef1332d6483c11d839042c17be58decc92fa8b1c3508a" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.6", + "base64 0.21.7", "bytes", "const-hex", "enr", @@ -1614,9 +1615,9 @@ dependencies = [ [[package]] name = "ethers-signers" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb1b714e227bbd2d8c53528adb580b203009728b17d0d0e4119353aa9bc5532" +checksum = "b3b125a103b56aef008af5d5fb48191984aa326b50bfd2557d231dc499833de3" dependencies = [ "async-trait", "coins-bip32", @@ -1633,9 +1634,9 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.11" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64f710586d147864cff66540a6d64518b9ff37d73ef827fee430538265b595f" +checksum = "d21df08582e0a43005018a858cc9b465c5fff9cf4056651be64f844e57d1f55f" dependencies = [ "cfg-if", "const-hex", @@ -2473,7 +2474,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "pem", "ring 0.16.20", "serde", @@ -3516,11 +3517,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -3544,6 +3545,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -3689,7 +3691,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", ] [[package]] @@ -4351,9 +4353,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -4430,14 +4432,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.6", ] [[package]] @@ -4457,7 +4459,7 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.33", ] [[package]] @@ -4468,7 +4470,7 @@ checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.33", ] [[package]] @@ -4476,12 +4478,23 @@ name = "toml_edit" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.33", +] + +[[package]] +name = "toml_edit" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.2", ] [[package]] @@ -5061,6 +5074,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/coral-lib/Cargo.toml b/coral-lib/Cargo.toml index 21bf69b..04bd681 100644 --- a/coral-lib/Cargo.toml +++ b/coral-lib/Cargo.toml @@ -4,13 +4,14 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.2" -ethers = "2.0.11" -reqwest = { version = "0.11.23", features = ["json"] } -serde = { version = "1.0.193", features = ["derive"] } -serde_json = "1.0.108" -tokio = { version = "1.35.1", features = ["full"] } -toml = "0.8.8" +axum = "0.7.4" +base64 = "0.21.7" +ethers = "2.0.13" +reqwest = { version = "0.11.24", features = ["json"] } +serde = { version = "1.0.195", features = ["derive"] } +serde_json = "1.0.111" +tokio = { version = "1.36.0", features = ["full"] } +toml = "0.8.10" tower-http = { version = "0.5.0", features = [ "cors", "trace" ] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } diff --git a/coral-lib/src/lib.rs b/coral-lib/src/lib.rs index 8ba13c6..3c326f8 100644 --- a/coral-lib/src/lib.rs +++ b/coral-lib/src/lib.rs @@ -1,5 +1,7 @@ pub mod error; pub mod structs; +pub mod services; +pub mod utils; #[inline] pub fn strip_0x_prefix(s: &str) -> &str { diff --git a/coral-lib/src/services/beacon/attestation_rewards.rs b/coral-lib/src/services/beacon/attestation_rewards.rs new file mode 100644 index 0000000..e9b6482 --- /dev/null +++ b/coral-lib/src/services/beacon/attestation_rewards.rs @@ -0,0 +1,48 @@ +use axum::http::StatusCode; + +use crate::{ + error::{AppServerResult, ServerErrorResponse}, + utils::encoding::parse_json_response, +}; + +use super::types::AttestationRewardsResponse; + +pub async fn get_attestation_rewards( + beacon_url: &str, + epoch: u64, + validators: &[u64], +) -> AppServerResult { + let validators_json_body: String = serde_json::to_string( + &validators + .iter() + .map(|v| v.to_string()) + .collect::>(), + ) + .unwrap(); + + let api_url = format!("{beacon_url}/eth/v1/beacon/rewards/attestations/{epoch}"); + let resp = reqwest::Client::new() + .request(reqwest::Method::POST, api_url) + .body(validators_json_body) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + + let resp_json: AttestationRewardsResponse = parse_json_response(resp).await?; + Ok(resp_json) +} diff --git a/coral-lib/src/services/beacon/client.rs b/coral-lib/src/services/beacon/client.rs new file mode 100644 index 0000000..d2b41fd --- /dev/null +++ b/coral-lib/src/services/beacon/client.rs @@ -0,0 +1,78 @@ +use async_trait::async_trait; + +use crate::error::AppServerResult; +use crate::services::beacon; +use crate::services::beacon::types; + +use super::types::{BlockId, StateId, ValidatorId}; + +#[async_trait] +pub trait BeaconClientTrait { + async fn fetch_block(&self, block_id: BlockId) -> AppServerResult; + + async fn fetch_block_root(&self, block_id: BlockId) -> AppServerResult; + + async fn fetch_validator( + &self, + state_id: types::StateId, + validator: ValidatorId, + ) -> AppServerResult; + + async fn fetch_validators_by_pubkey( + &self, + state_id: StateId, + validators: &[String], + ) -> AppServerResult; + + async fn fetch_validators_by_index( + &self, + state_id: StateId, + validators: &[u64], + ) -> AppServerResult; +} + +#[derive(Clone, Debug)] +pub struct BeaconClient { + pub url: String, +} + +impl BeaconClient { + pub fn new(url: String) -> Self { + Self { url } + } +} + +#[async_trait] +impl BeaconClientTrait for BeaconClient { + async fn fetch_block(&self, block_id: BlockId) -> AppServerResult { + beacon::fetch_block::fetch_block(&self.url, block_id).await + } + + async fn fetch_block_root(&self, block_id: BlockId) -> AppServerResult { + beacon::fetch_block::fetch_block_root(&self.url, block_id).await + } + + async fn fetch_validator( + &self, + state_id: types::StateId, + validator: ValidatorId, + ) -> AppServerResult { + beacon::fetch_validator::fetch_validator(&self.url, state_id, validator).await + } + + async fn fetch_validators_by_pubkey( + &self, + state_id: StateId, + validators: &[String], + ) -> AppServerResult { + beacon::fetch_validators::fetch_validators_by_pubkey(&self.url, state_id, validators).await + } + + async fn fetch_validators_by_index( + &self, + state_id: StateId, + validators: &[u64], + ) -> AppServerResult { + beacon::fetch_validators::fetch_validators_by_index(&self.url, state_id, validators).await + } +} diff --git a/coral-lib/src/services/beacon/fetch_block.rs b/coral-lib/src/services/beacon/fetch_block.rs new file mode 100644 index 0000000..69d835c --- /dev/null +++ b/coral-lib/src/services/beacon/fetch_block.rs @@ -0,0 +1,77 @@ +use axum::http::StatusCode; + +use crate::services::beacon::types::{BlockResponse, BlockRootResponse}; +use crate::{ + error::{AppServerResult, ServerErrorResponse}, + utils::encoding::parse_json_response, +}; + +use super::types::BlockId; + +pub async fn fetch_block(beacon_url: &str, block_id: BlockId) -> AppServerResult { + let api_url = format!("{beacon_url}/eth/v2/beacon/blocks/{block_id}"); + tracing::debug!("Beacon: {api_url}"); + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let body = resp.text().await.map_err(|err| { + let error_msg = "Failed to parse body"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + eprintln!("{body}"); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + let resp_json = parse_json_response(resp).await?; + Ok(resp_json) +} + +pub async fn fetch_block_root(beacon_url: &str, block_id: BlockId) -> AppServerResult { + let api_url = format!("{beacon_url}/eth/v1/beacon/blocks/{block_id}/root"); + tracing::debug!("Beacon: {api_url}"); + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let body = resp.text().await.map_err(|err| { + let error_msg = "Failed to parse body"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + eprintln!("{body}"); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + let resp_json: BlockRootResponse = parse_json_response(resp).await?; + Ok(resp_json.data.root) +} diff --git a/coral-lib/src/services/beacon/fetch_genesis.rs b/coral-lib/src/services/beacon/fetch_genesis.rs new file mode 100644 index 0000000..6d685c0 --- /dev/null +++ b/coral-lib/src/services/beacon/fetch_genesis.rs @@ -0,0 +1,40 @@ +use axum::http::StatusCode; + +use serde::Deserialize; + +use crate::services::beacon::types::BeaconGenesis; +use crate::{ + error::{AppServerResult, ServerErrorResponse}, + utils::encoding::parse_json_response, +}; + +#[derive(Clone, Debug, Deserialize)] +pub struct BeaconGenesisWrapper { + pub data: BeaconGenesis, +} + +pub async fn fetch_genesis(beacon_url: &str) -> AppServerResult { + let api_url = format!("{beacon_url}/eth/v1/beacon/genesis"); + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + let resp_json: BeaconGenesisWrapper = parse_json_response(resp).await?; + Ok(resp_json.data) +} diff --git a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs new file mode 100644 index 0000000..02e2e57 --- /dev/null +++ b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs @@ -0,0 +1,247 @@ +use std::collections::HashMap; + +use ethers::prelude::*; +// use puffer_pool_contracts::withdrawal_pool::Validator; + +use crate::error::AppServerResult; +use crate::services::beacon::types::ValidatorData; +use crate::services::beacon::SLOTS_PER_EPOCH; +use crate::strip_0x_prefix; + +use super::client::BeaconClientTrait; +use super::types::{BlockId, ValidatorStatus}; +use super::{is_active_validator, is_full_withdrawal}; + +#[derive(Clone, Debug)] +pub struct NodeValidator { + pub pub_key: String, + pub validator_id: u64, +} + +#[derive(Clone, Debug, Default)] +pub struct ValidatorFullWithdrawal { + pub amount: U256, + pub was_slashed: bool, +} + +#[derive(Clone, Debug, Default)] +pub struct ValidatorConsensusReward { + pub amount: U256, +} + +#[derive(Clone, Debug, Default)] +pub struct ValidatorReward { + pub pubkey: String, + pub consensus_rewards: ValidatorConsensusReward, + pub full_withdrawal: ValidatorFullWithdrawal, +} + +#[derive(Clone, Debug, Default)] +pub struct RewardBlock { + pub block_number: String, + pub block_root: String, +} + +#[derive(Clone, Debug, Default)] +pub struct PufferValidatorStats { + pub start_block: RewardBlock, + pub end_block: RewardBlock, + pub validators: HashMap, +} + +pub async fn fetch_puffer_validator_stats( + beacon_client: &impl BeaconClientTrait, + validators_by_index: &HashMap, + last_post_block: U256, + block_root: &str, +) -> AppServerResult { + let eth_32: U256 = U256::from(32).saturating_mul(U256::exp10(9)); + + let last_reward_block_str = format!("{}", last_post_block); + + let mut validator_rewards = PufferValidatorStats::default(); + + let mut end_block: Option = None; + let start_block: Option; + + let mut block_root = block_root.to_string(); + loop { + let curr_block = beacon_client + .fetch_block(BlockId::BlockRoot(block_root.to_string())) + .await?; + if end_block.is_none() { + end_block = Some(RewardBlock { + block_number: curr_block + .data + .message + .body + .execution_payload + .block_number + .clone(), + block_root: block_root.clone(), + }); + } + + tracing::debug!( + "BLOCK: {} {} {block_root}", + last_reward_block_str, + curr_block.data.message.body.execution_payload.block_number + ); + + block_root = curr_block.data.message.parent_root; + let (epoch, _) = curr_block + .data + .message + .slot + .div_mod(U256::from(SLOTS_PER_EPOCH)); + + let withdrawals = curr_block.data.message.body.execution_payload.withdrawals; + for withdrawal in withdrawals { + let validator_index = withdrawal.validator_index; + if let Some(validator_data) = validators_by_index.get(&validator_index) { + let v_fully_withdrawn = is_full_withdrawal(validator_data, epoch.as_u64()); + let entry = validator_rewards + .validators + .entry(withdrawal.validator_index) + .or_insert(ValidatorReward::default()); + + entry.pubkey = validator_data.validator.pubkey.to_string(); + if v_fully_withdrawn { + if withdrawal.amount > eth_32 { + entry.full_withdrawal.amount = eth_32; + entry.consensus_rewards.amount += withdrawal.amount - eth_32; + } else { + entry.full_withdrawal.amount = withdrawal.amount; + } + match validator_data.status { + ValidatorStatus::ActiveSlashed | ValidatorStatus::ExitedSlashed => { + entry.full_withdrawal.was_slashed = true; + } + _ => { + entry.full_withdrawal.was_slashed = false; + } + } + } else { + entry.consensus_rewards.amount += withdrawal.amount; + } + } + } + if curr_block.data.message.body.execution_payload.block_number <= last_reward_block_str { + start_block = Some(RewardBlock { + block_number: curr_block + .data + .message + .body + .execution_payload + .block_number + .clone(), + block_root: block_root.clone(), + }); + break; + } + } + + if let Some(block) = start_block { + validator_rewards.start_block = block; + } + if let Some(block) = end_block { + validator_rewards.end_block = block; + } + + // convert GWEI to WEI + validator_rewards + .validators + .iter_mut() + .for_each(|(_, reward)| { + reward.consensus_rewards.amount = reward + .consensus_rewards + .amount + .saturating_mul(U256::exp10(9)); + reward.full_withdrawal.amount = + reward.full_withdrawal.amount.saturating_mul(U256::exp10(9)); + }); + Ok(validator_rewards) +} + +/// Given an epoch, count the number of valid validators in +/// validators_by_index. +pub fn count_active_validators( + validators_by_index: &HashMap, + end_epoch: u64, +) -> u64 { + validators_by_index + .values() + .filter(|v| is_active_validator(v, end_epoch)) + .count() as u64 +} + +/// Calculates Puffer Validator balances with just their +/// raw balance on the beacon chain. +pub fn calculate_puffer_validator_beacon_balances( + validators_by_index: &HashMap, + end_epoch: U256, +) -> U256 { + let gwei_32 = U256::from(32).saturating_mul(U256::exp10(9)); + let mut validator_balance = U256::zero(); + for validator in validators_by_index.values() { + let is_active = is_active_validator(validator, end_epoch.as_u64()); + // Edge case where validator just registered and is waiting to + // start validating + #[allow(clippy::if_same_then_else)] + if validator.status == ValidatorStatus::PendingQueued { + validator_balance += gwei_32; + } else if is_active && validator.balance == U256::zero() { + validator_balance += gwei_32; + } else if is_active { + validator_balance += validator.balance; + } + } + validator_balance.saturating_mul(U256::exp10(9)) +} + +/// Calculates Puffer Validator balances with their +/// pufETH bond accounted for. If their pufETH bond can cover +/// their losses, then their effective balance should be 32 ETH. +pub fn calculate_puffer_validator_beacon_balances_with_puf_eth_bond( + puffer_validators: &HashMap, + validators_by_index: &HashMap, + end_epoch: U256, + puf_eth_to_eth: U256, +) -> U256 { + let gwei_32 = U256::from(32).saturating_mul(U256::exp10(9)); + + let mut validator_balance = U256::zero(); + for (_, validator) in validators_by_index.iter() { + let is_active = is_active_validator(validator, end_epoch.as_u64()); + // Edge case where validator just registered and is waiting to + // start validating + #[allow(clippy::if_same_then_else)] + if validator.status == ValidatorStatus::PendingQueued { + validator_balance += gwei_32; + } else if is_active { + if validator.balance == U256::zero() { + validator_balance += gwei_32; + } else if validator.balance >= gwei_32 { + validator_balance += validator.balance; + } else { + let validator_address: &str = strip_0x_prefix!(validator.validator.pubkey); + if let Some(validator_sc) = puffer_validators.get(validator_address) { + let bond_eth_value = + U256::from(validator_sc.bond).saturating_mul(puf_eth_to_eth); + + let double_validator_balance = validator.balance.saturating_mul(U256::from(2)); + let gwei_64 = gwei_32.saturating_mul(U256::from(2)); + + // The idea is we want to have the bond account for + // double the discrepancy to be conservative, hence the U256::from(2) + if double_validator_balance + bond_eth_value >= gwei_64 { + validator_balance += gwei_32; + } else { + validator_balance += validator.balance; + } + } + } + } + } + validator_balance.saturating_mul(U256::exp10(9)) +} diff --git a/coral-lib/src/services/beacon/fetch_state_root.rs b/coral-lib/src/services/beacon/fetch_state_root.rs new file mode 100644 index 0000000..1ef2127 --- /dev/null +++ b/coral-lib/src/services/beacon/fetch_state_root.rs @@ -0,0 +1,37 @@ +use axum::http::StatusCode; + +use crate::error::{AppServerResult, ServerErrorResponse}; +use crate::utils::encoding::parse_json_response; + +use super::types::{StateId, StateRootResponse}; + +pub async fn get_state_root( + beacon_url: &str, + state_id: &StateId, +) -> AppServerResult { + let api_url = format!("{beacon_url}/eth/v1/beacon/states/{state_id}/root"); + + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + + let resp_json: StateRootResponse = parse_json_response(resp).await?; + Ok(resp_json) +} diff --git a/coral-lib/src/services/beacon/fetch_validator.rs b/coral-lib/src/services/beacon/fetch_validator.rs new file mode 100644 index 0000000..b26489c --- /dev/null +++ b/coral-lib/src/services/beacon/fetch_validator.rs @@ -0,0 +1,79 @@ +use axum::http::StatusCode; + +use crate::services::beacon::types::StateId; +use crate::{ + error::{AppServerResult, ServerErrorResponse}, + utils::encoding::parse_json_response, +}; + +use super::types::{ValidatorId, ValidatorResponse}; + +pub async fn fetch_validator_by_index( + beacon_url: &str, + state_id: StateId, + validator_index: u64, +) -> AppServerResult { + let api_url = + format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators/{validator_index}"); + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + tracing::error!("Failed to fetch validator"); + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + + let resp_json = parse_json_response(resp).await?; + Ok(resp_json) +} + +pub async fn fetch_validator( + beacon_url: &str, + state_id: StateId, + validator: ValidatorId, +) -> AppServerResult { + let api_url = format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators/{validator}"); + tracing::debug!("Beacon: {api_url}"); + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + let error_msg = "Failed to send request"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + tracing::error!("Failed to fetch validator {validator}"); + let body = resp.text().await.map_err(|err| { + let error_msg = "Failed to parse body"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + eprintln!("{body}"); + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + + let resp_json = parse_json_response(resp).await?; + Ok(resp_json) +} diff --git a/coral-lib/src/services/beacon/fetch_validators.rs b/coral-lib/src/services/beacon/fetch_validators.rs new file mode 100644 index 0000000..9508767 --- /dev/null +++ b/coral-lib/src/services/beacon/fetch_validators.rs @@ -0,0 +1,123 @@ +use axum::http::StatusCode; +use std::collections::HashMap; + +use crate::{ + add_0x_prefix, + services::beacon::types::{StateId, ValidatorId}, +}; + +use super::{ + client::BeaconClientTrait, + types::{ValidatorData, ValidatorListResponse}, +}; +use crate::{ + error::{AppServerResult, ServerErrorResponse}, + utils::encoding::parse_json_response, +}; + +pub async fn fetch_validators_by_index( + beacon_url: &str, + state_id: StateId, + validators: &[u64], +) -> AppServerResult { + let validators_query: String = validators + .iter() + .map(|v| v.to_string()) + .collect::>() + .join(","); + + let api_url = + format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators?id={validators_query}"); + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + let error_msg = "Failed to send request"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + tracing::error!("Failed to fetch validators"); + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + + let resp_json = parse_json_response(resp).await?; + Ok(resp_json) +} + +pub async fn fetch_validators_by_pubkey( + beacon_url: &str, + state_id: StateId, + validators: &[String], +) -> AppServerResult { + let validators_query: String = validators.to_vec().join(","); + + let api_url = + format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators?id={validators_query}"); + tracing::debug!("Beacon: {api_url}"); + + let resp = reqwest::Client::new() + .request(reqwest::Method::GET, api_url) + .send() + .await + .map_err(|err| { + let error_msg = "Failed to send request"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + tracing::error!("Failed to fetch validators"); + let body = resp.text().await.map_err(|err| { + let error_msg = "Failed to parse body"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + eprintln!("{body}"); + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + + let resp_json = parse_json_response(resp).await?; + Ok(resp_json) +} + +pub async fn fetch_validators_fallback( + beacon_client: &impl BeaconClientTrait, + validator_pubkeys: &[String], +) -> HashMap { + let validator_pubkeys: Vec = + validator_pubkeys.iter().map(|k| add_0x_prefix(k)).collect(); + + let validators_by_index: HashMap = match beacon_client + .fetch_validators_by_pubkey(StateId::Finalized, validator_pubkeys.as_slice()) + .await + { + Ok(validators) => validators.data.into_iter().map(|v| (v.index, v)).collect(), + Err(_err) => { + tracing::debug!("Failed to fetch validators in bulk. Fetching individually instead"); + + let mut validators_by_index: HashMap = HashMap::new(); + for pubkey in validator_pubkeys { + let validator_resp = beacon_client + .fetch_validator(StateId::Finalized, ValidatorId::Pubkey(pubkey.clone())) + .await; + if let Ok(v) = validator_resp { + validators_by_index.insert(v.data.index, v.data); + } + } + validators_by_index + } + }; + validators_by_index +} diff --git a/coral-lib/src/services/beacon/mock_client.rs b/coral-lib/src/services/beacon/mock_client.rs new file mode 100644 index 0000000..020df64 --- /dev/null +++ b/coral-lib/src/services/beacon/mock_client.rs @@ -0,0 +1,118 @@ +use std::collections::VecDeque; +use std::sync::{Arc, Mutex}; + +use async_trait::async_trait; +use axum::http::StatusCode; + +use crate::error::{AppServerResult, ServerErrorResponse}; +use crate::services::beacon::types; + +use super::client::BeaconClientTrait; + +#[derive(Clone, Debug, Default)] +pub struct MockBeaconClient { + pub block_responses: Arc>>, + pub block_root_responses: Arc>>, + pub validator_responses: Arc>>, + pub validators_by_pubkey_responses: Arc>>, +} + +impl MockBeaconClient { + pub fn new() -> Self { + Self::default() + } + + pub fn push_block_response(&mut self, value: types::BlockResponse) { + self.block_responses.lock().unwrap().push_back(value); + } + + pub fn push_block_root_response(&mut self, value: String) { + self.block_root_responses.lock().unwrap().push_back(value); + } + + pub fn push_validator_response(&mut self, value: types::ValidatorResponse) { + self.validator_responses.lock().unwrap().push_back(value); + } + + pub fn push_validators_by_pubkey_response(&mut self, value: types::ValidatorListResponse) { + self.validators_by_pubkey_responses + .lock() + .unwrap() + .push_back(value); + } +} + +#[async_trait] +impl BeaconClientTrait for MockBeaconClient { + async fn fetch_block( + &self, + _state_id: types::BlockId, + ) -> AppServerResult { + match self.block_responses.lock().unwrap().pop_front() { + Some(block) => Ok(block), + None => Err(ServerErrorResponse::new( + StatusCode::IM_A_TEAPOT, + 2000, + "No fetch_block response set", + )), + } + } + + async fn fetch_block_root(&self, _state_id: types::BlockId) -> AppServerResult { + match self.block_root_responses.lock().unwrap().pop_front() { + Some(val) => Ok(val), + None => Err(ServerErrorResponse::new( + StatusCode::IM_A_TEAPOT, + 2000, + "No fetch_block_root response set", + )), + } + } + + async fn fetch_validator( + &self, + _state_id: types::StateId, + _validator: types::ValidatorId, + ) -> AppServerResult { + match self.validator_responses.lock().unwrap().pop_front() { + Some(value) => Ok(value), + None => Err(ServerErrorResponse::new( + StatusCode::IM_A_TEAPOT, + 2000, + "No fetch_validator response set", + )), + } + } + + async fn fetch_validators_by_pubkey( + &self, + _state_id: types::StateId, + _validators: &[String], + ) -> AppServerResult { + match self + .validators_by_pubkey_responses + .lock() + .unwrap() + .pop_front() + { + Some(value) => Ok(value), + None => Err(ServerErrorResponse::new( + StatusCode::IM_A_TEAPOT, + 2000, + "No fetch_validators_by_pubkey response set", + )), + } + } + + async fn fetch_validators_by_index( + &self, + _state_id: types::StateId, + _validators: &[u64], + ) -> AppServerResult { + Err(ServerErrorResponse::new( + StatusCode::IM_A_TEAPOT, + 2000, + "No fetch_validators_by_index response set", + )) + } +} diff --git a/coral-lib/src/services/beacon/mod.rs b/coral-lib/src/services/beacon/mod.rs new file mode 100644 index 0000000..a73b4b9 --- /dev/null +++ b/coral-lib/src/services/beacon/mod.rs @@ -0,0 +1,34 @@ +pub mod types; + +mod attestation_rewards; +mod fetch_block; +mod fetch_genesis; +mod fetch_puffer_validator_stats; +mod fetch_state_root; +mod fetch_validator; +mod fetch_validators; +mod submit_exit; + +pub mod client; +pub mod mock_client; + +pub use self::attestation_rewards::*; +pub use self::fetch_block::*; +pub use self::fetch_genesis::*; +pub use self::fetch_puffer_validator_stats::*; +pub use self::fetch_state_root::*; +pub use self::fetch_validator::*; +pub use self::fetch_validators::*; +pub use self::submit_exit::*; + +pub const SLOTS_PER_EPOCH: u64 = 32; + +#[inline] +pub fn is_active_validator(data: &types::ValidatorData, epoch: u64) -> bool { + data.validator.activation_epoch <= epoch && epoch < data.validator.exit_epoch +} + +#[inline] +pub fn is_full_withdrawal(data: &types::ValidatorData, epoch: u64) -> bool { + data.validator.exit_epoch <= epoch && data.validator.withdrawable_epoch <= epoch +} diff --git a/coral-lib/src/services/beacon/submit_exit.rs b/coral-lib/src/services/beacon/submit_exit.rs new file mode 100644 index 0000000..45db4e6 --- /dev/null +++ b/coral-lib/src/services/beacon/submit_exit.rs @@ -0,0 +1,60 @@ +use axum::http::StatusCode; +use serde::Serialize; + +use crate::error::{AppServerResult, ServerErrorResponse}; + +#[derive(Clone, Debug, Serialize)] +pub struct VoluntaryExit { + pub epoch: String, + pub validator_index: String, +} + +#[derive(Clone, Debug, Serialize)] +pub struct SignedVoluntaryExit { + pub message: VoluntaryExit, + pub signature: String, +} + +pub async fn submit_exit( + beacon_url: &str, + validator_index: u64, + epoch: u64, + signature: &str, +) -> AppServerResult<()> { + let req_body = SignedVoluntaryExit { + message: VoluntaryExit { + epoch: epoch.to_string(), + validator_index: validator_index.to_string(), + }, + signature: signature.to_string(), + }; + let req_body_str = serde_json::to_string(&req_body).unwrap(); + + eprintln!("Req Body: {}", req_body_str); + + let api_url = format!("{beacon_url}/eth/v1/beacon/pool/voluntary_exits"); + let resp = reqwest::Client::new() + .request(reqwest::Method::POST, api_url) + .body(req_body_str) + .send() + .await + .map_err(|err| { + tracing::error!("Failed to send request"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to send request", + ) + })?; + + let status_code = resp.status(); + if !status_code.is_success() { + let body = resp.text().await; + eprintln!("Body: {:?}", body); + let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); + let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); + return Err(err); + } + Ok(()) +} diff --git a/coral-lib/src/services/beacon/types/attestation_rewards.rs b/coral-lib/src/services/beacon/types/attestation_rewards.rs new file mode 100644 index 0000000..065a9f4 --- /dev/null +++ b/coral-lib/src/services/beacon/types/attestation_rewards.rs @@ -0,0 +1,31 @@ +use serde::Deserialize; + +use super::BeaconResponse; + +#[derive(Clone, Debug, Deserialize)] +pub struct IdealRewardResponse { + pub effective_balance: String, + pub head: String, + pub target: String, + pub source: String, + pub inclusion_delay: Option, + pub inactivity: Option, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct TotalRewardResponse { + pub validator_index: String, + pub head: String, + pub target: String, + pub source: String, + pub inclusion_delay: Option, + pub inactivity: Option, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct AttestationRewardsDataResponse { + pub ideal_rewards: Vec, + pub total_rewards: Vec, +} + +pub type AttestationRewardsResponse = BeaconResponse; diff --git a/coral-lib/src/services/beacon/types/beacon_block.rs b/coral-lib/src/services/beacon/types/beacon_block.rs new file mode 100644 index 0000000..544812e --- /dev/null +++ b/coral-lib/src/services/beacon/types/beacon_block.rs @@ -0,0 +1,99 @@ +use ethers::types::U256; +use serde::Deserialize; + +use crate::utils::serialize::{string_to_u256_base10, string_to_u64}; + +#[derive(Clone, Debug, Deserialize)] +pub struct BeaconWithdrawal { + pub index: String, + #[serde(deserialize_with = "string_to_u64")] + pub validator_index: u64, + pub address: String, + #[serde(deserialize_with = "string_to_u256_base10")] + pub amount: U256, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct ExecutionPayload { + pub parent_hash: String, + pub fee_recipient: String, + pub state_root: String, + pub receipts_root: String, + pub logs_bloom: String, + pub prev_randao: String, + pub block_number: String, + pub gas_limit: String, + pub gas_used: String, + pub timestamp: String, + pub extra_data: String, + pub base_fee_per_gas: String, + pub block_hash: String, + pub transactions: Vec, + pub withdrawals: Vec, + #[serde(skip_deserializing)] + pub bls_to_execution_changes: Vec, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BeaconEth1BlockBody { + pub deposit_root: String, + pub deposit_count: String, + pub block_hash: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BeaconBlockBody { + pub randao_reveal: String, + pub eth1_data: BeaconEth1BlockBody, + pub graffiti: String, + #[serde(skip_deserializing)] + pub proposer_slashings: Vec, + #[serde(skip_deserializing)] + pub attester_slashings: Vec, + #[serde(skip_deserializing)] + pub attestations: Vec, + #[serde(skip_deserializing)] + pub deposits: Vec, + #[serde(skip_deserializing)] + pub voluntary_exits: Vec, + #[serde(skip_deserializing)] + pub sync_aggregate: Option>, + pub execution_payload: ExecutionPayload, + #[serde(skip_deserializing)] + pub bls_to_execution_changes: Vec, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlockMessageData { + #[serde(deserialize_with = "string_to_u256_base10")] + pub slot: U256, + pub proposer_index: String, + pub parent_root: String, + pub state_root: String, + pub body: BeaconBlockBody, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlockMessage { + pub message: BlockMessageData, + pub signature: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlockResponse { + pub execution_optimistic: Option, + pub finalized: Option, + pub data: BlockMessage, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlockRoot { + pub root: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlockRootResponse { + pub execution_optimistic: Option, + pub finalized: Option, + pub data: BlockRoot, +} diff --git a/coral-lib/src/services/beacon/types/genesis.rs b/coral-lib/src/services/beacon/types/genesis.rs new file mode 100644 index 0000000..0e57888 --- /dev/null +++ b/coral-lib/src/services/beacon/types/genesis.rs @@ -0,0 +1,52 @@ +use ethers::utils::hex::{self}; + +use serde::Deserialize; + +use crate::{ + error::{AppError, AppErrorKind, AppResult}, + strip_0x_prefix, + structs::eth_types::ForkVersion, +}; + +#[derive(Clone, Debug, Deserialize)] +pub struct BeaconGenesis { + pub genesis_time: String, + pub genesis_validators_root: String, + pub genesis_fork_version: String, +} + +impl BeaconGenesis { + pub fn fork_version_as_fixed(&self) -> AppResult { + let genesis_fork_version: &str = strip_0x_prefix!(self.genesis_fork_version); + let genesis_fork_version: ForkVersion = hex::decode(genesis_fork_version) + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "Failed to decode hex".to_string(), + ) + })? + .as_slice() + .try_into() + .map_err(|_err| { + AppError::new(AppErrorKind::DecodeError, "Invalid length".to_string()) + })?; + Ok(genesis_fork_version) + } + + pub fn genesis_validators_root_as_fixed(&self) -> AppResult<[u8; 32]> { + let genesis_validators_root: &str = strip_0x_prefix!(self.genesis_validators_root); + let genesis_validators_root: [u8; 32] = hex::decode(genesis_validators_root) + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "Failed to decode hex".to_string(), + ) + })? + .as_slice() + .try_into() + .map_err(|_err| { + AppError::new(AppErrorKind::DecodeError, "Invalid length".to_string()) + })?; + Ok(genesis_validators_root) + } +} diff --git a/coral-lib/src/services/beacon/types/mod.rs b/coral-lib/src/services/beacon/types/mod.rs new file mode 100644 index 0000000..d853e90 --- /dev/null +++ b/coral-lib/src/services/beacon/types/mod.rs @@ -0,0 +1,24 @@ +mod attestation_rewards; +mod beacon_block; +mod genesis; +mod state_root; +mod validator; +mod validator_balance; + +#[cfg(test)] +mod state_root_test; + +pub use attestation_rewards::*; +pub use beacon_block::*; +pub use genesis::*; +pub use state_root::*; +pub use validator::*; +pub use validator_balance::*; + +use serde::Deserialize; + +#[derive(Clone, Debug, Deserialize)] +pub struct BeaconResponse { + pub finalized: Option, + pub data: T, +} diff --git a/coral-lib/src/services/beacon/types/state_root.rs b/coral-lib/src/services/beacon/types/state_root.rs new file mode 100644 index 0000000..31e1e4a --- /dev/null +++ b/coral-lib/src/services/beacon/types/state_root.rs @@ -0,0 +1,74 @@ +use ethers::types::{H256, U256}; +use serde::{Deserialize, Serialize}; + +use crate::utils::serialize::u256_serialize; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum StateId { + #[serde(rename = "head")] + Head, + #[serde(rename = "genesis")] + Genesis, + #[serde(rename = "finalized")] + Finalized, + #[serde(rename = "justified")] + Justified, + #[serde(untagged, serialize_with = "u256_serialize")] + Slot(U256), + #[serde(untagged)] + StateRoot(H256), +} + +impl std::fmt::Display for StateId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Head => f.write_str("head"), + Self::Genesis => f.write_str("genesis"), + Self::Finalized => f.write_str("finalized"), + Self::Justified => f.write_str("justified"), + Self::Slot(s) => f.write_str(&format!("{}", s)), + Self::StateRoot(s) => f.write_str(&format!("0x{:x}", s)), + } + } +} + +#[derive(Clone, Debug, Deserialize)] +pub struct StateRootData { + pub root: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct StateRootResponse { + pub execution_optimistic: bool, + pub finalized: bool, + pub data: StateRootData, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum BlockId { + #[serde(rename = "head")] + Head, + #[serde(rename = "genesis")] + Genesis, + #[serde(rename = "finalized")] + Finalized, + #[serde(rename = "justified")] + Justified, + #[serde(untagged, serialize_with = "u256_serialize")] + Slot(U256), + #[serde(untagged)] + BlockRoot(String), +} + +impl std::fmt::Display for BlockId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Head => f.write_str("head"), + Self::Genesis => f.write_str("genesis"), + Self::Finalized => f.write_str("finalized"), + Self::Justified => f.write_str("justified"), + Self::Slot(s) => f.write_str(&s.to_string()), + Self::BlockRoot(s) => f.write_str(&s.to_string()), + } + } +} diff --git a/coral-lib/src/services/beacon/types/state_root_test.rs b/coral-lib/src/services/beacon/types/state_root_test.rs new file mode 100644 index 0000000..130e93a --- /dev/null +++ b/coral-lib/src/services/beacon/types/state_root_test.rs @@ -0,0 +1,76 @@ +use ethers::types::{H256, U256}; +use serde_json::json; + +use super::StateId; + +#[test] +pub fn test_serialize_state_id() { + let values = [ + (StateId::Head, "head"), + (StateId::Genesis, "genesis"), + (StateId::Finalized, "finalized"), + (StateId::Justified, "justified"), + (StateId::Slot(U256::from(1000)), "1000"), + ( + StateId::StateRoot(H256::from_low_u64_be(123)), + "0x000000000000000000000000000000000000000000000000000000000000007b", + ), + ]; + + for (value, value_str) in values { + let commit = json!({ + "value": value, + }); + + let json = serde_json::to_string(&commit).unwrap(); + assert_eq!(json, format!("{{\"value\":\"{value_str}\"}}")) + } +} + +#[test] +fn test_deserialize_state_id() { + let values = [ + (StateId::Head, "head"), + (StateId::Genesis, "genesis"), + (StateId::Finalized, "finalized"), + (StateId::Justified, "justified"), + (StateId::Slot(U256::from(1000)), "1000"), + ( + StateId::StateRoot(H256::from_low_u64_be(123)), + "0x000000000000000000000000000000000000000000000000000000000000007b", + ), + ]; + + for (value, value_str) in values { + let commit = json!({ + "value": value, + }); + let commit_str = format!("{{\"value\":\"{value_str}\"}}"); + + let json: serde_json::Value = serde_json::from_str(&commit_str).unwrap(); + assert_eq!(commit, json); + } +} + +#[test] +pub fn test_display_state_id() { + let values = [ + (StateId::Head, "head"), + (StateId::Genesis, "genesis"), + (StateId::Finalized, "finalized"), + (StateId::Justified, "justified"), + ( + StateId::Slot(U256::from(1000).saturating_mul(U256::from(10000000000000000000u64))), + "10000000000000000000000", + ), + ( + StateId::StateRoot(H256::from_low_u64_be(123)), + "0x000000000000000000000000000000000000000000000000000000000000007b", + ), + ]; + + for (value, value_str) in values { + let result_str = format!("{}", value); + assert_eq!(result_str, value_str) + } +} diff --git a/coral-lib/src/services/beacon/types/validator.rs b/coral-lib/src/services/beacon/types/validator.rs new file mode 100644 index 0000000..9da2bf7 --- /dev/null +++ b/coral-lib/src/services/beacon/types/validator.rs @@ -0,0 +1,73 @@ +use ethers::types::U256; +use serde::Deserialize; + +use crate::utils::serialize::{string_to_u256_base10, string_to_u64}; + +use super::BeaconResponse; + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +pub enum ValidatorId { + Pubkey(String), + Index(u64), +} + +impl std::fmt::Display for ValidatorId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Pubkey(key) => f.write_str(key), + Self::Index(index) => f.write_str(&format!("{}", *index)), + } + } +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +pub enum ValidatorStatus { + #[serde(rename = "pending_initialized")] + PendingInitialized, + #[serde(rename = "pending_queued")] + PendingQueued, + #[serde(rename = "active_ongoing")] + ActiveOngoing, + #[serde(rename = "active_exiting")] + ActiveExiting, + #[serde(rename = "active_slashed")] + ActiveSlashed, + #[serde(rename = "exited_unslashed")] + ExitedUnslashed, + #[serde(rename = "exited_slashed")] + ExitedSlashed, + #[serde(rename = "withdrawal_possible")] + WithdrawalPossible, + #[serde(rename = "withdrawal_done")] + WithdrawalDone, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct ValidatorStats { + pub pubkey: String, + pub withdrawal_credentials: String, + #[serde(deserialize_with = "string_to_u256_base10")] + pub effective_balance: U256, + pub slashed: bool, + #[serde(deserialize_with = "string_to_u64")] + pub activation_eligibility_epoch: u64, + #[serde(deserialize_with = "string_to_u64")] + pub activation_epoch: u64, + #[serde(deserialize_with = "string_to_u64")] + pub exit_epoch: u64, + #[serde(deserialize_with = "string_to_u64")] + pub withdrawable_epoch: u64, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct ValidatorData { + #[serde(deserialize_with = "string_to_u64")] + pub index: u64, + #[serde(deserialize_with = "string_to_u256_base10")] + pub balance: U256, + pub status: ValidatorStatus, + pub validator: ValidatorStats, +} + +pub type ValidatorResponse = BeaconResponse; +pub type ValidatorListResponse = BeaconResponse>; diff --git a/coral-lib/src/services/beacon/types/validator_balance.rs b/coral-lib/src/services/beacon/types/validator_balance.rs new file mode 100644 index 0000000..23aa3d1 --- /dev/null +++ b/coral-lib/src/services/beacon/types/validator_balance.rs @@ -0,0 +1,12 @@ +use ethers::types::U256; +use serde::Deserialize; + +use super::BeaconResponse; + +#[derive(Clone, Debug, Deserialize)] +pub struct ValidatorBalance { + pub id: u64, + pub balance: U256, +} + +pub type ValidatorBalancesResponse = BeaconResponse>; diff --git a/coral-lib/src/services/mod.rs b/coral-lib/src/services/mod.rs new file mode 100644 index 0000000..f66e2a0 --- /dev/null +++ b/coral-lib/src/services/mod.rs @@ -0,0 +1 @@ +pub mod beacon; diff --git a/coral-lib/src/utils/abi/abi_test.rs b/coral-lib/src/utils/abi/abi_test.rs new file mode 100644 index 0000000..7e12863 --- /dev/null +++ b/coral-lib/src/utils/abi/abi_test.rs @@ -0,0 +1,95 @@ +// use ethers::utils::hex::{FromHex, ToHex}; +// use puffersecuresigner::{ +// enclave::types::KeyGenResponse, io::remote_attestation::AttestationEvidence, +// }; +// use crate::utils; + +/* +const KEYGEN_TEST_RESPONSE: &str = + include_str!("../../../../mock-server/test_data/keygen_response_001.json"); + +const REPORT_CALLDATA: &str = + include_str!("../../../../mock-server/test_data/keygen_response_001_report_calldata.txt"); +const RAVE_CALLDATA: &str = + include_str!("../../../../mock-server/test_data/keygen_response_001_rave_calldata.txt"); + +#[test] +fn test_extract_x509_valid() { + let report: KeyGenResponse = serde_json::from_str(KEYGEN_TEST_RESPONSE).unwrap(); + + let (leaf_x509, root_x509) = + utils::ssl::extract_x509(report.evidence.signing_cert.as_bytes()).unwrap(); + + assert_eq!( + true, + utils::ssl::verify_intel_sgx_root_ca(&root_x509).is_ok() + ); + assert_eq!( + true, + utils::ssl::verify_intel_sgx_attestation_report(&leaf_x509).is_ok() + ); +} + +#[test] +fn test_raw_report_calldata_valid() { + let report: KeyGenResponse = serde_json::from_str(KEYGEN_TEST_RESPONSE).unwrap(); + let evidence = &report.evidence; + let raw_report = + utils::abi::intel_report::deserialize_report(evidence.raw_report.as_bytes()).unwrap(); + + let actual = utils::abi::intel_report::to_calldata(&raw_report).unwrap(); + let expected: Vec = >::from_hex(REPORT_CALLDATA).unwrap(); + + assert_eq!(expected.len(), actual.len()); + assert_eq!(expected, actual); +} + +#[test] +fn test_rave_calldata_generate_json() { + const KEYGEN_RESPONSE_JSON: &str = include_str!("../../../../mock-server/test_data/0x8144e74faf431dad80831ef0dddca2302f9a913bc0c2fdfafaeacac05cdb173b.json"); + + let report: KeyGenResponse = serde_json::from_str(KEYGEN_RESPONSE_JSON).unwrap(); + let attestation_report = + utils::abi::intel_report::deserialize_report(report.evidence.raw_report.as_bytes()) + .unwrap(); + + let report_json = utils::abi::intel_report::to_json(&attestation_report).unwrap(); + println!("{}", report_json); + + let rave_json = utils::abi::rave_evidence::to_json(&report, &attestation_report).unwrap(); + println!("{}", rave_json); + + let report_calldata = utils::abi::intel_report::to_calldata(&attestation_report).unwrap(); + println!( + "report calldata: '{}'", + report_calldata.encode_hex::() + ); +} + +#[test] +fn test_rave_calldata_generate_json_from_keygen() { + let report = KeyGenResponse { + pk_hex: "0x04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd".to_string(), + evidence: AttestationEvidence { + raw_report: "{\"id\":\"186453210057823126547835745110511429060\",\"timestamp\":\"2023-10-16T20:17:59.516859\",\"version\":4,\"epidPseudonym\":\"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhspNWPNBkpcmwf+3WZYsuncw6eX6Uijk+PzPp3dBQSebHsOEQYDRxGeFuWowvkTo2Z5HTavyoRIrSupBTqDE78HA=\",\"advisoryURL\":\"https://security-center.intel.com\",\"advisoryIDs\":[\"INTEL-SA-00334\",\"INTEL-SA-00615\"],\"isvEnclaveQuoteStatus\":\"SW_HARDENING_NEEDED\",\"isvEnclaveQuoteBody\":\"AgABAKwMAAANAA0AAAAAAEJhbJjVPJcSY5RHybDnAD8AAAAAAAAAAAAAAAAAAAAAFRULB/+ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAfAAAAAAAAAI63DnajS/bL+d7tf0Z7SIjMGH8fHzTM4tEcpUAUFJo1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGGfbNg35+DFwYIjUiKm+84K8beqRS7hF/CO4eKrj1YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}".to_string(), + signed_report: "LDx4Yimeh/lB5amkm5ahvJ4v7E/BXp6mTow9akiUy+9DMkisIUAvFlBik2sS/9dea4xAFcNJkbdaVYOQQ03LcKGE4k/sOPUJKYJiga4xeT6gL8O1HwCZBun+u/IKvs7jKy27gx9ne6usvEBXAwxGUK1Ng9xbayiu94tJwmd3wEgghWvTbFFPDoaTwLp82UoZHSQY8rDX0lMwE+WpgVs8t4WwV1ZIJnt5kMBwsmYUsd4Ylq3mORNkFX6+BhEreohP8FlYbLpPaKAqJEATbhb1ubZb4NIII863c8khkfxhXLq1aLgJtb7q1HIBFhI4uWgV8OnSw3xEAOSseU3PKxs1mQ==".to_string(), + signing_cert: "-----BEGIN CERTIFICATE-----\nMIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\nBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV\nBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0\nYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIw\nMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1Nh\nbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwk\nSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+t\nbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtId\ncv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuv\nLUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhA\nImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8\ngZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGh\nMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIG\nwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVk\nc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJl\ncG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4r\nRq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9\nlpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYv\nWLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUd\nZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY\n6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW7\n2uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2\ntQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbq\nd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\nBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV\nBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0\nYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy\nMzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL\nU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD\nDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G\nCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR+tXc8u1EtJzLA10Feu1Wg+p7e\nLmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh\nrgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT\nL/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe\nNpEJUmg4ktal4qgIAxk+QHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ\nbyinkNndn+Bgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H\nafuVeLHcDsRp6hol4P+ZFIhu8mmbI1u0hH3W/0C2BuYXB5PC+5izFFh/nP0lc2Lf\n6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM\nRoOaX4AS+909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX\nMFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50\nL0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW\nBBR4Q3t2pn680K9+QjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9+Qjfr\nNXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq\nhkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir\nIEqucRiJSSx+HjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi+ripMtPZ\nsFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi\nzLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra\nUd4APK0wZTGtfPXU7w+IBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA\n152Sq049ESDz+1rRGc2NVEqh1KaGXmtXvqxXcTB+Ljy5Bw2ke0v8iGngFBPqCTVB\n3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5+xmBc388v9Dm21HGfcC8O\nDD+gT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R+mJTLwPXVMrv\nDaVzWh5aiEx+idkSGMnX\n-----END CERTIFICATE-----\n".to_string(), + }, + }; + let attestation_report = + utils::abi::intel_report::deserialize_report(report.evidence.raw_report.as_bytes()); + let attestation_report = attestation_report.unwrap(); + + println!("===========REPORT============"); + let report_json = utils::abi::intel_report::to_json(&attestation_report).unwrap(); + println!("{}", report_json); + + println!("===========RAVE============"); + let rave_json = utils::abi::rave_evidence::to_json(&report, &attestation_report).unwrap(); + println!("{}", rave_json); + + println!("==========CALLDATA========="); + let report_calldata = utils::abi::intel_report::to_calldata(&attestation_report).unwrap(); + println!("{}", report_calldata.encode_hex::()); +} + */ diff --git a/coral-lib/src/utils/abi/intel_report.rs b/coral-lib/src/utils/abi/intel_report.rs new file mode 100644 index 0000000..8c95181 --- /dev/null +++ b/coral-lib/src/utils/abi/intel_report.rs @@ -0,0 +1,233 @@ +use ethers::abi; +use ethers::utils::hex::ToHex; + +use axum::http::StatusCode; +use puffersecuresigner::io::remote_attestation::AttestationReport; + +use crate::error::{AppServerResult, ServerErrorResponse}; +use crate::utils; + +pub fn deserialize_report(b: &[u8]) -> AppServerResult { + let report: AttestationReport = serde_json::from_slice(b).map_err(|err| { + tracing::error!("Failed to parse attestation report"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to parse attestation report", + ) + })?; + Ok(report) +} + +pub fn to_json(report: &AttestationReport) -> AppServerResult { + let decoded_quote_body = utils::encoding::base64_decode_to_bytes(&report.isvEnclaveQuoteBody)?; + let advisory_ids = serde_json::to_string(&report.advisoryIDs).map_err(|err| { + tracing::error!("Failed to serialize advisoryIDs"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to serialize advisoryIDs", + ) + })?; + + let json_data = serde_json::json!({ + "id": report.id, + "timestamp": report.timestamp, + "version": report.version, + "epidPseudonym": report.epidPseudonym, + "advisoryURL": report.advisoryURL, + "advisoryIds": advisory_ids, + "isvEnclaveQuoteStatus": report.isvEnclaveQuoteStatus, + "isvEnclaveQuoteBody": decoded_quote_body.encode_hex::(), + }); + + let json_data = serde_json::json!({ + "report": json_data + }); + + let json_string = serde_json::to_string(&json_data).map_err(|err| { + tracing::error!("Failed to serialize json"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to serialize json", + ) + })?; + Ok(json_string) +} + +pub fn to_calldata_with_decoded_quote_body( + attestation_report: &AttestationReport, +) -> AppServerResult { + let decoded_quote_body = + utils::encoding::base64_decode_to_bytes(&attestation_report.isvEnclaveQuoteBody)?; + + let advisory_ids = serde_json::to_string(&attestation_report.advisoryIDs).map_err(|err| { + tracing::error!("Failed to serialize advisoryIDs"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to serialize advisoryIDs", + ) + })?; + + let calldata = abi::encode(&[ + abi::Token::Bytes(attestation_report.id.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.timestamp.as_bytes().to_vec()), + abi::Token::Bytes( + format!("{}", attestation_report.version) + .as_bytes() + .to_vec(), + ), + abi::Token::Bytes(attestation_report.epidPseudonym.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.advisoryURL.as_bytes().to_vec()), + abi::Token::Bytes(advisory_ids.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.isvEnclaveQuoteStatus.as_bytes().to_vec()), + abi::Token::Bytes(decoded_quote_body.to_vec()), + ]); + Ok(calldata) +} + +pub fn to_calldata(attestation_report: &AttestationReport) -> AppServerResult { + let advisory_ids = serde_json::to_string(&attestation_report.advisoryIDs).map_err(|err| { + tracing::error!("Failed to serialize advisoryIDs"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to serialize advisoryIDs", + ) + })?; + + let calldata = abi::encode(&[ + abi::Token::Bytes(attestation_report.id.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.timestamp.as_bytes().to_vec()), + abi::Token::Bytes( + format!("{}", attestation_report.version) + .as_bytes() + .to_vec(), + ), + abi::Token::Bytes(attestation_report.epidPseudonym.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.advisoryURL.as_bytes().to_vec()), + abi::Token::Bytes(advisory_ids.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.isvEnclaveQuoteStatus.as_bytes().to_vec()), + abi::Token::Bytes(attestation_report.isvEnclaveQuoteBody.as_bytes().to_vec()), + ]); + Ok(calldata) +} + +pub fn from_calldata(data: &[u8]) -> AppServerResult { + let calldata_tokens = abi::decode( + &[ + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + ], + data, + ) + .map_err(|err| { + let error_msg = "Failed to parse report calldata"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let report_data = match calldata_tokens.as_slice() { + [abi::Token::Bytes(id), abi::Token::Bytes(timestamp), abi::Token::Bytes(version), abi::Token::Bytes(epid_pseudonym), abi::Token::Bytes(advisory_url), abi::Token::Bytes(advisory_ids), abi::Token::Bytes(isv_enclave_quote_status), abi::Token::Bytes(encoded_quote_body), ..] => + { + let id = String::from_utf8(id.clone()).map_err(|err| { + let error_msg = "Failed to decode report calldata fields"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let timestamp = String::from_utf8(timestamp.clone()).map_err(|err| { + let error_msg = "Failed to decode report calldata fields"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let version: u32 = { + let s = String::from_utf8(version.clone()).map_err(|err| { + let error_msg = "Failed to decode report calldata fields"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + s.parse::().map_err(|err| { + let error_msg = "Failed to decode report calldata fields"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })? + }; + + let epid_pseudonym = String::from_utf8(epid_pseudonym.clone()).map_err(|err| { + let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let advisory_url = String::from_utf8(advisory_url.clone()).map_err(|err| { + let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let isv_enclave_quote_status = String::from_utf8(isv_enclave_quote_status.clone()) + .map_err(|err| { + let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let encoded_quote_body = + String::from_utf8(encoded_quote_body.clone()).map_err(|err| { + let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let advisory_ids: Vec = + serde_json::from_slice(advisory_ids).map_err(|err| { + let error_msg = "Failed to decode report calldata advisory_ids"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + AttestationReport { + id, + timestamp, + version, + epidPseudonym: epid_pseudonym, + advisoryURL: advisory_url, + advisoryIDs: advisory_ids, + isvEnclaveQuoteStatus: isv_enclave_quote_status, + isvEnclaveQuoteBody: encoded_quote_body, + } + } + _ => { + let error_msg = "Invalid report calldata"; + tracing::error!("{error_msg}"); + let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); + return Err(err); + } + }; + Ok(report_data) +} diff --git a/coral-lib/src/utils/abi/mod.rs b/coral-lib/src/utils/abi/mod.rs new file mode 100644 index 0000000..5a01cb1 --- /dev/null +++ b/coral-lib/src/utils/abi/mod.rs @@ -0,0 +1,10 @@ +pub mod intel_report; +pub mod rave_evidence; +pub mod validator_key_data; + +#[cfg(test)] +mod abi_test; + +// Intel SGX constants +pub const SIGNING_MOD: &str = "9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; +pub const SIGNING_EXP: &str = "010001"; diff --git a/coral-lib/src/utils/abi/rave_evidence.rs b/coral-lib/src/utils/abi/rave_evidence.rs new file mode 100644 index 0000000..41c270b --- /dev/null +++ b/coral-lib/src/utils/abi/rave_evidence.rs @@ -0,0 +1,106 @@ +use ethers::abi; +use ethers::utils::hex::ToHex; + +use axum::http::StatusCode; +use puffersecuresigner::enclave::types::KeyGenResponse; +use puffersecuresigner::io::remote_attestation::AttestationReport; + +use crate::error::{AppServerResult, ServerErrorResponse}; +use crate::utils; + +use super::{SIGNING_EXP, SIGNING_MOD}; + +#[derive(Clone, Debug)] +pub struct AbiDecodedRaveData { + pub enclave_report: Vec, + pub enclave_sig: Vec, + pub enclave_x509: Vec, +} + +pub fn to_json( + report: &KeyGenResponse, + attestation_report: &AttestationReport, +) -> AppServerResult { + let evidence = &report.evidence; + let signature = utils::encoding::base64_decode_to_bytes(&evidence.signed_report)?; + + let (leaf_x509, _) = utils::ssl::extract_x509(report.evidence.signing_cert.as_bytes())?; + let leaf_x509_der = leaf_x509.to_der().map_err(|err| { + let msg = "Failed to convert x509 to DER format"; + tracing::error!(msg); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, msg) + })?; + + let quote_body = attestation_report.deserialize_quote_body().unwrap(); + + let json_data = serde_json::json!({ + "evidence": report.evidence, + "signature": signature.encode_hex::(), + "leaf_x509": leaf_x509_der.encode_hex::(), + "mr_enclave": quote_body.MRENCLAVE, + "mr_signer": quote_body.MRSIGNER, + "signing_mod": SIGNING_MOD, + "signing_exp": SIGNING_EXP, + }); + + let json_string = serde_json::to_string(&json_data).map_err(|err| { + tracing::error!("Failed to serialize json"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to serialize json", + ) + })?; + Ok(json_string) +} + +pub fn to_calldata( + enclave_report: &[u8], + enclave_sig: &[u8], + enclave_x509: &[u8], +) -> AppServerResult { + let rave_evidence = abi::encode(&[ + abi::Token::Bytes(enclave_report.into()), + abi::Token::Bytes(enclave_sig.into()), + abi::Token::Bytes(enclave_x509.to_vec()), + ]); + Ok(rave_evidence) +} + +pub fn from_calldata(data: &[u8]) -> AppServerResult { + let calldata_tokens = abi::decode( + &[ + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::Bytes, + ], + data, + ) + .map_err(|err| { + let error_msg = "Failed to parse RAVE calldata"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + // eprintln!("RAVE_calldata: {:?}", calldata_tokens); + + let rave_data = match calldata_tokens.as_slice() { + [abi::Token::Bytes(enclave_report), abi::Token::Bytes(enclave_sig), abi::Token::Bytes(enclave_x509), ..] => { + AbiDecodedRaveData { + enclave_report: enclave_report.clone(), + enclave_sig: enclave_sig.clone(), + enclave_x509: enclave_x509.clone(), + } + } + _ => { + let error_msg = "Invalid RAVE calldata"; + tracing::error!("{error_msg}"); + let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); + return Err(err); + } + }; + Ok(rave_data) +} diff --git a/coral-lib/src/utils/abi/validator_key_data.rs b/coral-lib/src/utils/abi/validator_key_data.rs new file mode 100644 index 0000000..689da7f --- /dev/null +++ b/coral-lib/src/utils/abi/validator_key_data.rs @@ -0,0 +1,95 @@ +use ethers::{abi, prelude::*}; + +use axum::http::StatusCode; +use puffer_pool_contracts::withdrawal_pool::ValidatorKeyData; + +use crate::error::{AppServerResult, ServerErrorResponse}; + +pub fn from_calldata(tx_data: &[u8]) -> AppServerResult<(ValidatorKeyData, Vec, U256)> { + let calldata_tokens = abi::decode( + &[ + abi::ParamType::Tuple(vec![ + abi::ParamType::Bytes, + abi::ParamType::Bytes, + abi::ParamType::FixedBytes(32), + abi::ParamType::Array(Box::new(abi::ParamType::Bytes)), + abi::ParamType::Bytes, + abi::ParamType::Bytes, + ]), + abi::ParamType::FixedBytes(32), + abi::ParamType::Uint(256), + ], + tx_data, + ) + .map_err(|err| { + let error_msg = "Failed to parse register validator calldata"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let (key_data, module_name, number_of_months) = match calldata_tokens.as_slice() { + [abi::Token::Tuple(data), abi::Token::FixedBytes(module_name), abi::Token::Uint(number_of_months), ..] => + { + if data.len() != 6 { + let error_msg = "ValidatorKeyData parameters incorrect"; + tracing::error!("{error_msg}"); + let err = + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); + return Err(err); + } + + let key_data: ValidatorKeyData = match data.as_slice() { + [abi::Token::Bytes(bls_pub_key), abi::Token::Bytes(signature), abi::Token::FixedBytes(deposit_data_root), abi::Token::Array(bls_encrypted_priv_key_shares), abi::Token::Bytes(bls_pub_key_set), abi::Token::Bytes(rave_evidence)] => + { + let bls_encrypted_priv_key_shares = bls_encrypted_priv_key_shares + .iter() + .filter_map(|item| match item { + abi::Token::Bytes(b) => Some(b.clone().into()), + _ => None, + }) + .collect(); + + let deposit_data_root: [u8; 32] = + deposit_data_root.clone().try_into().map_err(|_| { + let error_msg = "Failed to parse calldata"; + tracing::error!("{error_msg}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + error_msg, + ) + })?; + + ValidatorKeyData { + bls_pub_key: bls_pub_key.clone().into(), + signature: signature.clone().into(), + deposit_data_root, + bls_encrypted_priv_key_shares, + bls_pub_key_set: bls_pub_key_set.clone().into(), + rave_evidence: rave_evidence.clone().into(), + } + } + _ => { + let error_msg = "Invalid calldata"; + tracing::error!("{error_msg}"); + let err = ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + error_msg, + ); + return Err(err); + } + }; + + (key_data, module_name.clone(), *number_of_months) + } + _ => { + let error_msg = "Invalid register validator calldata"; + tracing::error!("{error_msg}"); + let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); + return Err(err); + } + }; + Ok((key_data, module_name, number_of_months)) +} diff --git a/coral-lib/src/utils/encoding.rs b/coral-lib/src/utils/encoding.rs new file mode 100644 index 0000000..ab6c444 --- /dev/null +++ b/coral-lib/src/utils/encoding.rs @@ -0,0 +1,69 @@ +use axum::http::StatusCode; +use base64::Engine; +use reqwest::Response; +use serde::de::DeserializeOwned; + +use crate::error::{AppServerResult, ServerErrorResponse}; + +pub fn base64_encode_to_bytes(s: &[u8]) -> AppServerResult { + let res = base64::engine::general_purpose::STANDARD.encode(s); + Ok(res) +} + +pub fn base64_decode_to_bytes(s: &str) -> AppServerResult> { + let res = base64::engine::general_purpose::STANDARD + .decode(s.as_bytes()) + .map_err(|err| { + tracing::error!("Failed to base64 decode"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to decode base64 decode", + ) + })?; + Ok(res) +} + +pub fn base64_decode_to_string(s: &str) -> AppServerResult { + let vec_bytes = base64_decode_to_bytes(s)?; + let new_string = String::from_utf8(vec_bytes).map_err(|err| { + tracing::error!("Failed to decode to utf8"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to decode decode to utf8", + ) + })?; + + Ok(new_string) +} + +pub async fn parse_json_response(resp: Response) -> AppServerResult { + if !resp.status().is_success() { + let body = resp.text().await.map_err(|err| { + tracing::error!("Failed to parse body"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to parse body", + ) + })?; + tracing::error!("Body: {}", body); + let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, &body); + return Err(err); + } + + let resp_json: T = resp.json().await.map_err(|err| { + tracing::error!("Failed to parse JSON"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to parse JSON", + ) + })?; + Ok(resp_json) +} diff --git a/coral-lib/src/utils/encoding_test.rs b/coral-lib/src/utils/encoding_test.rs new file mode 100644 index 0000000..e69de29 diff --git a/coral-lib/src/utils/ethereum.rs b/coral-lib/src/utils/ethereum.rs new file mode 100644 index 0000000..a856e90 --- /dev/null +++ b/coral-lib/src/utils/ethereum.rs @@ -0,0 +1,96 @@ +use std::sync::Arc; + +use axum::http::StatusCode; +use ethers::prelude::*; + +use crate::error::{AppServerResult, ServerErrorResponse}; + +pub fn get_provider(rpc_url: &str) -> AppServerResult> { + let provider = Provider::::try_from(rpc_url).map_err(|err| { + tracing::error!("Invalid RPC URL"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::BAD_REQUEST, 1000, "Invalid RPC URL") + })?; + Ok(provider) +} + +pub fn get_client( + provider: Provider, + wallet: LocalWallet, + chain_id: u64, +) -> Arc, LocalWallet>> +where + J: JsonRpcClient, +{ + let client = SignerMiddleware::new(provider, wallet.with_chain_id(chain_id)); + Arc::new(client) +} + +pub async fn get_chain_id(provider: &Provider) -> AppServerResult +where + J: JsonRpcClient, +{ + let chain_id = provider.get_chainid().await.map_err(|err| { + tracing::error!("Failed to retrieve Chain ID"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to retrieve Chain ID", + ) + })?; + Ok(chain_id) +} + +pub async fn get_block( + provider: &Provider, + block_number: BlockNumber, +) -> AppServerResult> +where + J: JsonRpcClient, +{ + let block = provider + .get_block(block_number) + .await + .map_err(|err| { + tracing::error!("Failed to fetch block"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to fetch block", + ) + })? + .ok_or_else(|| { + tracing::error!("Block does not exist"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Block does not exist", + ) + })?; + Ok(block) +} + +pub async fn get_balance( + provider: &Provider, + address: Address, + block_id: BlockId, +) -> AppServerResult +where + J: JsonRpcClient, +{ + let balance = provider + .get_balance(address, Some(block_id)) + .await + .map_err(|err| { + tracing::error!("Failed to get balance of address"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to get balance of address", + ) + })?; + Ok(balance) +} diff --git a/coral-lib/src/utils/mod.rs b/coral-lib/src/utils/mod.rs new file mode 100644 index 0000000..fe470d7 --- /dev/null +++ b/coral-lib/src/utils/mod.rs @@ -0,0 +1,8 @@ +pub mod abi; +pub mod encoding; +pub mod ethereum; +pub mod parse; +pub mod serialize; +pub mod ssl; +pub mod validator; +pub mod wallet; diff --git a/coral-lib/src/utils/parse.rs b/coral-lib/src/utils/parse.rs new file mode 100644 index 0000000..53f6632 --- /dev/null +++ b/coral-lib/src/utils/parse.rs @@ -0,0 +1,48 @@ +use axum::http::StatusCode; + +use ethers::utils::hex::{self}; + +use crate::{ + error::{AppServerResult, ServerErrorResponse}, + strip_0x_prefix, +}; + +pub fn parse_module_name(module_name: &str) -> AppServerResult<[u8; 32]> { + let mut module_name: String = strip_0x_prefix!(&module_name); + if module_name.len() > 64 { + let err = ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + &format!("Invalid module value: '{}'", module_name), + ); + return Err(err); + } + + for _ in module_name.len()..64 { + module_name.push('0'); + } + + let module_name_vec: Vec = hex::decode(&module_name).map_err(|err| { + let error_msg = "Failed to decode module name"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + let module_name: [u8; 32] = module_name_vec.as_slice().try_into().map_err(|err| { + let error_msg = "Module name length incorrect"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + Ok(module_name) +} + +pub fn parse_withdrawal_credentials(val: &[u8]) -> AppServerResult<[u8; 32]> { + let withdrawal_credentials: [u8; 32] = val.try_into().map_err(|err| { + let error_msg = "Failed to parse withdrawal_credentials"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::BAD_REQUEST, 1000, error_msg) + })?; + Ok(withdrawal_credentials) +} diff --git a/coral-lib/src/utils/serialize.rs b/coral-lib/src/utils/serialize.rs new file mode 100644 index 0000000..0ef0850 --- /dev/null +++ b/coral-lib/src/utils/serialize.rs @@ -0,0 +1,27 @@ +use ethers::types::U256; +use serde::{de, Deserialize, Deserializer}; + +pub fn string_to_u64<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(deserializer)?; + // do better hex decoding than this + s.parse::() + .map_err(|_| de::Error::custom("failed to parse u64".to_string())) +} + +pub fn string_to_u256_base10<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(deserializer)?; + U256::from_str_radix(s, 10).map_err(|_| de::Error::custom("failed to parse U256".to_string())) +} + +pub fn u256_serialize(val: &U256, serializer: S) -> Result +where + S: serde::Serializer, +{ + serializer.serialize_str(&val.to_string()) +} diff --git a/coral-lib/src/utils/ssl.rs b/coral-lib/src/utils/ssl.rs new file mode 100644 index 0000000..016197b --- /dev/null +++ b/coral-lib/src/utils/ssl.rs @@ -0,0 +1,107 @@ +use axum::http::StatusCode; +use openssl::x509::X509; + +use crate::error::{AppServerResult, ServerErrorResponse}; + +pub fn extract_x509(signing_cert: &[u8]) -> AppServerResult<(X509, X509)> { + let x509s = X509::stack_from_pem(signing_cert).map_err(|err| { + tracing::error!("Failed to parse x509 cert"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to parse x509 cert", + ) + })?; + + // Extract intel's signing certificate + + let (signing_x509, root_x509) = match x509s.as_slice() { + [signing_x509, root_x509] => (signing_x509.to_owned(), root_x509.to_owned()), + _ => { + tracing::error!("Failed to split x509 cert"); + return Err(ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to split x509 cert", + )); + } + }; + Ok((signing_x509, root_x509)) +} + +pub fn verify_intel_sgx_attestation_report(x509: &X509) -> AppServerResult<()> { + match x509 + .subject_name() + .entries_by_nid(openssl::nid::Nid::COMMONNAME) + .last() + { + Some(name) => { + let n = name + .data() + .as_utf8() + .map_err(|err| { + tracing::debug!("Failed to convert to UTF-8"); + tracing::debug!("{}", err); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to convert to UTF-8", + ) + })? + .to_string(); + if n.as_str() != "Intel SGX Attestation Report Signing" { + Err(ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Invalid attestation", + )) + } else { + Ok(()) + } + } + None => Err(ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Invalid attestation", + )), + } +} + +pub fn verify_intel_sgx_root_ca(x509: &X509) -> AppServerResult<()> { + match x509 + .subject_name() + .entries_by_nid(openssl::nid::Nid::COMMONNAME) + .last() + { + Some(name) => { + let n = name + .data() + .as_utf8() + .map_err(|err| { + tracing::debug!("Failed to convert to UTF-8"); + tracing::debug!("{}", err); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to convert to UTF-8", + ) + })? + .to_string(); + if n.as_str() != "Intel SGX Attestation Report Signing CA" { + Err(ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Invalid attestation", + )) + } else { + Ok(()) + } + } + None => Err(ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Invalid attestation", + )), + } +} diff --git a/coral-lib/src/utils/validator.rs b/coral-lib/src/utils/validator.rs new file mode 100644 index 0000000..167647f --- /dev/null +++ b/coral-lib/src/utils/validator.rs @@ -0,0 +1,79 @@ +use std::sync::Arc; + +use axum::http::StatusCode; + +use ethers::prelude::*; +use ethers::types::Address; +use ethers::types::Log; +use ethers::utils::keccak256; + +use puffer_pool_contracts::puffer_protocol::PufferProtocol; + +use crate::error::{AppServerResult, ServerErrorResponse}; + +pub async fn find_register_validator_event_by_index( + client: Arc, LocalWallet>>, + puffer_protocol_address: Address, + validator_index: U256, +) -> AppServerResult +where + J: JsonRpcClient, +{ + let contract: PufferProtocol<_> = PufferProtocol::new(puffer_protocol_address, client.clone()); + let filter = contract + .validator_key_registered_filter() + .filter + .address(puffer_protocol_address) + .from_block(0); + + let logs = client.get_logs(&filter).await.map_err(|err| { + let error_msg = "Failed to get logs"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + for log in logs { + let log_validator_index = U256::from_big_endian(log.topics[2].as_bytes()); + if log_validator_index == validator_index { + return Ok(log); + } + } + + let err = ServerErrorResponse::new(StatusCode::NOT_FOUND, 1000, "Validator event not found"); + Err(err) +} + +pub async fn find_register_validator_event_by_address( + client: Arc, LocalWallet>>, + puffer_protocol_address: Address, + validator_address: Vec, +) -> AppServerResult +where + J: JsonRpcClient, +{ + let contract: PufferProtocol<_> = PufferProtocol::new(puffer_protocol_address, client.clone()); + let filter = contract + .validator_key_registered_filter() + .filter + .address(puffer_protocol_address) + .from_block(0); + + let logs = client.get_logs(&filter).await.map_err(|err| { + let error_msg = "Failed to get logs"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let hashed_address = keccak256(validator_address); + for log in logs { + let bls_key = log.topics[1]; + if *bls_key.as_fixed_bytes() == hashed_address { + return Ok(log); + } + } + + let err = ServerErrorResponse::new(StatusCode::NOT_FOUND, 1000, "Validator event not found"); + Err(err) +} diff --git a/coral-lib/src/utils/wallet.rs b/coral-lib/src/utils/wallet.rs new file mode 100644 index 0000000..a80464e --- /dev/null +++ b/coral-lib/src/utils/wallet.rs @@ -0,0 +1,80 @@ +use std::fs; +use std::io::prelude::Read; +use std::path; + +use axum::http::StatusCode; +use ethers::prelude::k256::ecdsa::SigningKey; +use ethers::prelude::*; +use rand_core::OsRng; + +use crate::{ + error::{AppError, AppErrorKind, AppResult, AppServerResult, ServerErrorResponse}, + strip_0x_prefix, +}; + +pub fn generate_keystore(password: &str) -> AppServerResult<(Wallet, String)> { + let (new_wallet, keystore_uuid) = Wallet::new_keystore(".", &mut OsRng, password, None) + .map_err(|err| { + tracing::error!("Failed to generate keystore"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to generate keystore", + ) + })?; + + // Ethers Keystore API must be generated and stored in a file. + // So we have to read from it and delete it after + let keystore_json = { + let mut file = fs::File::open(&keystore_uuid).map_err(|err| { + tracing::error!("Failed to read keystore"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to read keystore", + ) + })?; + let mut contents = String::new(); + file.read_to_string(&mut contents).map_err(|err| { + tracing::error!("Failed to read keystore to string"); + tracing::error!("{err}"); + ServerErrorResponse::new( + StatusCode::INTERNAL_SERVER_ERROR, + 1000, + "Failed to read keystore to string", + ) + })?; + + // remove file after reading it + let _ = fs::remove_file(&keystore_uuid); + contents + }; + + Ok((new_wallet, keystore_json)) +} + +pub fn read_key_from_file>(file_path: P) -> std::io::Result { + let key_content = std::fs::read_to_string(file_path)?; + let key_content: String = strip_0x_prefix!(key_content.trim()); + Ok(key_content) +} + +pub fn private_key_file_to_wallet>( + private_key_path: P, +) -> AppResult { + let private_key = read_key_from_file(private_key_path)?; + let wallet: LocalWallet = private_key.parse().map_err(|err| { + tracing::error!("Invalid private key: '{}'", private_key); + tracing::error!("{err}"); + AppError::new(AppErrorKind::ParseError, "Invalid private key".to_string()) + })?; + Ok(wallet) +} + +/// Generate a random wallet. +/// Mostly used for calling view and pure functions +pub fn generate_random_wallet() -> LocalWallet { + LocalWallet::new(&mut rand::thread_rng()) +} From b7c328e4ea975ceb7e2ab25530765b1dc6d3cef6 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:31:34 +0100 Subject: [PATCH 03/11] add first version for sign _vem command --- Cargo.lock | 522 +++++++++--------- coral-cli/src/commands/validator/mod.rs | 41 ++ .../commands/validator/register_validator.rs | 2 - coral-cli/src/commands/validator/sign_vem.rs | 204 +++++++ coral-lib/Cargo.toml | 5 + .../beacon/fetch_puffer_validator_stats.rs | 50 +- .../src/services/beacon/types/genesis.rs | 2 +- coral-lib/src/utils/abi/mod.rs | 1 - coral-lib/src/utils/abi/validator_key_data.rs | 95 ---- coral-lib/src/utils/mod.rs | 1 - coral-lib/src/utils/parse.rs | 6 +- coral-lib/src/utils/validator.rs | 79 --- coral-lib/src/utils/wallet.rs | 8 +- 13 files changed, 509 insertions(+), 507 deletions(-) create mode 100644 coral-cli/src/commands/validator/sign_vem.rs delete mode 100644 coral-lib/src/utils/abi/validator_key_data.rs delete mode 100644 coral-lib/src/utils/validator.rs diff --git a/Cargo.lock b/Cargo.lock index 0253372..b19ea92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -88,9 +88,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" dependencies = [ "anstyle", "anstyle-parse", @@ -102,9 +102,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -136,9 +136,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "array-init" @@ -178,7 +178,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -200,14 +200,13 @@ checksum = "3c1e7e457ea78e524f48639f551fd79703ac3f2237f5ecccdf4708f8a75ad373" [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.50", ] [[package]] @@ -262,7 +261,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "http-body-util", - "hyper 1.1.0", + "hyper 1.2.0", "hyper-util", "itoa", "matchit", @@ -330,7 +329,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -350,7 +349,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "smallvec 1.11.2", + "smallvec 1.13.1", "tokio", "url", ] @@ -423,9 +422,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -534,15 +533,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.5", "serde", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "byte-slice-cast" @@ -597,9 +596,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -620,11 +619,10 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" dependencies = [ - "jobserver", "libc", ] @@ -636,16 +634,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.3", ] [[package]] @@ -660,9 +658,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.14" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -670,42 +668,42 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.14" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", ] [[package]] name = "clap_complete" -version = "4.4.6" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" +checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "coins-bip32" @@ -777,9 +775,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5104de16b218eddf8e34ffe2f86f74bfa4e61e95a1b89732fccf6325efd0557" +checksum = "18d59688ad0945eaf6b84cb44fedbe93484c81b48970e98f09db8a22832d7961" dependencies = [ "cfg-if", "cpufeatures", @@ -839,9 +837,13 @@ dependencies = [ name = "coral-lib" version = "0.1.0" dependencies = [ + "async-trait", "axum 0.7.4", "base64 0.21.7", "ethers", + "openssl", + "puffersecuresigner", + "rand_core 0.6.4", "reqwest", "serde", "serde_json", @@ -879,9 +881,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -978,7 +980,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] @@ -1149,9 +1151,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "elliptic-curve" @@ -1298,7 +1300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "948e343aa022785c07193f41ed37adfd9dd0350368060803b8302c7f798e8306" dependencies = [ "ethereum-types 0.12.1", - "smallvec 1.11.2", + "smallvec 1.13.1", ] [[package]] @@ -1323,7 +1325,7 @@ dependencies = [ "eth2_ssz", "serde", "serde_derive", - "smallvec 1.11.2", + "smallvec 1.13.1", "tree_hash", "typenum", ] @@ -1482,7 +1484,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.48", + "syn 2.0.50", "toml", "walkdir", ] @@ -1500,7 +1502,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1526,7 +1528,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.48", + "syn 2.0.50", "tempfile", "thiserror", "tiny-keccak", @@ -1666,9 +1668,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -1859,7 +1861,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1876,9 +1878,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ "gloo-timers", "send_wrapper 0.4.0", @@ -1995,9 +1997,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -2014,9 +2016,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991910e35c615d8cab86b5ab04be67e6ad24d2bf5f4f11fdbbed26da999bbeab" +checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" dependencies = [ "bytes", "fnv", @@ -2054,9 +2056,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hex" @@ -2202,7 +2204,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.22", + "h2 0.3.24", "http 0.2.11", "http-body 0.4.6", "httparse", @@ -2218,20 +2220,21 @@ dependencies = [ [[package]] name = "hyper" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.1", + "h2 0.4.2", "http 1.0.0", "http-body 1.0.0", "httparse", "httpdate", "itoa", "pin-project-lite", + "smallvec 1.13.1", "tokio", ] @@ -2264,27 +2267,25 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ "bytes", - "futures-channel", "futures-util", "http 1.0.0", "http-body 1.0.0", - "hyper 1.1.0", + "hyper 1.2.0", "pin-project-lite", "socket2", "tokio", - "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2383,9 +2384,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown", @@ -2417,12 +2418,12 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix", + "libc", "windows-sys 0.52.0", ] @@ -2450,20 +2451,11 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" -[[package]] -name = "jobserver" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -2498,9 +2490,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -2541,9 +2533,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libm" @@ -2557,7 +2549,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall", ] @@ -2612,9 +2604,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2677,9 +2669,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -2746,21 +2738,26 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -2791,10 +2788,10 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 3.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -2845,11 +2842,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.62" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", "foreign-types", "libc", @@ -2866,7 +2863,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -2877,9 +2874,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.98" +version = "0.9.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" +checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" dependencies = [ "cc", "libc", @@ -2988,7 +2985,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "smallvec 1.11.2", + "smallvec 1.13.1", "windows-targets 0.48.5", ] @@ -3096,7 +3093,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -3119,22 +3116,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -3161,9 +3158,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "polyval" @@ -3202,7 +3199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -3253,42 +3250,18 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2685dd208a3771337d8d386a89840f0f43cd68be8dae90a5f8c2384effc9cd" -dependencies = [ - "toml_edit 0.21.0", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "toml_edit 0.21.1", ] [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -3299,7 +3272,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "lazy_static", "num-traits", "rand", @@ -3312,7 +3285,7 @@ dependencies = [ [[package]] name = "puffersecuresigner" version = "0.1.0" -source = "git+https://github.com/PufferFinance/secure-signer.git#f904718305382b0cf3d956ca48dc828c1990ebe4" +source = "git+https://github.com/PufferFinance/secure-signer.git#36a8c31ef566efaa7d302ce930fec0ef197b93ab" dependencies = [ "anyhow", "async-trait", @@ -3427,9 +3400,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -3437,9 +3410,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3467,13 +3440,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.5", "regex-syntax 0.8.2", ] @@ -3488,9 +3461,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -3526,7 +3499,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.22", + "h2 0.3.24", "http 0.2.11", "http-body 0.4.6", "hyper 0.14.28", @@ -3596,16 +3569,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3662,11 +3636,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", @@ -3680,7 +3654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring 0.17.8", "rustls-webpki", "sct", ] @@ -3700,7 +3674,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -3712,9 +3686,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "salsa20" @@ -3791,7 +3765,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -3834,9 +3808,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] @@ -3855,9 +3829,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -3875,20 +3849,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -4048,18 +4022,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4123,6 +4097,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "strum" version = "0.25.0" @@ -4142,7 +4122,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4153,9 +4133,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "svm-rs" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20689c7d03b6461b502d0b95d6c24874c7d24dea2688af80486a130a06af3b07" +checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" dependencies = [ "dirs", "fs2", @@ -4184,9 +4164,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", @@ -4228,13 +4208,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] @@ -4261,29 +4240,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -4300,12 +4279,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -4320,10 +4300,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -4378,7 +4359,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4459,7 +4440,7 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "toml_datetime", - "winnow 0.5.33", + "winnow 0.5.40", ] [[package]] @@ -4470,18 +4451,18 @@ checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap", "toml_datetime", - "winnow 0.5.33", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap", "toml_datetime", - "winnow 0.5.33", + "winnow 0.5.40", ] [[package]] @@ -4515,13 +4496,12 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e12e6351354851911bdf8c2b8f2ab15050c567d70a8b9a37ae7b8301a4080d" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "bytes", - "futures-util", "http 1.0.0", "http-body 1.0.0", "http-body-util", @@ -4563,7 +4543,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4608,7 +4588,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec 1.11.2", + "smallvec 1.13.1", "thread_local", "tracing", "tracing-core", @@ -4623,7 +4603,7 @@ dependencies = [ "ethereum-types 0.14.1", "lazy_static", "sha2 0.10.8", - "smallvec 1.11.2", + "smallvec 1.13.1", ] [[package]] @@ -4688,9 +4668,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -4700,9 +4680,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -4813,9 +4793,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4823,24 +4803,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -4850,9 +4830,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4860,28 +4840,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", @@ -4889,9 +4869,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "winapi" @@ -4930,7 +4910,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -4948,7 +4928,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -4968,17 +4948,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.3", + "windows_aarch64_msvc 0.52.3", + "windows_i686_gnu 0.52.3", + "windows_i686_msvc 0.52.3", + "windows_x86_64_gnu 0.52.3", + "windows_x86_64_gnullvm 0.52.3", + "windows_x86_64_msvc 0.52.3", ] [[package]] @@ -4989,9 +4969,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" [[package]] name = "windows_aarch64_msvc" @@ -5001,9 +4981,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" [[package]] name = "windows_i686_gnu" @@ -5013,9 +4993,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" [[package]] name = "windows_i686_msvc" @@ -5025,9 +5005,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" [[package]] name = "windows_x86_64_gnu" @@ -5037,9 +5017,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" [[package]] name = "windows_x86_64_gnullvm" @@ -5049,9 +5029,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" [[package]] name = "windows_x86_64_msvc" @@ -5061,15 +5041,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" [[package]] name = "winnow" -version = "0.5.33" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] @@ -5150,7 +5130,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] diff --git a/coral-cli/src/commands/validator/mod.rs b/coral-cli/src/commands/validator/mod.rs index 05cc588..7ecc5b8 100644 --- a/coral-cli/src/commands/validator/mod.rs +++ b/coral-cli/src/commands/validator/mod.rs @@ -1,5 +1,6 @@ pub mod list_keys; pub mod register_validator; +pub mod sign_vem; use std::path::PathBuf; @@ -40,6 +41,24 @@ pub enum ValidatorCommand { #[arg(long = "input-file")] input_file: PathBuf, }, + SignVEM { + #[arg(long = "validator-public-key")] + bls_pukey: String, + #[arg(long = "enclave-url")] + enclave_url: String, + #[arg(long = "beacon-url")] + beacon_url: String, + #[arg(long = "fork-previous-version")] + fork_previous_version: String, + #[arg(long = "fork-current-version")] + fork_current_version: String, + #[arg(long = "epoch")] + epoch: u64, + #[arg(long = "genesis-validators-root")] + genesis_validators_root: String, + #[arg(long = "output-file")] + output_file: String, + }, } impl ValidatorCommand { @@ -75,6 +94,28 @@ impl ValidatorCommand { Self::RegisterWithFile { input_file } => { register_validator::register_validator_from_file(input_file.as_path()).await?; } + Self::SignVEM { + enclave_url, + bls_pukey, + beacon_url, + fork_current_version, + fork_previous_version, + epoch, + genesis_validators_root, + output_file, + } => { + sign_vem::sign_vem_from_cmd( + enclave_url, + bls_pukey, + beacon_url, + fork_current_version, + fork_previous_version, + epoch, + genesis_validators_root, + output_file, + ) + .await?; + } } Ok(0) } diff --git a/coral-cli/src/commands/validator/register_validator.rs b/coral-cli/src/commands/validator/register_validator.rs index 79b7aac..b28acde 100644 --- a/coral-cli/src/commands/validator/register_validator.rs +++ b/coral-cli/src/commands/validator/register_validator.rs @@ -42,7 +42,6 @@ pub struct RegisterValidatorInput { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct RegisterValidatorOutput { pub guardian_threshold: u64, - pub bls_pub_key_set: String, pub bls_pub_key: String, pub signature: String, @@ -177,7 +176,6 @@ pub async fn register_validator(input_data: &RegisterValidatorInput) -> AppResul } // enclave - validator_enclave_client .attest_fresh_bls_key(&enclave_payload) .await diff --git a/coral-cli/src/commands/validator/sign_vem.rs b/coral-cli/src/commands/validator/sign_vem.rs new file mode 100644 index 0000000..f41a645 --- /dev/null +++ b/coral-cli/src/commands/validator/sign_vem.rs @@ -0,0 +1,204 @@ +use axum::http::StatusCode; +use coral_lib::add_0x_prefix; +use coral_lib::error::{AppError, AppErrorKind, AppResult, ServerErrorResponse}; +use coral_lib::services::beacon::{ + client::{BeaconClient, BeaconClientTrait}, + types::StateId, + types::ValidatorId, +}; +use puffersecuresigner::client::{traits::ValidatorClientTrait, ClientBuilder}; +use puffersecuresigner::eth2::eth_types::{Fork, ForkInfo, Root}; +use puffersecuresigner::strip_0x_prefix; +use std::io::Write; +use serde::{Serialize, Deserialize}; +use coral_lib::structs::eth_types::ForkVersion; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ExitResponseOutput { + pub signature: String, + pub beacon_index: u64, + pub epoch: u64, + pub bls_pubkey: String, +} + +#[derive(Clone, Debug)] +pub struct SignVoluntaryExitMessageInput { + pub bls_pubkey: String, + pub enclave_url: String, + pub beacon_url: String, + pub fork: Fork, + pub genesis_validators_root: [u8; 32], + pub output_file: String, +} + +#[allow(clippy::too_many_arguments)] +pub async fn sign_vem_from_cmd( + enclave_url: String, + bls_pubkey: String, + beacon_url: String, + fork_current_version: String, + fork_previous_version: String, + epoch: u64, + genesis_validators_root: String, + output_file: String, +) -> AppResult { + let converted_fork_info: ForkInfo = convert_to_fork_formats( + fork_current_version, + fork_previous_version, + epoch, + genesis_validators_root, + ) + .unwrap(); + + let input_data = SignVoluntaryExitMessageInput { + bls_pubkey, + enclave_url, + beacon_url, + fork: converted_fork_info.fork, + genesis_validators_root: converted_fork_info.genesis_validators_root, + output_file, + }; + sign_voluntary_exit_message(input_data).await +} + +pub async fn sign_voluntary_exit_message( + input_data: SignVoluntaryExitMessageInput, +) -> AppResult { + let enclave_url = input_data.enclave_url; + + let enclave_client = ClientBuilder::new() + .validator_url(enclave_url.to_string()) + .build(); + let beacon_client = BeaconClient::new(input_data.beacon_url.to_string()); + let validator_enclave_client = enclave_client.validator; + + let health_status = validator_enclave_client.health().await; + if !health_status { + let err = AppError::new( + AppErrorKind::EnclaveError, + "Enclave health check failed".to_string(), + ); + return Err(err); + } + + let bls_public_key = add_0x_prefix(&input_data.bls_pubkey); + + let validator_resp = beacon_client + .fetch_validator( + StateId::Finalized, + ValidatorId::Pubkey(bls_public_key.clone()), + ) + .await?; + + let beacon_index = validator_resp.data.index; + let fork_info = ForkInfo { + fork: Fork { + previous_version: input_data.fork.previous_version, + current_version: input_data.fork.current_version, + epoch: input_data.fork.epoch, + }, + genesis_validators_root: input_data.genesis_validators_root, + }; + + let sign_exit_resp = validator_enclave_client + .sign_voluntary_exit_message( + bls_public_key, + fork_info.fork.epoch, + beacon_index, + fork_info.clone(), + ) + .await + .map_err(|err| { + let error_msg = "Failed to sign_voluntary_exit_message"; + tracing::error!("{error_msg}"); + tracing::error!("{err}"); + ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) + })?; + + let epoch = fork_info.clone().fork.epoch; + let exit_payload = ExitResponseOutput { + signature: sign_exit_resp.signature, + beacon_index, + epoch, + bls_pubkey: input_data.bls_pubkey, + }; + + let json_string_pretty = serde_json::to_string_pretty(&exit_payload)?; + println!("{}", json_string_pretty); + + { + let mut file = std::fs::File::create(&input_data.output_file)?; + file.write_all(json_string_pretty.as_bytes())?; + } + + Ok(0) +} + +// Helper to convert from String to Fork formats +fn convert_to_fork_formats( + fork_current_version: String, + fork_previous_version: String, + epoch: u64, + genesis_validators_root: String, +) -> AppResult { + let previous_version: &str = strip_0x_prefix!(fork_previous_version.as_str()); + let fork_previous_version: ForkVersion = hex::decode(previous_version) + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "fork.previous_version: Failed to decode hex".to_string(), + ) + })? + .as_slice() + .try_into() + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "fork.previous_version: Invalid length".to_string(), + ) + })?; + let current_version: &str = strip_0x_prefix!(fork_current_version.as_str()); + let fork_current_version: ForkVersion = hex::decode(current_version) + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "fork.current_version: Failed to decode hex".to_string(), + ) + })? + .as_slice() + .try_into() + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "fork.current_version: Invalid length".to_string(), + ) + })?; + + let genesis_validators_root: &str = strip_0x_prefix!(genesis_validators_root.as_str()); + let genesis_validators_root: Root = hex::decode(genesis_validators_root) + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "genesis_validators_root: Failed to decode hex".to_string(), + ) + })? + .as_slice() + .try_into() + .map_err(|_err| { + AppError::new( + AppErrorKind::DecodeError, + "fork.genesis_validators_root: Invalid length".to_string(), + ) + })?; + + let fork_config = ForkInfo { + fork: Fork { + current_version: fork_current_version, + previous_version: fork_previous_version, + epoch, + }, + genesis_validators_root, + }; + + Ok(fork_config) +} diff --git a/coral-lib/Cargo.toml b/coral-lib/Cargo.toml index 04bd681..b6e91d2 100644 --- a/coral-lib/Cargo.toml +++ b/coral-lib/Cargo.toml @@ -4,9 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] +async-trait = "0.1.77" axum = "0.7.4" base64 = "0.21.7" ethers = "2.0.13" +openssl = "0.10.64" +rand_core = "0.6.4" reqwest = { version = "0.11.24", features = ["json"] } serde = { version = "1.0.195", features = ["derive"] } serde_json = "1.0.111" @@ -15,3 +18,5 @@ toml = "0.8.10" tower-http = { version = "0.5.0", features = [ "cors", "trace" ] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } + +puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git" } diff --git a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs index 02e2e57..4b32335 100644 --- a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs +++ b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs @@ -1,12 +1,11 @@ use std::collections::HashMap; use ethers::prelude::*; -// use puffer_pool_contracts::withdrawal_pool::Validator; use crate::error::AppServerResult; use crate::services::beacon::types::ValidatorData; use crate::services::beacon::SLOTS_PER_EPOCH; -use crate::strip_0x_prefix; + use super::client::BeaconClientTrait; use super::types::{BlockId, ValidatorStatus}; @@ -198,50 +197,3 @@ pub fn calculate_puffer_validator_beacon_balances( } validator_balance.saturating_mul(U256::exp10(9)) } - -/// Calculates Puffer Validator balances with their -/// pufETH bond accounted for. If their pufETH bond can cover -/// their losses, then their effective balance should be 32 ETH. -pub fn calculate_puffer_validator_beacon_balances_with_puf_eth_bond( - puffer_validators: &HashMap, - validators_by_index: &HashMap, - end_epoch: U256, - puf_eth_to_eth: U256, -) -> U256 { - let gwei_32 = U256::from(32).saturating_mul(U256::exp10(9)); - - let mut validator_balance = U256::zero(); - for (_, validator) in validators_by_index.iter() { - let is_active = is_active_validator(validator, end_epoch.as_u64()); - // Edge case where validator just registered and is waiting to - // start validating - #[allow(clippy::if_same_then_else)] - if validator.status == ValidatorStatus::PendingQueued { - validator_balance += gwei_32; - } else if is_active { - if validator.balance == U256::zero() { - validator_balance += gwei_32; - } else if validator.balance >= gwei_32 { - validator_balance += validator.balance; - } else { - let validator_address: &str = strip_0x_prefix!(validator.validator.pubkey); - if let Some(validator_sc) = puffer_validators.get(validator_address) { - let bond_eth_value = - U256::from(validator_sc.bond).saturating_mul(puf_eth_to_eth); - - let double_validator_balance = validator.balance.saturating_mul(U256::from(2)); - let gwei_64 = gwei_32.saturating_mul(U256::from(2)); - - // The idea is we want to have the bond account for - // double the discrepancy to be conservative, hence the U256::from(2) - if double_validator_balance + bond_eth_value >= gwei_64 { - validator_balance += gwei_32; - } else { - validator_balance += validator.balance; - } - } - } - } - } - validator_balance.saturating_mul(U256::exp10(9)) -} diff --git a/coral-lib/src/services/beacon/types/genesis.rs b/coral-lib/src/services/beacon/types/genesis.rs index 0e57888..0229f70 100644 --- a/coral-lib/src/services/beacon/types/genesis.rs +++ b/coral-lib/src/services/beacon/types/genesis.rs @@ -4,9 +4,9 @@ use serde::Deserialize; use crate::{ error::{AppError, AppErrorKind, AppResult}, - strip_0x_prefix, structs::eth_types::ForkVersion, }; +use puffersecuresigner::strip_0x_prefix; #[derive(Clone, Debug, Deserialize)] pub struct BeaconGenesis { diff --git a/coral-lib/src/utils/abi/mod.rs b/coral-lib/src/utils/abi/mod.rs index 5a01cb1..a076f47 100644 --- a/coral-lib/src/utils/abi/mod.rs +++ b/coral-lib/src/utils/abi/mod.rs @@ -1,6 +1,5 @@ pub mod intel_report; pub mod rave_evidence; -pub mod validator_key_data; #[cfg(test)] mod abi_test; diff --git a/coral-lib/src/utils/abi/validator_key_data.rs b/coral-lib/src/utils/abi/validator_key_data.rs deleted file mode 100644 index 689da7f..0000000 --- a/coral-lib/src/utils/abi/validator_key_data.rs +++ /dev/null @@ -1,95 +0,0 @@ -use ethers::{abi, prelude::*}; - -use axum::http::StatusCode; -use puffer_pool_contracts::withdrawal_pool::ValidatorKeyData; - -use crate::error::{AppServerResult, ServerErrorResponse}; - -pub fn from_calldata(tx_data: &[u8]) -> AppServerResult<(ValidatorKeyData, Vec, U256)> { - let calldata_tokens = abi::decode( - &[ - abi::ParamType::Tuple(vec![ - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::FixedBytes(32), - abi::ParamType::Array(Box::new(abi::ParamType::Bytes)), - abi::ParamType::Bytes, - abi::ParamType::Bytes, - ]), - abi::ParamType::FixedBytes(32), - abi::ParamType::Uint(256), - ], - tx_data, - ) - .map_err(|err| { - let error_msg = "Failed to parse register validator calldata"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let (key_data, module_name, number_of_months) = match calldata_tokens.as_slice() { - [abi::Token::Tuple(data), abi::Token::FixedBytes(module_name), abi::Token::Uint(number_of_months), ..] => - { - if data.len() != 6 { - let error_msg = "ValidatorKeyData parameters incorrect"; - tracing::error!("{error_msg}"); - let err = - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); - return Err(err); - } - - let key_data: ValidatorKeyData = match data.as_slice() { - [abi::Token::Bytes(bls_pub_key), abi::Token::Bytes(signature), abi::Token::FixedBytes(deposit_data_root), abi::Token::Array(bls_encrypted_priv_key_shares), abi::Token::Bytes(bls_pub_key_set), abi::Token::Bytes(rave_evidence)] => - { - let bls_encrypted_priv_key_shares = bls_encrypted_priv_key_shares - .iter() - .filter_map(|item| match item { - abi::Token::Bytes(b) => Some(b.clone().into()), - _ => None, - }) - .collect(); - - let deposit_data_root: [u8; 32] = - deposit_data_root.clone().try_into().map_err(|_| { - let error_msg = "Failed to parse calldata"; - tracing::error!("{error_msg}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - error_msg, - ) - })?; - - ValidatorKeyData { - bls_pub_key: bls_pub_key.clone().into(), - signature: signature.clone().into(), - deposit_data_root, - bls_encrypted_priv_key_shares, - bls_pub_key_set: bls_pub_key_set.clone().into(), - rave_evidence: rave_evidence.clone().into(), - } - } - _ => { - let error_msg = "Invalid calldata"; - tracing::error!("{error_msg}"); - let err = ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - error_msg, - ); - return Err(err); - } - }; - - (key_data, module_name.clone(), *number_of_months) - } - _ => { - let error_msg = "Invalid register validator calldata"; - tracing::error!("{error_msg}"); - let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); - return Err(err); - } - }; - Ok((key_data, module_name, number_of_months)) -} diff --git a/coral-lib/src/utils/mod.rs b/coral-lib/src/utils/mod.rs index fe470d7..2e06d02 100644 --- a/coral-lib/src/utils/mod.rs +++ b/coral-lib/src/utils/mod.rs @@ -4,5 +4,4 @@ pub mod ethereum; pub mod parse; pub mod serialize; pub mod ssl; -pub mod validator; pub mod wallet; diff --git a/coral-lib/src/utils/parse.rs b/coral-lib/src/utils/parse.rs index 53f6632..9a64658 100644 --- a/coral-lib/src/utils/parse.rs +++ b/coral-lib/src/utils/parse.rs @@ -2,10 +2,8 @@ use axum::http::StatusCode; use ethers::utils::hex::{self}; -use crate::{ - error::{AppServerResult, ServerErrorResponse}, - strip_0x_prefix, -}; +use crate::error::{AppServerResult, ServerErrorResponse}; +use puffersecuresigner::strip_0x_prefix; pub fn parse_module_name(module_name: &str) -> AppServerResult<[u8; 32]> { let mut module_name: String = strip_0x_prefix!(&module_name); diff --git a/coral-lib/src/utils/validator.rs b/coral-lib/src/utils/validator.rs deleted file mode 100644 index 167647f..0000000 --- a/coral-lib/src/utils/validator.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::sync::Arc; - -use axum::http::StatusCode; - -use ethers::prelude::*; -use ethers::types::Address; -use ethers::types::Log; -use ethers::utils::keccak256; - -use puffer_pool_contracts::puffer_protocol::PufferProtocol; - -use crate::error::{AppServerResult, ServerErrorResponse}; - -pub async fn find_register_validator_event_by_index( - client: Arc, LocalWallet>>, - puffer_protocol_address: Address, - validator_index: U256, -) -> AppServerResult -where - J: JsonRpcClient, -{ - let contract: PufferProtocol<_> = PufferProtocol::new(puffer_protocol_address, client.clone()); - let filter = contract - .validator_key_registered_filter() - .filter - .address(puffer_protocol_address) - .from_block(0); - - let logs = client.get_logs(&filter).await.map_err(|err| { - let error_msg = "Failed to get logs"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - for log in logs { - let log_validator_index = U256::from_big_endian(log.topics[2].as_bytes()); - if log_validator_index == validator_index { - return Ok(log); - } - } - - let err = ServerErrorResponse::new(StatusCode::NOT_FOUND, 1000, "Validator event not found"); - Err(err) -} - -pub async fn find_register_validator_event_by_address( - client: Arc, LocalWallet>>, - puffer_protocol_address: Address, - validator_address: Vec, -) -> AppServerResult -where - J: JsonRpcClient, -{ - let contract: PufferProtocol<_> = PufferProtocol::new(puffer_protocol_address, client.clone()); - let filter = contract - .validator_key_registered_filter() - .filter - .address(puffer_protocol_address) - .from_block(0); - - let logs = client.get_logs(&filter).await.map_err(|err| { - let error_msg = "Failed to get logs"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let hashed_address = keccak256(validator_address); - for log in logs { - let bls_key = log.topics[1]; - if *bls_key.as_fixed_bytes() == hashed_address { - return Ok(log); - } - } - - let err = ServerErrorResponse::new(StatusCode::NOT_FOUND, 1000, "Validator event not found"); - Err(err) -} diff --git a/coral-lib/src/utils/wallet.rs b/coral-lib/src/utils/wallet.rs index a80464e..7e5ecb3 100644 --- a/coral-lib/src/utils/wallet.rs +++ b/coral-lib/src/utils/wallet.rs @@ -6,11 +6,11 @@ use axum::http::StatusCode; use ethers::prelude::k256::ecdsa::SigningKey; use ethers::prelude::*; use rand_core::OsRng; +use puffersecuresigner::strip_0x_prefix; -use crate::{ - error::{AppError, AppErrorKind, AppResult, AppServerResult, ServerErrorResponse}, - strip_0x_prefix, -}; +use crate:: + error::{AppError, AppErrorKind, AppResult, AppServerResult, ServerErrorResponse} +; pub fn generate_keystore(password: &str) -> AppServerResult<(Wallet, String)> { let (new_wallet, keystore_uuid) = Wallet::new_keystore(".", &mut OsRng, password, None) From f27e7961eed3baa7457d679051668db9d2221089 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:40:32 +0100 Subject: [PATCH 04/11] fmt --- coral-cli/src/commands/validator/sign_vem.rs | 4 ++-- coral-lib/src/lib.rs | 2 +- .../src/services/beacon/fetch_puffer_validator_stats.rs | 1 - coral-lib/src/utils/wallet.rs | 6 ++---- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/coral-cli/src/commands/validator/sign_vem.rs b/coral-cli/src/commands/validator/sign_vem.rs index f41a645..6e845db 100644 --- a/coral-cli/src/commands/validator/sign_vem.rs +++ b/coral-cli/src/commands/validator/sign_vem.rs @@ -6,12 +6,12 @@ use coral_lib::services::beacon::{ types::StateId, types::ValidatorId, }; +use coral_lib::structs::eth_types::ForkVersion; use puffersecuresigner::client::{traits::ValidatorClientTrait, ClientBuilder}; use puffersecuresigner::eth2::eth_types::{Fork, ForkInfo, Root}; use puffersecuresigner::strip_0x_prefix; +use serde::{Deserialize, Serialize}; use std::io::Write; -use serde::{Serialize, Deserialize}; -use coral_lib::structs::eth_types::ForkVersion; #[derive(Serialize, Deserialize, Debug)] pub struct ExitResponseOutput { diff --git a/coral-lib/src/lib.rs b/coral-lib/src/lib.rs index 3c326f8..d1960ee 100644 --- a/coral-lib/src/lib.rs +++ b/coral-lib/src/lib.rs @@ -1,6 +1,6 @@ pub mod error; -pub mod structs; pub mod services; +pub mod structs; pub mod utils; #[inline] diff --git a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs index 4b32335..1d4912a 100644 --- a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs +++ b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs @@ -6,7 +6,6 @@ use crate::error::AppServerResult; use crate::services::beacon::types::ValidatorData; use crate::services::beacon::SLOTS_PER_EPOCH; - use super::client::BeaconClientTrait; use super::types::{BlockId, ValidatorStatus}; use super::{is_active_validator, is_full_withdrawal}; diff --git a/coral-lib/src/utils/wallet.rs b/coral-lib/src/utils/wallet.rs index 7e5ecb3..9022d8a 100644 --- a/coral-lib/src/utils/wallet.rs +++ b/coral-lib/src/utils/wallet.rs @@ -5,12 +5,10 @@ use std::path; use axum::http::StatusCode; use ethers::prelude::k256::ecdsa::SigningKey; use ethers::prelude::*; -use rand_core::OsRng; use puffersecuresigner::strip_0x_prefix; +use rand_core::OsRng; -use crate:: - error::{AppError, AppErrorKind, AppResult, AppServerResult, ServerErrorResponse} -; +use crate::error::{AppError, AppErrorKind, AppResult, AppServerResult, ServerErrorResponse}; pub fn generate_keystore(password: &str) -> AppServerResult<(Wallet, String)> { let (new_wallet, keystore_uuid) = Wallet::new_keystore(".", &mut OsRng, password, None) From 0dfefbdff9209c0efd69146cd8267541ce8aa110 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Fri, 23 Feb 2024 20:33:47 +0100 Subject: [PATCH 05/11] improve docs --- coral-cli/docs/validator.md | 15 +++++++++++++++ coral-cli/src/commands/validator/mod.rs | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/coral-cli/docs/validator.md b/coral-cli/docs/validator.md index 73927d7..5d3a365 100644 --- a/coral-cli/docs/validator.md +++ b/coral-cli/docs/validator.md @@ -17,4 +17,19 @@ coral-cli validator register \ --withdrawal-credentials 0x01000000000000000000000049ce199bba75926ab5c6fc16fedd11d418cb2edf --output-file registration_001.json \ --guardian-pubkeys 0x040783e639f5675cd12c86bab61678a2c4be44846b36df9a9648970ea803e92fd8dd25c51660b64f61d20fc04c77c34145410496fd923309a5c143b9c5eadd19e7 +``` + +## `validator sign-voluntary-exit` +Sign voluntary exit message and stop validating + +``` +coral-cli validator sign-voluntary-exit \ + --bls_pukey 0x0439afaa6c9c26c342c7463d8fd116d72f18ed1980a10bd6a2707a2a498315bb17ff4352b91c18b2d34391503fe15fe48b42f95fafc96d4a758172de61dd9a91e7 \ + --enclave-url http://localhost:9001 \ + --beacon_url http://localhost:5052 \ + --fork-previous-version 0x01017000 \ + --fork-current-version 0x01017000 \ + --epoch 5 + --genesis_validators_root 0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69 \ + --output-file registration_001.json \ ``` \ No newline at end of file diff --git a/coral-cli/src/commands/validator/mod.rs b/coral-cli/src/commands/validator/mod.rs index 7ecc5b8..7f19f0e 100644 --- a/coral-cli/src/commands/validator/mod.rs +++ b/coral-cli/src/commands/validator/mod.rs @@ -41,7 +41,7 @@ pub enum ValidatorCommand { #[arg(long = "input-file")] input_file: PathBuf, }, - SignVEM { + SignVoluntaryExit { #[arg(long = "validator-public-key")] bls_pukey: String, #[arg(long = "enclave-url")] @@ -94,7 +94,7 @@ impl ValidatorCommand { Self::RegisterWithFile { input_file } => { register_validator::register_validator_from_file(input_file.as_path()).await?; } - Self::SignVEM { + Self::SignVoluntaryExit { enclave_url, bls_pukey, beacon_url, From 5bb842c9f045b5c2ad75470ee40eedd6eaf5ed29 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Fri, 23 Feb 2024 20:36:14 +0100 Subject: [PATCH 06/11] add sign vem to docs --- coral-cli/docs/validator.md | 1 + 1 file changed, 1 insertion(+) diff --git a/coral-cli/docs/validator.md b/coral-cli/docs/validator.md index 89211e6..313691d 100644 --- a/coral-cli/docs/validator.md +++ b/coral-cli/docs/validator.md @@ -2,6 +2,7 @@ - [list-keys](#validator-list-keys) - [register](#validator-register) + - [sign-voluntary-exit](#validator-sign-voluntary-exit) ## `validator list-keys` List keys associated with this node From 3f42364b8bc60eb4ff83353ee2cf913474a6f2e7 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:25:07 +0100 Subject: [PATCH 07/11] remove beacon part --- coral-cli/src/commands/validator/sign_vem.rs | 22 +- coral-lib/src/lib.rs | 3 +- .../services/beacon/attestation_rewards.rs | 48 ---- coral-lib/src/services/beacon/client.rs | 78 ------ coral-lib/src/services/beacon/fetch_block.rs | 77 ------ .../src/services/beacon/fetch_genesis.rs | 40 --- .../beacon/fetch_puffer_validator_stats.rs | 198 --------------- .../src/services/beacon/fetch_state_root.rs | 37 --- .../src/services/beacon/fetch_validator.rs | 79 ------ .../src/services/beacon/fetch_validators.rs | 123 --------- coral-lib/src/services/beacon/mock_client.rs | 118 --------- coral-lib/src/services/beacon/mod.rs | 34 --- coral-lib/src/services/beacon/submit_exit.rs | 60 ----- .../beacon/types/attestation_rewards.rs | 31 --- .../src/services/beacon/types/beacon_block.rs | 99 -------- .../src/services/beacon/types/genesis.rs | 52 ---- coral-lib/src/services/beacon/types/mod.rs | 24 -- .../src/services/beacon/types/state_root.rs | 74 ------ .../services/beacon/types/state_root_test.rs | 76 ------ .../src/services/beacon/types/validator.rs | 73 ------ .../beacon/types/validator_balance.rs | 12 - coral-lib/src/services/mod.rs | 1 - coral-lib/src/utils/abi/abi_test.rs | 95 ------- coral-lib/src/utils/abi/intel_report.rs | 233 ------------------ coral-lib/src/utils/abi/mod.rs | 9 - coral-lib/src/utils/abi/rave_evidence.rs | 106 -------- coral-lib/src/utils/encoding.rs | 69 ------ coral-lib/src/utils/encoding_test.rs | 0 coral-lib/src/utils/ethereum.rs | 96 -------- coral-lib/src/utils/mod.rs | 7 - coral-lib/src/utils/parse.rs | 46 ---- coral-lib/src/utils/serialize.rs | 27 -- coral-lib/src/utils/ssl.rs | 107 -------- coral-lib/src/utils/wallet.rs | 78 ------ 34 files changed, 7 insertions(+), 2225 deletions(-) delete mode 100644 coral-lib/src/services/beacon/attestation_rewards.rs delete mode 100644 coral-lib/src/services/beacon/client.rs delete mode 100644 coral-lib/src/services/beacon/fetch_block.rs delete mode 100644 coral-lib/src/services/beacon/fetch_genesis.rs delete mode 100644 coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs delete mode 100644 coral-lib/src/services/beacon/fetch_state_root.rs delete mode 100644 coral-lib/src/services/beacon/fetch_validator.rs delete mode 100644 coral-lib/src/services/beacon/fetch_validators.rs delete mode 100644 coral-lib/src/services/beacon/mock_client.rs delete mode 100644 coral-lib/src/services/beacon/mod.rs delete mode 100644 coral-lib/src/services/beacon/submit_exit.rs delete mode 100644 coral-lib/src/services/beacon/types/attestation_rewards.rs delete mode 100644 coral-lib/src/services/beacon/types/beacon_block.rs delete mode 100644 coral-lib/src/services/beacon/types/genesis.rs delete mode 100644 coral-lib/src/services/beacon/types/mod.rs delete mode 100644 coral-lib/src/services/beacon/types/state_root.rs delete mode 100644 coral-lib/src/services/beacon/types/state_root_test.rs delete mode 100644 coral-lib/src/services/beacon/types/validator.rs delete mode 100644 coral-lib/src/services/beacon/types/validator_balance.rs delete mode 100644 coral-lib/src/services/mod.rs delete mode 100644 coral-lib/src/utils/abi/abi_test.rs delete mode 100644 coral-lib/src/utils/abi/intel_report.rs delete mode 100644 coral-lib/src/utils/abi/mod.rs delete mode 100644 coral-lib/src/utils/abi/rave_evidence.rs delete mode 100644 coral-lib/src/utils/encoding.rs delete mode 100644 coral-lib/src/utils/encoding_test.rs delete mode 100644 coral-lib/src/utils/ethereum.rs delete mode 100644 coral-lib/src/utils/mod.rs delete mode 100644 coral-lib/src/utils/parse.rs delete mode 100644 coral-lib/src/utils/serialize.rs delete mode 100644 coral-lib/src/utils/ssl.rs delete mode 100644 coral-lib/src/utils/wallet.rs diff --git a/coral-cli/src/commands/validator/sign_vem.rs b/coral-cli/src/commands/validator/sign_vem.rs index 6e845db..e0a6ebd 100644 --- a/coral-cli/src/commands/validator/sign_vem.rs +++ b/coral-cli/src/commands/validator/sign_vem.rs @@ -1,11 +1,6 @@ use axum::http::StatusCode; use coral_lib::add_0x_prefix; use coral_lib::error::{AppError, AppErrorKind, AppResult, ServerErrorResponse}; -use coral_lib::services::beacon::{ - client::{BeaconClient, BeaconClientTrait}, - types::StateId, - types::ValidatorId, -}; use coral_lib::structs::eth_types::ForkVersion; use puffersecuresigner::client::{traits::ValidatorClientTrait, ClientBuilder}; use puffersecuresigner::eth2::eth_types::{Fork, ForkInfo, Root}; @@ -24,6 +19,7 @@ pub struct ExitResponseOutput { #[derive(Clone, Debug)] pub struct SignVoluntaryExitMessageInput { pub bls_pubkey: String, + pub beacon_index: u64, pub enclave_url: String, pub beacon_url: String, pub fork: Fork, @@ -35,6 +31,7 @@ pub struct SignVoluntaryExitMessageInput { pub async fn sign_vem_from_cmd( enclave_url: String, bls_pubkey: String, + beacon_index: u64, beacon_url: String, fork_current_version: String, fork_previous_version: String, @@ -52,6 +49,7 @@ pub async fn sign_vem_from_cmd( let input_data = SignVoluntaryExitMessageInput { bls_pubkey, + beacon_index, enclave_url, beacon_url, fork: converted_fork_info.fork, @@ -69,7 +67,7 @@ pub async fn sign_voluntary_exit_message( let enclave_client = ClientBuilder::new() .validator_url(enclave_url.to_string()) .build(); - let beacon_client = BeaconClient::new(input_data.beacon_url.to_string()); + let validator_enclave_client = enclave_client.validator; let health_status = validator_enclave_client.health().await; @@ -83,14 +81,6 @@ pub async fn sign_voluntary_exit_message( let bls_public_key = add_0x_prefix(&input_data.bls_pubkey); - let validator_resp = beacon_client - .fetch_validator( - StateId::Finalized, - ValidatorId::Pubkey(bls_public_key.clone()), - ) - .await?; - - let beacon_index = validator_resp.data.index; let fork_info = ForkInfo { fork: Fork { previous_version: input_data.fork.previous_version, @@ -104,7 +94,7 @@ pub async fn sign_voluntary_exit_message( .sign_voluntary_exit_message( bls_public_key, fork_info.fork.epoch, - beacon_index, + input_data.beacon_index, fork_info.clone(), ) .await @@ -118,7 +108,7 @@ pub async fn sign_voluntary_exit_message( let epoch = fork_info.clone().fork.epoch; let exit_payload = ExitResponseOutput { signature: sign_exit_resp.signature, - beacon_index, + beacon_index: input_data.beacon_index, epoch, bls_pubkey: input_data.bls_pubkey, }; diff --git a/coral-lib/src/lib.rs b/coral-lib/src/lib.rs index d1960ee..1b286f0 100644 --- a/coral-lib/src/lib.rs +++ b/coral-lib/src/lib.rs @@ -1,7 +1,6 @@ pub mod error; -pub mod services; pub mod structs; -pub mod utils; + #[inline] pub fn strip_0x_prefix(s: &str) -> &str { diff --git a/coral-lib/src/services/beacon/attestation_rewards.rs b/coral-lib/src/services/beacon/attestation_rewards.rs deleted file mode 100644 index e9b6482..0000000 --- a/coral-lib/src/services/beacon/attestation_rewards.rs +++ /dev/null @@ -1,48 +0,0 @@ -use axum::http::StatusCode; - -use crate::{ - error::{AppServerResult, ServerErrorResponse}, - utils::encoding::parse_json_response, -}; - -use super::types::AttestationRewardsResponse; - -pub async fn get_attestation_rewards( - beacon_url: &str, - epoch: u64, - validators: &[u64], -) -> AppServerResult { - let validators_json_body: String = serde_json::to_string( - &validators - .iter() - .map(|v| v.to_string()) - .collect::>(), - ) - .unwrap(); - - let api_url = format!("{beacon_url}/eth/v1/beacon/rewards/attestations/{epoch}"); - let resp = reqwest::Client::new() - .request(reqwest::Method::POST, api_url) - .body(validators_json_body) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - - let resp_json: AttestationRewardsResponse = parse_json_response(resp).await?; - Ok(resp_json) -} diff --git a/coral-lib/src/services/beacon/client.rs b/coral-lib/src/services/beacon/client.rs deleted file mode 100644 index d2b41fd..0000000 --- a/coral-lib/src/services/beacon/client.rs +++ /dev/null @@ -1,78 +0,0 @@ -use async_trait::async_trait; - -use crate::error::AppServerResult; -use crate::services::beacon; -use crate::services::beacon::types; - -use super::types::{BlockId, StateId, ValidatorId}; - -#[async_trait] -pub trait BeaconClientTrait { - async fn fetch_block(&self, block_id: BlockId) -> AppServerResult; - - async fn fetch_block_root(&self, block_id: BlockId) -> AppServerResult; - - async fn fetch_validator( - &self, - state_id: types::StateId, - validator: ValidatorId, - ) -> AppServerResult; - - async fn fetch_validators_by_pubkey( - &self, - state_id: StateId, - validators: &[String], - ) -> AppServerResult; - - async fn fetch_validators_by_index( - &self, - state_id: StateId, - validators: &[u64], - ) -> AppServerResult; -} - -#[derive(Clone, Debug)] -pub struct BeaconClient { - pub url: String, -} - -impl BeaconClient { - pub fn new(url: String) -> Self { - Self { url } - } -} - -#[async_trait] -impl BeaconClientTrait for BeaconClient { - async fn fetch_block(&self, block_id: BlockId) -> AppServerResult { - beacon::fetch_block::fetch_block(&self.url, block_id).await - } - - async fn fetch_block_root(&self, block_id: BlockId) -> AppServerResult { - beacon::fetch_block::fetch_block_root(&self.url, block_id).await - } - - async fn fetch_validator( - &self, - state_id: types::StateId, - validator: ValidatorId, - ) -> AppServerResult { - beacon::fetch_validator::fetch_validator(&self.url, state_id, validator).await - } - - async fn fetch_validators_by_pubkey( - &self, - state_id: StateId, - validators: &[String], - ) -> AppServerResult { - beacon::fetch_validators::fetch_validators_by_pubkey(&self.url, state_id, validators).await - } - - async fn fetch_validators_by_index( - &self, - state_id: StateId, - validators: &[u64], - ) -> AppServerResult { - beacon::fetch_validators::fetch_validators_by_index(&self.url, state_id, validators).await - } -} diff --git a/coral-lib/src/services/beacon/fetch_block.rs b/coral-lib/src/services/beacon/fetch_block.rs deleted file mode 100644 index 69d835c..0000000 --- a/coral-lib/src/services/beacon/fetch_block.rs +++ /dev/null @@ -1,77 +0,0 @@ -use axum::http::StatusCode; - -use crate::services::beacon::types::{BlockResponse, BlockRootResponse}; -use crate::{ - error::{AppServerResult, ServerErrorResponse}, - utils::encoding::parse_json_response, -}; - -use super::types::BlockId; - -pub async fn fetch_block(beacon_url: &str, block_id: BlockId) -> AppServerResult { - let api_url = format!("{beacon_url}/eth/v2/beacon/blocks/{block_id}"); - tracing::debug!("Beacon: {api_url}"); - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let body = resp.text().await.map_err(|err| { - let error_msg = "Failed to parse body"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - eprintln!("{body}"); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - let resp_json = parse_json_response(resp).await?; - Ok(resp_json) -} - -pub async fn fetch_block_root(beacon_url: &str, block_id: BlockId) -> AppServerResult { - let api_url = format!("{beacon_url}/eth/v1/beacon/blocks/{block_id}/root"); - tracing::debug!("Beacon: {api_url}"); - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let body = resp.text().await.map_err(|err| { - let error_msg = "Failed to parse body"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - eprintln!("{body}"); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - let resp_json: BlockRootResponse = parse_json_response(resp).await?; - Ok(resp_json.data.root) -} diff --git a/coral-lib/src/services/beacon/fetch_genesis.rs b/coral-lib/src/services/beacon/fetch_genesis.rs deleted file mode 100644 index 6d685c0..0000000 --- a/coral-lib/src/services/beacon/fetch_genesis.rs +++ /dev/null @@ -1,40 +0,0 @@ -use axum::http::StatusCode; - -use serde::Deserialize; - -use crate::services::beacon::types::BeaconGenesis; -use crate::{ - error::{AppServerResult, ServerErrorResponse}, - utils::encoding::parse_json_response, -}; - -#[derive(Clone, Debug, Deserialize)] -pub struct BeaconGenesisWrapper { - pub data: BeaconGenesis, -} - -pub async fn fetch_genesis(beacon_url: &str) -> AppServerResult { - let api_url = format!("{beacon_url}/eth/v1/beacon/genesis"); - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - let resp_json: BeaconGenesisWrapper = parse_json_response(resp).await?; - Ok(resp_json.data) -} diff --git a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs b/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs deleted file mode 100644 index 1d4912a..0000000 --- a/coral-lib/src/services/beacon/fetch_puffer_validator_stats.rs +++ /dev/null @@ -1,198 +0,0 @@ -use std::collections::HashMap; - -use ethers::prelude::*; - -use crate::error::AppServerResult; -use crate::services::beacon::types::ValidatorData; -use crate::services::beacon::SLOTS_PER_EPOCH; - -use super::client::BeaconClientTrait; -use super::types::{BlockId, ValidatorStatus}; -use super::{is_active_validator, is_full_withdrawal}; - -#[derive(Clone, Debug)] -pub struct NodeValidator { - pub pub_key: String, - pub validator_id: u64, -} - -#[derive(Clone, Debug, Default)] -pub struct ValidatorFullWithdrawal { - pub amount: U256, - pub was_slashed: bool, -} - -#[derive(Clone, Debug, Default)] -pub struct ValidatorConsensusReward { - pub amount: U256, -} - -#[derive(Clone, Debug, Default)] -pub struct ValidatorReward { - pub pubkey: String, - pub consensus_rewards: ValidatorConsensusReward, - pub full_withdrawal: ValidatorFullWithdrawal, -} - -#[derive(Clone, Debug, Default)] -pub struct RewardBlock { - pub block_number: String, - pub block_root: String, -} - -#[derive(Clone, Debug, Default)] -pub struct PufferValidatorStats { - pub start_block: RewardBlock, - pub end_block: RewardBlock, - pub validators: HashMap, -} - -pub async fn fetch_puffer_validator_stats( - beacon_client: &impl BeaconClientTrait, - validators_by_index: &HashMap, - last_post_block: U256, - block_root: &str, -) -> AppServerResult { - let eth_32: U256 = U256::from(32).saturating_mul(U256::exp10(9)); - - let last_reward_block_str = format!("{}", last_post_block); - - let mut validator_rewards = PufferValidatorStats::default(); - - let mut end_block: Option = None; - let start_block: Option; - - let mut block_root = block_root.to_string(); - loop { - let curr_block = beacon_client - .fetch_block(BlockId::BlockRoot(block_root.to_string())) - .await?; - if end_block.is_none() { - end_block = Some(RewardBlock { - block_number: curr_block - .data - .message - .body - .execution_payload - .block_number - .clone(), - block_root: block_root.clone(), - }); - } - - tracing::debug!( - "BLOCK: {} {} {block_root}", - last_reward_block_str, - curr_block.data.message.body.execution_payload.block_number - ); - - block_root = curr_block.data.message.parent_root; - let (epoch, _) = curr_block - .data - .message - .slot - .div_mod(U256::from(SLOTS_PER_EPOCH)); - - let withdrawals = curr_block.data.message.body.execution_payload.withdrawals; - for withdrawal in withdrawals { - let validator_index = withdrawal.validator_index; - if let Some(validator_data) = validators_by_index.get(&validator_index) { - let v_fully_withdrawn = is_full_withdrawal(validator_data, epoch.as_u64()); - let entry = validator_rewards - .validators - .entry(withdrawal.validator_index) - .or_insert(ValidatorReward::default()); - - entry.pubkey = validator_data.validator.pubkey.to_string(); - if v_fully_withdrawn { - if withdrawal.amount > eth_32 { - entry.full_withdrawal.amount = eth_32; - entry.consensus_rewards.amount += withdrawal.amount - eth_32; - } else { - entry.full_withdrawal.amount = withdrawal.amount; - } - match validator_data.status { - ValidatorStatus::ActiveSlashed | ValidatorStatus::ExitedSlashed => { - entry.full_withdrawal.was_slashed = true; - } - _ => { - entry.full_withdrawal.was_slashed = false; - } - } - } else { - entry.consensus_rewards.amount += withdrawal.amount; - } - } - } - if curr_block.data.message.body.execution_payload.block_number <= last_reward_block_str { - start_block = Some(RewardBlock { - block_number: curr_block - .data - .message - .body - .execution_payload - .block_number - .clone(), - block_root: block_root.clone(), - }); - break; - } - } - - if let Some(block) = start_block { - validator_rewards.start_block = block; - } - if let Some(block) = end_block { - validator_rewards.end_block = block; - } - - // convert GWEI to WEI - validator_rewards - .validators - .iter_mut() - .for_each(|(_, reward)| { - reward.consensus_rewards.amount = reward - .consensus_rewards - .amount - .saturating_mul(U256::exp10(9)); - reward.full_withdrawal.amount = - reward.full_withdrawal.amount.saturating_mul(U256::exp10(9)); - }); - Ok(validator_rewards) -} - -/// Given an epoch, count the number of valid validators in -/// validators_by_index. -pub fn count_active_validators( - validators_by_index: &HashMap, - end_epoch: u64, -) -> u64 { - validators_by_index - .values() - .filter(|v| is_active_validator(v, end_epoch)) - .count() as u64 -} - -/// Calculates Puffer Validator balances with just their -/// raw balance on the beacon chain. -pub fn calculate_puffer_validator_beacon_balances( - validators_by_index: &HashMap, - end_epoch: U256, -) -> U256 { - let gwei_32 = U256::from(32).saturating_mul(U256::exp10(9)); - let mut validator_balance = U256::zero(); - for validator in validators_by_index.values() { - let is_active = is_active_validator(validator, end_epoch.as_u64()); - // Edge case where validator just registered and is waiting to - // start validating - #[allow(clippy::if_same_then_else)] - if validator.status == ValidatorStatus::PendingQueued { - validator_balance += gwei_32; - } else if is_active && validator.balance == U256::zero() { - validator_balance += gwei_32; - } else if is_active { - validator_balance += validator.balance; - } - } - validator_balance.saturating_mul(U256::exp10(9)) -} diff --git a/coral-lib/src/services/beacon/fetch_state_root.rs b/coral-lib/src/services/beacon/fetch_state_root.rs deleted file mode 100644 index 1ef2127..0000000 --- a/coral-lib/src/services/beacon/fetch_state_root.rs +++ /dev/null @@ -1,37 +0,0 @@ -use axum::http::StatusCode; - -use crate::error::{AppServerResult, ServerErrorResponse}; -use crate::utils::encoding::parse_json_response; - -use super::types::{StateId, StateRootResponse}; - -pub async fn get_state_root( - beacon_url: &str, - state_id: &StateId, -) -> AppServerResult { - let api_url = format!("{beacon_url}/eth/v1/beacon/states/{state_id}/root"); - - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - - let resp_json: StateRootResponse = parse_json_response(resp).await?; - Ok(resp_json) -} diff --git a/coral-lib/src/services/beacon/fetch_validator.rs b/coral-lib/src/services/beacon/fetch_validator.rs deleted file mode 100644 index b26489c..0000000 --- a/coral-lib/src/services/beacon/fetch_validator.rs +++ /dev/null @@ -1,79 +0,0 @@ -use axum::http::StatusCode; - -use crate::services::beacon::types::StateId; -use crate::{ - error::{AppServerResult, ServerErrorResponse}, - utils::encoding::parse_json_response, -}; - -use super::types::{ValidatorId, ValidatorResponse}; - -pub async fn fetch_validator_by_index( - beacon_url: &str, - state_id: StateId, - validator_index: u64, -) -> AppServerResult { - let api_url = - format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators/{validator_index}"); - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - tracing::error!("Failed to fetch validator"); - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - - let resp_json = parse_json_response(resp).await?; - Ok(resp_json) -} - -pub async fn fetch_validator( - beacon_url: &str, - state_id: StateId, - validator: ValidatorId, -) -> AppServerResult { - let api_url = format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators/{validator}"); - tracing::debug!("Beacon: {api_url}"); - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - let error_msg = "Failed to send request"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - tracing::error!("Failed to fetch validator {validator}"); - let body = resp.text().await.map_err(|err| { - let error_msg = "Failed to parse body"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - eprintln!("{body}"); - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - - let resp_json = parse_json_response(resp).await?; - Ok(resp_json) -} diff --git a/coral-lib/src/services/beacon/fetch_validators.rs b/coral-lib/src/services/beacon/fetch_validators.rs deleted file mode 100644 index 9508767..0000000 --- a/coral-lib/src/services/beacon/fetch_validators.rs +++ /dev/null @@ -1,123 +0,0 @@ -use axum::http::StatusCode; -use std::collections::HashMap; - -use crate::{ - add_0x_prefix, - services::beacon::types::{StateId, ValidatorId}, -}; - -use super::{ - client::BeaconClientTrait, - types::{ValidatorData, ValidatorListResponse}, -}; -use crate::{ - error::{AppServerResult, ServerErrorResponse}, - utils::encoding::parse_json_response, -}; - -pub async fn fetch_validators_by_index( - beacon_url: &str, - state_id: StateId, - validators: &[u64], -) -> AppServerResult { - let validators_query: String = validators - .iter() - .map(|v| v.to_string()) - .collect::>() - .join(","); - - let api_url = - format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators?id={validators_query}"); - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - let error_msg = "Failed to send request"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - tracing::error!("Failed to fetch validators"); - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - - let resp_json = parse_json_response(resp).await?; - Ok(resp_json) -} - -pub async fn fetch_validators_by_pubkey( - beacon_url: &str, - state_id: StateId, - validators: &[String], -) -> AppServerResult { - let validators_query: String = validators.to_vec().join(","); - - let api_url = - format!("{beacon_url}/eth/v1/beacon/states/{state_id}/validators?id={validators_query}"); - tracing::debug!("Beacon: {api_url}"); - - let resp = reqwest::Client::new() - .request(reqwest::Method::GET, api_url) - .send() - .await - .map_err(|err| { - let error_msg = "Failed to send request"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - tracing::error!("Failed to fetch validators"); - let body = resp.text().await.map_err(|err| { - let error_msg = "Failed to parse body"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - eprintln!("{body}"); - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - - let resp_json = parse_json_response(resp).await?; - Ok(resp_json) -} - -pub async fn fetch_validators_fallback( - beacon_client: &impl BeaconClientTrait, - validator_pubkeys: &[String], -) -> HashMap { - let validator_pubkeys: Vec = - validator_pubkeys.iter().map(|k| add_0x_prefix(k)).collect(); - - let validators_by_index: HashMap = match beacon_client - .fetch_validators_by_pubkey(StateId::Finalized, validator_pubkeys.as_slice()) - .await - { - Ok(validators) => validators.data.into_iter().map(|v| (v.index, v)).collect(), - Err(_err) => { - tracing::debug!("Failed to fetch validators in bulk. Fetching individually instead"); - - let mut validators_by_index: HashMap = HashMap::new(); - for pubkey in validator_pubkeys { - let validator_resp = beacon_client - .fetch_validator(StateId::Finalized, ValidatorId::Pubkey(pubkey.clone())) - .await; - if let Ok(v) = validator_resp { - validators_by_index.insert(v.data.index, v.data); - } - } - validators_by_index - } - }; - validators_by_index -} diff --git a/coral-lib/src/services/beacon/mock_client.rs b/coral-lib/src/services/beacon/mock_client.rs deleted file mode 100644 index 020df64..0000000 --- a/coral-lib/src/services/beacon/mock_client.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::collections::VecDeque; -use std::sync::{Arc, Mutex}; - -use async_trait::async_trait; -use axum::http::StatusCode; - -use crate::error::{AppServerResult, ServerErrorResponse}; -use crate::services::beacon::types; - -use super::client::BeaconClientTrait; - -#[derive(Clone, Debug, Default)] -pub struct MockBeaconClient { - pub block_responses: Arc>>, - pub block_root_responses: Arc>>, - pub validator_responses: Arc>>, - pub validators_by_pubkey_responses: Arc>>, -} - -impl MockBeaconClient { - pub fn new() -> Self { - Self::default() - } - - pub fn push_block_response(&mut self, value: types::BlockResponse) { - self.block_responses.lock().unwrap().push_back(value); - } - - pub fn push_block_root_response(&mut self, value: String) { - self.block_root_responses.lock().unwrap().push_back(value); - } - - pub fn push_validator_response(&mut self, value: types::ValidatorResponse) { - self.validator_responses.lock().unwrap().push_back(value); - } - - pub fn push_validators_by_pubkey_response(&mut self, value: types::ValidatorListResponse) { - self.validators_by_pubkey_responses - .lock() - .unwrap() - .push_back(value); - } -} - -#[async_trait] -impl BeaconClientTrait for MockBeaconClient { - async fn fetch_block( - &self, - _state_id: types::BlockId, - ) -> AppServerResult { - match self.block_responses.lock().unwrap().pop_front() { - Some(block) => Ok(block), - None => Err(ServerErrorResponse::new( - StatusCode::IM_A_TEAPOT, - 2000, - "No fetch_block response set", - )), - } - } - - async fn fetch_block_root(&self, _state_id: types::BlockId) -> AppServerResult { - match self.block_root_responses.lock().unwrap().pop_front() { - Some(val) => Ok(val), - None => Err(ServerErrorResponse::new( - StatusCode::IM_A_TEAPOT, - 2000, - "No fetch_block_root response set", - )), - } - } - - async fn fetch_validator( - &self, - _state_id: types::StateId, - _validator: types::ValidatorId, - ) -> AppServerResult { - match self.validator_responses.lock().unwrap().pop_front() { - Some(value) => Ok(value), - None => Err(ServerErrorResponse::new( - StatusCode::IM_A_TEAPOT, - 2000, - "No fetch_validator response set", - )), - } - } - - async fn fetch_validators_by_pubkey( - &self, - _state_id: types::StateId, - _validators: &[String], - ) -> AppServerResult { - match self - .validators_by_pubkey_responses - .lock() - .unwrap() - .pop_front() - { - Some(value) => Ok(value), - None => Err(ServerErrorResponse::new( - StatusCode::IM_A_TEAPOT, - 2000, - "No fetch_validators_by_pubkey response set", - )), - } - } - - async fn fetch_validators_by_index( - &self, - _state_id: types::StateId, - _validators: &[u64], - ) -> AppServerResult { - Err(ServerErrorResponse::new( - StatusCode::IM_A_TEAPOT, - 2000, - "No fetch_validators_by_index response set", - )) - } -} diff --git a/coral-lib/src/services/beacon/mod.rs b/coral-lib/src/services/beacon/mod.rs deleted file mode 100644 index a73b4b9..0000000 --- a/coral-lib/src/services/beacon/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -pub mod types; - -mod attestation_rewards; -mod fetch_block; -mod fetch_genesis; -mod fetch_puffer_validator_stats; -mod fetch_state_root; -mod fetch_validator; -mod fetch_validators; -mod submit_exit; - -pub mod client; -pub mod mock_client; - -pub use self::attestation_rewards::*; -pub use self::fetch_block::*; -pub use self::fetch_genesis::*; -pub use self::fetch_puffer_validator_stats::*; -pub use self::fetch_state_root::*; -pub use self::fetch_validator::*; -pub use self::fetch_validators::*; -pub use self::submit_exit::*; - -pub const SLOTS_PER_EPOCH: u64 = 32; - -#[inline] -pub fn is_active_validator(data: &types::ValidatorData, epoch: u64) -> bool { - data.validator.activation_epoch <= epoch && epoch < data.validator.exit_epoch -} - -#[inline] -pub fn is_full_withdrawal(data: &types::ValidatorData, epoch: u64) -> bool { - data.validator.exit_epoch <= epoch && data.validator.withdrawable_epoch <= epoch -} diff --git a/coral-lib/src/services/beacon/submit_exit.rs b/coral-lib/src/services/beacon/submit_exit.rs deleted file mode 100644 index 45db4e6..0000000 --- a/coral-lib/src/services/beacon/submit_exit.rs +++ /dev/null @@ -1,60 +0,0 @@ -use axum::http::StatusCode; -use serde::Serialize; - -use crate::error::{AppServerResult, ServerErrorResponse}; - -#[derive(Clone, Debug, Serialize)] -pub struct VoluntaryExit { - pub epoch: String, - pub validator_index: String, -} - -#[derive(Clone, Debug, Serialize)] -pub struct SignedVoluntaryExit { - pub message: VoluntaryExit, - pub signature: String, -} - -pub async fn submit_exit( - beacon_url: &str, - validator_index: u64, - epoch: u64, - signature: &str, -) -> AppServerResult<()> { - let req_body = SignedVoluntaryExit { - message: VoluntaryExit { - epoch: epoch.to_string(), - validator_index: validator_index.to_string(), - }, - signature: signature.to_string(), - }; - let req_body_str = serde_json::to_string(&req_body).unwrap(); - - eprintln!("Req Body: {}", req_body_str); - - let api_url = format!("{beacon_url}/eth/v1/beacon/pool/voluntary_exits"); - let resp = reqwest::Client::new() - .request(reqwest::Method::POST, api_url) - .body(req_body_str) - .send() - .await - .map_err(|err| { - tracing::error!("Failed to send request"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to send request", - ) - })?; - - let status_code = resp.status(); - if !status_code.is_success() { - let body = resp.text().await; - eprintln!("Body: {:?}", body); - let status_code = StatusCode::from_u16(status_code.as_u16()).unwrap(); - let err = ServerErrorResponse::new(status_code, 1000, &format!("{}", status_code)); - return Err(err); - } - Ok(()) -} diff --git a/coral-lib/src/services/beacon/types/attestation_rewards.rs b/coral-lib/src/services/beacon/types/attestation_rewards.rs deleted file mode 100644 index 065a9f4..0000000 --- a/coral-lib/src/services/beacon/types/attestation_rewards.rs +++ /dev/null @@ -1,31 +0,0 @@ -use serde::Deserialize; - -use super::BeaconResponse; - -#[derive(Clone, Debug, Deserialize)] -pub struct IdealRewardResponse { - pub effective_balance: String, - pub head: String, - pub target: String, - pub source: String, - pub inclusion_delay: Option, - pub inactivity: Option, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct TotalRewardResponse { - pub validator_index: String, - pub head: String, - pub target: String, - pub source: String, - pub inclusion_delay: Option, - pub inactivity: Option, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct AttestationRewardsDataResponse { - pub ideal_rewards: Vec, - pub total_rewards: Vec, -} - -pub type AttestationRewardsResponse = BeaconResponse; diff --git a/coral-lib/src/services/beacon/types/beacon_block.rs b/coral-lib/src/services/beacon/types/beacon_block.rs deleted file mode 100644 index 544812e..0000000 --- a/coral-lib/src/services/beacon/types/beacon_block.rs +++ /dev/null @@ -1,99 +0,0 @@ -use ethers::types::U256; -use serde::Deserialize; - -use crate::utils::serialize::{string_to_u256_base10, string_to_u64}; - -#[derive(Clone, Debug, Deserialize)] -pub struct BeaconWithdrawal { - pub index: String, - #[serde(deserialize_with = "string_to_u64")] - pub validator_index: u64, - pub address: String, - #[serde(deserialize_with = "string_to_u256_base10")] - pub amount: U256, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct ExecutionPayload { - pub parent_hash: String, - pub fee_recipient: String, - pub state_root: String, - pub receipts_root: String, - pub logs_bloom: String, - pub prev_randao: String, - pub block_number: String, - pub gas_limit: String, - pub gas_used: String, - pub timestamp: String, - pub extra_data: String, - pub base_fee_per_gas: String, - pub block_hash: String, - pub transactions: Vec, - pub withdrawals: Vec, - #[serde(skip_deserializing)] - pub bls_to_execution_changes: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BeaconEth1BlockBody { - pub deposit_root: String, - pub deposit_count: String, - pub block_hash: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BeaconBlockBody { - pub randao_reveal: String, - pub eth1_data: BeaconEth1BlockBody, - pub graffiti: String, - #[serde(skip_deserializing)] - pub proposer_slashings: Vec, - #[serde(skip_deserializing)] - pub attester_slashings: Vec, - #[serde(skip_deserializing)] - pub attestations: Vec, - #[serde(skip_deserializing)] - pub deposits: Vec, - #[serde(skip_deserializing)] - pub voluntary_exits: Vec, - #[serde(skip_deserializing)] - pub sync_aggregate: Option>, - pub execution_payload: ExecutionPayload, - #[serde(skip_deserializing)] - pub bls_to_execution_changes: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BlockMessageData { - #[serde(deserialize_with = "string_to_u256_base10")] - pub slot: U256, - pub proposer_index: String, - pub parent_root: String, - pub state_root: String, - pub body: BeaconBlockBody, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BlockMessage { - pub message: BlockMessageData, - pub signature: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BlockResponse { - pub execution_optimistic: Option, - pub finalized: Option, - pub data: BlockMessage, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BlockRoot { - pub root: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct BlockRootResponse { - pub execution_optimistic: Option, - pub finalized: Option, - pub data: BlockRoot, -} diff --git a/coral-lib/src/services/beacon/types/genesis.rs b/coral-lib/src/services/beacon/types/genesis.rs deleted file mode 100644 index 0229f70..0000000 --- a/coral-lib/src/services/beacon/types/genesis.rs +++ /dev/null @@ -1,52 +0,0 @@ -use ethers::utils::hex::{self}; - -use serde::Deserialize; - -use crate::{ - error::{AppError, AppErrorKind, AppResult}, - structs::eth_types::ForkVersion, -}; -use puffersecuresigner::strip_0x_prefix; - -#[derive(Clone, Debug, Deserialize)] -pub struct BeaconGenesis { - pub genesis_time: String, - pub genesis_validators_root: String, - pub genesis_fork_version: String, -} - -impl BeaconGenesis { - pub fn fork_version_as_fixed(&self) -> AppResult { - let genesis_fork_version: &str = strip_0x_prefix!(self.genesis_fork_version); - let genesis_fork_version: ForkVersion = hex::decode(genesis_fork_version) - .map_err(|_err| { - AppError::new( - AppErrorKind::DecodeError, - "Failed to decode hex".to_string(), - ) - })? - .as_slice() - .try_into() - .map_err(|_err| { - AppError::new(AppErrorKind::DecodeError, "Invalid length".to_string()) - })?; - Ok(genesis_fork_version) - } - - pub fn genesis_validators_root_as_fixed(&self) -> AppResult<[u8; 32]> { - let genesis_validators_root: &str = strip_0x_prefix!(self.genesis_validators_root); - let genesis_validators_root: [u8; 32] = hex::decode(genesis_validators_root) - .map_err(|_err| { - AppError::new( - AppErrorKind::DecodeError, - "Failed to decode hex".to_string(), - ) - })? - .as_slice() - .try_into() - .map_err(|_err| { - AppError::new(AppErrorKind::DecodeError, "Invalid length".to_string()) - })?; - Ok(genesis_validators_root) - } -} diff --git a/coral-lib/src/services/beacon/types/mod.rs b/coral-lib/src/services/beacon/types/mod.rs deleted file mode 100644 index d853e90..0000000 --- a/coral-lib/src/services/beacon/types/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -mod attestation_rewards; -mod beacon_block; -mod genesis; -mod state_root; -mod validator; -mod validator_balance; - -#[cfg(test)] -mod state_root_test; - -pub use attestation_rewards::*; -pub use beacon_block::*; -pub use genesis::*; -pub use state_root::*; -pub use validator::*; -pub use validator_balance::*; - -use serde::Deserialize; - -#[derive(Clone, Debug, Deserialize)] -pub struct BeaconResponse { - pub finalized: Option, - pub data: T, -} diff --git a/coral-lib/src/services/beacon/types/state_root.rs b/coral-lib/src/services/beacon/types/state_root.rs deleted file mode 100644 index 31e1e4a..0000000 --- a/coral-lib/src/services/beacon/types/state_root.rs +++ /dev/null @@ -1,74 +0,0 @@ -use ethers::types::{H256, U256}; -use serde::{Deserialize, Serialize}; - -use crate::utils::serialize::u256_serialize; - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum StateId { - #[serde(rename = "head")] - Head, - #[serde(rename = "genesis")] - Genesis, - #[serde(rename = "finalized")] - Finalized, - #[serde(rename = "justified")] - Justified, - #[serde(untagged, serialize_with = "u256_serialize")] - Slot(U256), - #[serde(untagged)] - StateRoot(H256), -} - -impl std::fmt::Display for StateId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Head => f.write_str("head"), - Self::Genesis => f.write_str("genesis"), - Self::Finalized => f.write_str("finalized"), - Self::Justified => f.write_str("justified"), - Self::Slot(s) => f.write_str(&format!("{}", s)), - Self::StateRoot(s) => f.write_str(&format!("0x{:x}", s)), - } - } -} - -#[derive(Clone, Debug, Deserialize)] -pub struct StateRootData { - pub root: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct StateRootResponse { - pub execution_optimistic: bool, - pub finalized: bool, - pub data: StateRootData, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum BlockId { - #[serde(rename = "head")] - Head, - #[serde(rename = "genesis")] - Genesis, - #[serde(rename = "finalized")] - Finalized, - #[serde(rename = "justified")] - Justified, - #[serde(untagged, serialize_with = "u256_serialize")] - Slot(U256), - #[serde(untagged)] - BlockRoot(String), -} - -impl std::fmt::Display for BlockId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Head => f.write_str("head"), - Self::Genesis => f.write_str("genesis"), - Self::Finalized => f.write_str("finalized"), - Self::Justified => f.write_str("justified"), - Self::Slot(s) => f.write_str(&s.to_string()), - Self::BlockRoot(s) => f.write_str(&s.to_string()), - } - } -} diff --git a/coral-lib/src/services/beacon/types/state_root_test.rs b/coral-lib/src/services/beacon/types/state_root_test.rs deleted file mode 100644 index 130e93a..0000000 --- a/coral-lib/src/services/beacon/types/state_root_test.rs +++ /dev/null @@ -1,76 +0,0 @@ -use ethers::types::{H256, U256}; -use serde_json::json; - -use super::StateId; - -#[test] -pub fn test_serialize_state_id() { - let values = [ - (StateId::Head, "head"), - (StateId::Genesis, "genesis"), - (StateId::Finalized, "finalized"), - (StateId::Justified, "justified"), - (StateId::Slot(U256::from(1000)), "1000"), - ( - StateId::StateRoot(H256::from_low_u64_be(123)), - "0x000000000000000000000000000000000000000000000000000000000000007b", - ), - ]; - - for (value, value_str) in values { - let commit = json!({ - "value": value, - }); - - let json = serde_json::to_string(&commit).unwrap(); - assert_eq!(json, format!("{{\"value\":\"{value_str}\"}}")) - } -} - -#[test] -fn test_deserialize_state_id() { - let values = [ - (StateId::Head, "head"), - (StateId::Genesis, "genesis"), - (StateId::Finalized, "finalized"), - (StateId::Justified, "justified"), - (StateId::Slot(U256::from(1000)), "1000"), - ( - StateId::StateRoot(H256::from_low_u64_be(123)), - "0x000000000000000000000000000000000000000000000000000000000000007b", - ), - ]; - - for (value, value_str) in values { - let commit = json!({ - "value": value, - }); - let commit_str = format!("{{\"value\":\"{value_str}\"}}"); - - let json: serde_json::Value = serde_json::from_str(&commit_str).unwrap(); - assert_eq!(commit, json); - } -} - -#[test] -pub fn test_display_state_id() { - let values = [ - (StateId::Head, "head"), - (StateId::Genesis, "genesis"), - (StateId::Finalized, "finalized"), - (StateId::Justified, "justified"), - ( - StateId::Slot(U256::from(1000).saturating_mul(U256::from(10000000000000000000u64))), - "10000000000000000000000", - ), - ( - StateId::StateRoot(H256::from_low_u64_be(123)), - "0x000000000000000000000000000000000000000000000000000000000000007b", - ), - ]; - - for (value, value_str) in values { - let result_str = format!("{}", value); - assert_eq!(result_str, value_str) - } -} diff --git a/coral-lib/src/services/beacon/types/validator.rs b/coral-lib/src/services/beacon/types/validator.rs deleted file mode 100644 index 9da2bf7..0000000 --- a/coral-lib/src/services/beacon/types/validator.rs +++ /dev/null @@ -1,73 +0,0 @@ -use ethers::types::U256; -use serde::Deserialize; - -use crate::utils::serialize::{string_to_u256_base10, string_to_u64}; - -use super::BeaconResponse; - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] -pub enum ValidatorId { - Pubkey(String), - Index(u64), -} - -impl std::fmt::Display for ValidatorId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Pubkey(key) => f.write_str(key), - Self::Index(index) => f.write_str(&format!("{}", *index)), - } - } -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] -pub enum ValidatorStatus { - #[serde(rename = "pending_initialized")] - PendingInitialized, - #[serde(rename = "pending_queued")] - PendingQueued, - #[serde(rename = "active_ongoing")] - ActiveOngoing, - #[serde(rename = "active_exiting")] - ActiveExiting, - #[serde(rename = "active_slashed")] - ActiveSlashed, - #[serde(rename = "exited_unslashed")] - ExitedUnslashed, - #[serde(rename = "exited_slashed")] - ExitedSlashed, - #[serde(rename = "withdrawal_possible")] - WithdrawalPossible, - #[serde(rename = "withdrawal_done")] - WithdrawalDone, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct ValidatorStats { - pub pubkey: String, - pub withdrawal_credentials: String, - #[serde(deserialize_with = "string_to_u256_base10")] - pub effective_balance: U256, - pub slashed: bool, - #[serde(deserialize_with = "string_to_u64")] - pub activation_eligibility_epoch: u64, - #[serde(deserialize_with = "string_to_u64")] - pub activation_epoch: u64, - #[serde(deserialize_with = "string_to_u64")] - pub exit_epoch: u64, - #[serde(deserialize_with = "string_to_u64")] - pub withdrawable_epoch: u64, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct ValidatorData { - #[serde(deserialize_with = "string_to_u64")] - pub index: u64, - #[serde(deserialize_with = "string_to_u256_base10")] - pub balance: U256, - pub status: ValidatorStatus, - pub validator: ValidatorStats, -} - -pub type ValidatorResponse = BeaconResponse; -pub type ValidatorListResponse = BeaconResponse>; diff --git a/coral-lib/src/services/beacon/types/validator_balance.rs b/coral-lib/src/services/beacon/types/validator_balance.rs deleted file mode 100644 index 23aa3d1..0000000 --- a/coral-lib/src/services/beacon/types/validator_balance.rs +++ /dev/null @@ -1,12 +0,0 @@ -use ethers::types::U256; -use serde::Deserialize; - -use super::BeaconResponse; - -#[derive(Clone, Debug, Deserialize)] -pub struct ValidatorBalance { - pub id: u64, - pub balance: U256, -} - -pub type ValidatorBalancesResponse = BeaconResponse>; diff --git a/coral-lib/src/services/mod.rs b/coral-lib/src/services/mod.rs deleted file mode 100644 index f66e2a0..0000000 --- a/coral-lib/src/services/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod beacon; diff --git a/coral-lib/src/utils/abi/abi_test.rs b/coral-lib/src/utils/abi/abi_test.rs deleted file mode 100644 index 7e12863..0000000 --- a/coral-lib/src/utils/abi/abi_test.rs +++ /dev/null @@ -1,95 +0,0 @@ -// use ethers::utils::hex::{FromHex, ToHex}; -// use puffersecuresigner::{ -// enclave::types::KeyGenResponse, io::remote_attestation::AttestationEvidence, -// }; -// use crate::utils; - -/* -const KEYGEN_TEST_RESPONSE: &str = - include_str!("../../../../mock-server/test_data/keygen_response_001.json"); - -const REPORT_CALLDATA: &str = - include_str!("../../../../mock-server/test_data/keygen_response_001_report_calldata.txt"); -const RAVE_CALLDATA: &str = - include_str!("../../../../mock-server/test_data/keygen_response_001_rave_calldata.txt"); - -#[test] -fn test_extract_x509_valid() { - let report: KeyGenResponse = serde_json::from_str(KEYGEN_TEST_RESPONSE).unwrap(); - - let (leaf_x509, root_x509) = - utils::ssl::extract_x509(report.evidence.signing_cert.as_bytes()).unwrap(); - - assert_eq!( - true, - utils::ssl::verify_intel_sgx_root_ca(&root_x509).is_ok() - ); - assert_eq!( - true, - utils::ssl::verify_intel_sgx_attestation_report(&leaf_x509).is_ok() - ); -} - -#[test] -fn test_raw_report_calldata_valid() { - let report: KeyGenResponse = serde_json::from_str(KEYGEN_TEST_RESPONSE).unwrap(); - let evidence = &report.evidence; - let raw_report = - utils::abi::intel_report::deserialize_report(evidence.raw_report.as_bytes()).unwrap(); - - let actual = utils::abi::intel_report::to_calldata(&raw_report).unwrap(); - let expected: Vec = >::from_hex(REPORT_CALLDATA).unwrap(); - - assert_eq!(expected.len(), actual.len()); - assert_eq!(expected, actual); -} - -#[test] -fn test_rave_calldata_generate_json() { - const KEYGEN_RESPONSE_JSON: &str = include_str!("../../../../mock-server/test_data/0x8144e74faf431dad80831ef0dddca2302f9a913bc0c2fdfafaeacac05cdb173b.json"); - - let report: KeyGenResponse = serde_json::from_str(KEYGEN_RESPONSE_JSON).unwrap(); - let attestation_report = - utils::abi::intel_report::deserialize_report(report.evidence.raw_report.as_bytes()) - .unwrap(); - - let report_json = utils::abi::intel_report::to_json(&attestation_report).unwrap(); - println!("{}", report_json); - - let rave_json = utils::abi::rave_evidence::to_json(&report, &attestation_report).unwrap(); - println!("{}", rave_json); - - let report_calldata = utils::abi::intel_report::to_calldata(&attestation_report).unwrap(); - println!( - "report calldata: '{}'", - report_calldata.encode_hex::() - ); -} - -#[test] -fn test_rave_calldata_generate_json_from_keygen() { - let report = KeyGenResponse { - pk_hex: "0x04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd".to_string(), - evidence: AttestationEvidence { - raw_report: "{\"id\":\"186453210057823126547835745110511429060\",\"timestamp\":\"2023-10-16T20:17:59.516859\",\"version\":4,\"epidPseudonym\":\"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhspNWPNBkpcmwf+3WZYsuncw6eX6Uijk+PzPp3dBQSebHsOEQYDRxGeFuWowvkTo2Z5HTavyoRIrSupBTqDE78HA=\",\"advisoryURL\":\"https://security-center.intel.com\",\"advisoryIDs\":[\"INTEL-SA-00334\",\"INTEL-SA-00615\"],\"isvEnclaveQuoteStatus\":\"SW_HARDENING_NEEDED\",\"isvEnclaveQuoteBody\":\"AgABAKwMAAANAA0AAAAAAEJhbJjVPJcSY5RHybDnAD8AAAAAAAAAAAAAAAAAAAAAFRULB/+ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAfAAAAAAAAAI63DnajS/bL+d7tf0Z7SIjMGH8fHzTM4tEcpUAUFJo1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGGfbNg35+DFwYIjUiKm+84K8beqRS7hF/CO4eKrj1YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}".to_string(), - signed_report: "LDx4Yimeh/lB5amkm5ahvJ4v7E/BXp6mTow9akiUy+9DMkisIUAvFlBik2sS/9dea4xAFcNJkbdaVYOQQ03LcKGE4k/sOPUJKYJiga4xeT6gL8O1HwCZBun+u/IKvs7jKy27gx9ne6usvEBXAwxGUK1Ng9xbayiu94tJwmd3wEgghWvTbFFPDoaTwLp82UoZHSQY8rDX0lMwE+WpgVs8t4WwV1ZIJnt5kMBwsmYUsd4Ylq3mORNkFX6+BhEreohP8FlYbLpPaKAqJEATbhb1ubZb4NIII863c8khkfxhXLq1aLgJtb7q1HIBFhI4uWgV8OnSw3xEAOSseU3PKxs1mQ==".to_string(), - signing_cert: "-----BEGIN CERTIFICATE-----\nMIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\nBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV\nBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0\nYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIw\nMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1Nh\nbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwk\nSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+t\nbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtId\ncv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuv\nLUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhA\nImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8\ngZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGh\nMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIG\nwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVk\nc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJl\ncG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4r\nRq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9\nlpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYv\nWLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUd\nZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY\n6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW7\n2uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2\ntQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbq\nd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\nBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV\nBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0\nYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy\nMzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL\nU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD\nDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G\nCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR+tXc8u1EtJzLA10Feu1Wg+p7e\nLmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh\nrgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT\nL/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe\nNpEJUmg4ktal4qgIAxk+QHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ\nbyinkNndn+Bgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H\nafuVeLHcDsRp6hol4P+ZFIhu8mmbI1u0hH3W/0C2BuYXB5PC+5izFFh/nP0lc2Lf\n6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM\nRoOaX4AS+909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX\nMFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50\nL0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW\nBBR4Q3t2pn680K9+QjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9+Qjfr\nNXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq\nhkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir\nIEqucRiJSSx+HjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi+ripMtPZ\nsFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi\nzLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra\nUd4APK0wZTGtfPXU7w+IBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA\n152Sq049ESDz+1rRGc2NVEqh1KaGXmtXvqxXcTB+Ljy5Bw2ke0v8iGngFBPqCTVB\n3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5+xmBc388v9Dm21HGfcC8O\nDD+gT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R+mJTLwPXVMrv\nDaVzWh5aiEx+idkSGMnX\n-----END CERTIFICATE-----\n".to_string(), - }, - }; - let attestation_report = - utils::abi::intel_report::deserialize_report(report.evidence.raw_report.as_bytes()); - let attestation_report = attestation_report.unwrap(); - - println!("===========REPORT============"); - let report_json = utils::abi::intel_report::to_json(&attestation_report).unwrap(); - println!("{}", report_json); - - println!("===========RAVE============"); - let rave_json = utils::abi::rave_evidence::to_json(&report, &attestation_report).unwrap(); - println!("{}", rave_json); - - println!("==========CALLDATA========="); - let report_calldata = utils::abi::intel_report::to_calldata(&attestation_report).unwrap(); - println!("{}", report_calldata.encode_hex::()); -} - */ diff --git a/coral-lib/src/utils/abi/intel_report.rs b/coral-lib/src/utils/abi/intel_report.rs deleted file mode 100644 index 8c95181..0000000 --- a/coral-lib/src/utils/abi/intel_report.rs +++ /dev/null @@ -1,233 +0,0 @@ -use ethers::abi; -use ethers::utils::hex::ToHex; - -use axum::http::StatusCode; -use puffersecuresigner::io::remote_attestation::AttestationReport; - -use crate::error::{AppServerResult, ServerErrorResponse}; -use crate::utils; - -pub fn deserialize_report(b: &[u8]) -> AppServerResult { - let report: AttestationReport = serde_json::from_slice(b).map_err(|err| { - tracing::error!("Failed to parse attestation report"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to parse attestation report", - ) - })?; - Ok(report) -} - -pub fn to_json(report: &AttestationReport) -> AppServerResult { - let decoded_quote_body = utils::encoding::base64_decode_to_bytes(&report.isvEnclaveQuoteBody)?; - let advisory_ids = serde_json::to_string(&report.advisoryIDs).map_err(|err| { - tracing::error!("Failed to serialize advisoryIDs"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to serialize advisoryIDs", - ) - })?; - - let json_data = serde_json::json!({ - "id": report.id, - "timestamp": report.timestamp, - "version": report.version, - "epidPseudonym": report.epidPseudonym, - "advisoryURL": report.advisoryURL, - "advisoryIds": advisory_ids, - "isvEnclaveQuoteStatus": report.isvEnclaveQuoteStatus, - "isvEnclaveQuoteBody": decoded_quote_body.encode_hex::(), - }); - - let json_data = serde_json::json!({ - "report": json_data - }); - - let json_string = serde_json::to_string(&json_data).map_err(|err| { - tracing::error!("Failed to serialize json"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to serialize json", - ) - })?; - Ok(json_string) -} - -pub fn to_calldata_with_decoded_quote_body( - attestation_report: &AttestationReport, -) -> AppServerResult { - let decoded_quote_body = - utils::encoding::base64_decode_to_bytes(&attestation_report.isvEnclaveQuoteBody)?; - - let advisory_ids = serde_json::to_string(&attestation_report.advisoryIDs).map_err(|err| { - tracing::error!("Failed to serialize advisoryIDs"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to serialize advisoryIDs", - ) - })?; - - let calldata = abi::encode(&[ - abi::Token::Bytes(attestation_report.id.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.timestamp.as_bytes().to_vec()), - abi::Token::Bytes( - format!("{}", attestation_report.version) - .as_bytes() - .to_vec(), - ), - abi::Token::Bytes(attestation_report.epidPseudonym.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.advisoryURL.as_bytes().to_vec()), - abi::Token::Bytes(advisory_ids.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.isvEnclaveQuoteStatus.as_bytes().to_vec()), - abi::Token::Bytes(decoded_quote_body.to_vec()), - ]); - Ok(calldata) -} - -pub fn to_calldata(attestation_report: &AttestationReport) -> AppServerResult { - let advisory_ids = serde_json::to_string(&attestation_report.advisoryIDs).map_err(|err| { - tracing::error!("Failed to serialize advisoryIDs"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to serialize advisoryIDs", - ) - })?; - - let calldata = abi::encode(&[ - abi::Token::Bytes(attestation_report.id.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.timestamp.as_bytes().to_vec()), - abi::Token::Bytes( - format!("{}", attestation_report.version) - .as_bytes() - .to_vec(), - ), - abi::Token::Bytes(attestation_report.epidPseudonym.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.advisoryURL.as_bytes().to_vec()), - abi::Token::Bytes(advisory_ids.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.isvEnclaveQuoteStatus.as_bytes().to_vec()), - abi::Token::Bytes(attestation_report.isvEnclaveQuoteBody.as_bytes().to_vec()), - ]); - Ok(calldata) -} - -pub fn from_calldata(data: &[u8]) -> AppServerResult { - let calldata_tokens = abi::decode( - &[ - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - ], - data, - ) - .map_err(|err| { - let error_msg = "Failed to parse report calldata"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let report_data = match calldata_tokens.as_slice() { - [abi::Token::Bytes(id), abi::Token::Bytes(timestamp), abi::Token::Bytes(version), abi::Token::Bytes(epid_pseudonym), abi::Token::Bytes(advisory_url), abi::Token::Bytes(advisory_ids), abi::Token::Bytes(isv_enclave_quote_status), abi::Token::Bytes(encoded_quote_body), ..] => - { - let id = String::from_utf8(id.clone()).map_err(|err| { - let error_msg = "Failed to decode report calldata fields"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let timestamp = String::from_utf8(timestamp.clone()).map_err(|err| { - let error_msg = "Failed to decode report calldata fields"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let version: u32 = { - let s = String::from_utf8(version.clone()).map_err(|err| { - let error_msg = "Failed to decode report calldata fields"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - s.parse::().map_err(|err| { - let error_msg = "Failed to decode report calldata fields"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })? - }; - - let epid_pseudonym = String::from_utf8(epid_pseudonym.clone()).map_err(|err| { - let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let advisory_url = String::from_utf8(advisory_url.clone()).map_err(|err| { - let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let isv_enclave_quote_status = String::from_utf8(isv_enclave_quote_status.clone()) - .map_err(|err| { - let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let encoded_quote_body = - String::from_utf8(encoded_quote_body.clone()).map_err(|err| { - let error_msg = "Failed to decode report calldata isv_enclave_quote_status"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - let advisory_ids: Vec = - serde_json::from_slice(advisory_ids).map_err(|err| { - let error_msg = "Failed to decode report calldata advisory_ids"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - AttestationReport { - id, - timestamp, - version, - epidPseudonym: epid_pseudonym, - advisoryURL: advisory_url, - advisoryIDs: advisory_ids, - isvEnclaveQuoteStatus: isv_enclave_quote_status, - isvEnclaveQuoteBody: encoded_quote_body, - } - } - _ => { - let error_msg = "Invalid report calldata"; - tracing::error!("{error_msg}"); - let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); - return Err(err); - } - }; - Ok(report_data) -} diff --git a/coral-lib/src/utils/abi/mod.rs b/coral-lib/src/utils/abi/mod.rs deleted file mode 100644 index a076f47..0000000 --- a/coral-lib/src/utils/abi/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod intel_report; -pub mod rave_evidence; - -#[cfg(test)] -mod abi_test; - -// Intel SGX constants -pub const SIGNING_MOD: &str = "9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; -pub const SIGNING_EXP: &str = "010001"; diff --git a/coral-lib/src/utils/abi/rave_evidence.rs b/coral-lib/src/utils/abi/rave_evidence.rs deleted file mode 100644 index 41c270b..0000000 --- a/coral-lib/src/utils/abi/rave_evidence.rs +++ /dev/null @@ -1,106 +0,0 @@ -use ethers::abi; -use ethers::utils::hex::ToHex; - -use axum::http::StatusCode; -use puffersecuresigner::enclave::types::KeyGenResponse; -use puffersecuresigner::io::remote_attestation::AttestationReport; - -use crate::error::{AppServerResult, ServerErrorResponse}; -use crate::utils; - -use super::{SIGNING_EXP, SIGNING_MOD}; - -#[derive(Clone, Debug)] -pub struct AbiDecodedRaveData { - pub enclave_report: Vec, - pub enclave_sig: Vec, - pub enclave_x509: Vec, -} - -pub fn to_json( - report: &KeyGenResponse, - attestation_report: &AttestationReport, -) -> AppServerResult { - let evidence = &report.evidence; - let signature = utils::encoding::base64_decode_to_bytes(&evidence.signed_report)?; - - let (leaf_x509, _) = utils::ssl::extract_x509(report.evidence.signing_cert.as_bytes())?; - let leaf_x509_der = leaf_x509.to_der().map_err(|err| { - let msg = "Failed to convert x509 to DER format"; - tracing::error!(msg); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, msg) - })?; - - let quote_body = attestation_report.deserialize_quote_body().unwrap(); - - let json_data = serde_json::json!({ - "evidence": report.evidence, - "signature": signature.encode_hex::(), - "leaf_x509": leaf_x509_der.encode_hex::(), - "mr_enclave": quote_body.MRENCLAVE, - "mr_signer": quote_body.MRSIGNER, - "signing_mod": SIGNING_MOD, - "signing_exp": SIGNING_EXP, - }); - - let json_string = serde_json::to_string(&json_data).map_err(|err| { - tracing::error!("Failed to serialize json"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to serialize json", - ) - })?; - Ok(json_string) -} - -pub fn to_calldata( - enclave_report: &[u8], - enclave_sig: &[u8], - enclave_x509: &[u8], -) -> AppServerResult { - let rave_evidence = abi::encode(&[ - abi::Token::Bytes(enclave_report.into()), - abi::Token::Bytes(enclave_sig.into()), - abi::Token::Bytes(enclave_x509.to_vec()), - ]); - Ok(rave_evidence) -} - -pub fn from_calldata(data: &[u8]) -> AppServerResult { - let calldata_tokens = abi::decode( - &[ - abi::ParamType::Bytes, - abi::ParamType::Bytes, - abi::ParamType::Bytes, - ], - data, - ) - .map_err(|err| { - let error_msg = "Failed to parse RAVE calldata"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - - // eprintln!("RAVE_calldata: {:?}", calldata_tokens); - - let rave_data = match calldata_tokens.as_slice() { - [abi::Token::Bytes(enclave_report), abi::Token::Bytes(enclave_sig), abi::Token::Bytes(enclave_x509), ..] => { - AbiDecodedRaveData { - enclave_report: enclave_report.clone(), - enclave_sig: enclave_sig.clone(), - enclave_x509: enclave_x509.clone(), - } - } - _ => { - let error_msg = "Invalid RAVE calldata"; - tracing::error!("{error_msg}"); - let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg); - return Err(err); - } - }; - Ok(rave_data) -} diff --git a/coral-lib/src/utils/encoding.rs b/coral-lib/src/utils/encoding.rs deleted file mode 100644 index ab6c444..0000000 --- a/coral-lib/src/utils/encoding.rs +++ /dev/null @@ -1,69 +0,0 @@ -use axum::http::StatusCode; -use base64::Engine; -use reqwest::Response; -use serde::de::DeserializeOwned; - -use crate::error::{AppServerResult, ServerErrorResponse}; - -pub fn base64_encode_to_bytes(s: &[u8]) -> AppServerResult { - let res = base64::engine::general_purpose::STANDARD.encode(s); - Ok(res) -} - -pub fn base64_decode_to_bytes(s: &str) -> AppServerResult> { - let res = base64::engine::general_purpose::STANDARD - .decode(s.as_bytes()) - .map_err(|err| { - tracing::error!("Failed to base64 decode"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to decode base64 decode", - ) - })?; - Ok(res) -} - -pub fn base64_decode_to_string(s: &str) -> AppServerResult { - let vec_bytes = base64_decode_to_bytes(s)?; - let new_string = String::from_utf8(vec_bytes).map_err(|err| { - tracing::error!("Failed to decode to utf8"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to decode decode to utf8", - ) - })?; - - Ok(new_string) -} - -pub async fn parse_json_response(resp: Response) -> AppServerResult { - if !resp.status().is_success() { - let body = resp.text().await.map_err(|err| { - tracing::error!("Failed to parse body"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to parse body", - ) - })?; - tracing::error!("Body: {}", body); - let err = ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, &body); - return Err(err); - } - - let resp_json: T = resp.json().await.map_err(|err| { - tracing::error!("Failed to parse JSON"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to parse JSON", - ) - })?; - Ok(resp_json) -} diff --git a/coral-lib/src/utils/encoding_test.rs b/coral-lib/src/utils/encoding_test.rs deleted file mode 100644 index e69de29..0000000 diff --git a/coral-lib/src/utils/ethereum.rs b/coral-lib/src/utils/ethereum.rs deleted file mode 100644 index a856e90..0000000 --- a/coral-lib/src/utils/ethereum.rs +++ /dev/null @@ -1,96 +0,0 @@ -use std::sync::Arc; - -use axum::http::StatusCode; -use ethers::prelude::*; - -use crate::error::{AppServerResult, ServerErrorResponse}; - -pub fn get_provider(rpc_url: &str) -> AppServerResult> { - let provider = Provider::::try_from(rpc_url).map_err(|err| { - tracing::error!("Invalid RPC URL"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::BAD_REQUEST, 1000, "Invalid RPC URL") - })?; - Ok(provider) -} - -pub fn get_client( - provider: Provider, - wallet: LocalWallet, - chain_id: u64, -) -> Arc, LocalWallet>> -where - J: JsonRpcClient, -{ - let client = SignerMiddleware::new(provider, wallet.with_chain_id(chain_id)); - Arc::new(client) -} - -pub async fn get_chain_id(provider: &Provider) -> AppServerResult -where - J: JsonRpcClient, -{ - let chain_id = provider.get_chainid().await.map_err(|err| { - tracing::error!("Failed to retrieve Chain ID"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to retrieve Chain ID", - ) - })?; - Ok(chain_id) -} - -pub async fn get_block( - provider: &Provider, - block_number: BlockNumber, -) -> AppServerResult> -where - J: JsonRpcClient, -{ - let block = provider - .get_block(block_number) - .await - .map_err(|err| { - tracing::error!("Failed to fetch block"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to fetch block", - ) - })? - .ok_or_else(|| { - tracing::error!("Block does not exist"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Block does not exist", - ) - })?; - Ok(block) -} - -pub async fn get_balance( - provider: &Provider, - address: Address, - block_id: BlockId, -) -> AppServerResult -where - J: JsonRpcClient, -{ - let balance = provider - .get_balance(address, Some(block_id)) - .await - .map_err(|err| { - tracing::error!("Failed to get balance of address"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to get balance of address", - ) - })?; - Ok(balance) -} diff --git a/coral-lib/src/utils/mod.rs b/coral-lib/src/utils/mod.rs deleted file mode 100644 index 2e06d02..0000000 --- a/coral-lib/src/utils/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod abi; -pub mod encoding; -pub mod ethereum; -pub mod parse; -pub mod serialize; -pub mod ssl; -pub mod wallet; diff --git a/coral-lib/src/utils/parse.rs b/coral-lib/src/utils/parse.rs deleted file mode 100644 index 9a64658..0000000 --- a/coral-lib/src/utils/parse.rs +++ /dev/null @@ -1,46 +0,0 @@ -use axum::http::StatusCode; - -use ethers::utils::hex::{self}; - -use crate::error::{AppServerResult, ServerErrorResponse}; -use puffersecuresigner::strip_0x_prefix; - -pub fn parse_module_name(module_name: &str) -> AppServerResult<[u8; 32]> { - let mut module_name: String = strip_0x_prefix!(&module_name); - if module_name.len() > 64 { - let err = ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - &format!("Invalid module value: '{}'", module_name), - ); - return Err(err); - } - - for _ in module_name.len()..64 { - module_name.push('0'); - } - - let module_name_vec: Vec = hex::decode(&module_name).map_err(|err| { - let error_msg = "Failed to decode module name"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - let module_name: [u8; 32] = module_name_vec.as_slice().try_into().map_err(|err| { - let error_msg = "Module name length incorrect"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, 1000, error_msg) - })?; - Ok(module_name) -} - -pub fn parse_withdrawal_credentials(val: &[u8]) -> AppServerResult<[u8; 32]> { - let withdrawal_credentials: [u8; 32] = val.try_into().map_err(|err| { - let error_msg = "Failed to parse withdrawal_credentials"; - tracing::error!("{error_msg}"); - tracing::error!("{err}"); - ServerErrorResponse::new(StatusCode::BAD_REQUEST, 1000, error_msg) - })?; - Ok(withdrawal_credentials) -} diff --git a/coral-lib/src/utils/serialize.rs b/coral-lib/src/utils/serialize.rs deleted file mode 100644 index 0ef0850..0000000 --- a/coral-lib/src/utils/serialize.rs +++ /dev/null @@ -1,27 +0,0 @@ -use ethers::types::U256; -use serde::{de, Deserialize, Deserializer}; - -pub fn string_to_u64<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(deserializer)?; - // do better hex decoding than this - s.parse::() - .map_err(|_| de::Error::custom("failed to parse u64".to_string())) -} - -pub fn string_to_u256_base10<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(deserializer)?; - U256::from_str_radix(s, 10).map_err(|_| de::Error::custom("failed to parse U256".to_string())) -} - -pub fn u256_serialize(val: &U256, serializer: S) -> Result -where - S: serde::Serializer, -{ - serializer.serialize_str(&val.to_string()) -} diff --git a/coral-lib/src/utils/ssl.rs b/coral-lib/src/utils/ssl.rs deleted file mode 100644 index 016197b..0000000 --- a/coral-lib/src/utils/ssl.rs +++ /dev/null @@ -1,107 +0,0 @@ -use axum::http::StatusCode; -use openssl::x509::X509; - -use crate::error::{AppServerResult, ServerErrorResponse}; - -pub fn extract_x509(signing_cert: &[u8]) -> AppServerResult<(X509, X509)> { - let x509s = X509::stack_from_pem(signing_cert).map_err(|err| { - tracing::error!("Failed to parse x509 cert"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to parse x509 cert", - ) - })?; - - // Extract intel's signing certificate - - let (signing_x509, root_x509) = match x509s.as_slice() { - [signing_x509, root_x509] => (signing_x509.to_owned(), root_x509.to_owned()), - _ => { - tracing::error!("Failed to split x509 cert"); - return Err(ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to split x509 cert", - )); - } - }; - Ok((signing_x509, root_x509)) -} - -pub fn verify_intel_sgx_attestation_report(x509: &X509) -> AppServerResult<()> { - match x509 - .subject_name() - .entries_by_nid(openssl::nid::Nid::COMMONNAME) - .last() - { - Some(name) => { - let n = name - .data() - .as_utf8() - .map_err(|err| { - tracing::debug!("Failed to convert to UTF-8"); - tracing::debug!("{}", err); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to convert to UTF-8", - ) - })? - .to_string(); - if n.as_str() != "Intel SGX Attestation Report Signing" { - Err(ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Invalid attestation", - )) - } else { - Ok(()) - } - } - None => Err(ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Invalid attestation", - )), - } -} - -pub fn verify_intel_sgx_root_ca(x509: &X509) -> AppServerResult<()> { - match x509 - .subject_name() - .entries_by_nid(openssl::nid::Nid::COMMONNAME) - .last() - { - Some(name) => { - let n = name - .data() - .as_utf8() - .map_err(|err| { - tracing::debug!("Failed to convert to UTF-8"); - tracing::debug!("{}", err); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to convert to UTF-8", - ) - })? - .to_string(); - if n.as_str() != "Intel SGX Attestation Report Signing CA" { - Err(ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Invalid attestation", - )) - } else { - Ok(()) - } - } - None => Err(ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Invalid attestation", - )), - } -} diff --git a/coral-lib/src/utils/wallet.rs b/coral-lib/src/utils/wallet.rs deleted file mode 100644 index 9022d8a..0000000 --- a/coral-lib/src/utils/wallet.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::fs; -use std::io::prelude::Read; -use std::path; - -use axum::http::StatusCode; -use ethers::prelude::k256::ecdsa::SigningKey; -use ethers::prelude::*; -use puffersecuresigner::strip_0x_prefix; -use rand_core::OsRng; - -use crate::error::{AppError, AppErrorKind, AppResult, AppServerResult, ServerErrorResponse}; - -pub fn generate_keystore(password: &str) -> AppServerResult<(Wallet, String)> { - let (new_wallet, keystore_uuid) = Wallet::new_keystore(".", &mut OsRng, password, None) - .map_err(|err| { - tracing::error!("Failed to generate keystore"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to generate keystore", - ) - })?; - - // Ethers Keystore API must be generated and stored in a file. - // So we have to read from it and delete it after - let keystore_json = { - let mut file = fs::File::open(&keystore_uuid).map_err(|err| { - tracing::error!("Failed to read keystore"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to read keystore", - ) - })?; - let mut contents = String::new(); - file.read_to_string(&mut contents).map_err(|err| { - tracing::error!("Failed to read keystore to string"); - tracing::error!("{err}"); - ServerErrorResponse::new( - StatusCode::INTERNAL_SERVER_ERROR, - 1000, - "Failed to read keystore to string", - ) - })?; - - // remove file after reading it - let _ = fs::remove_file(&keystore_uuid); - contents - }; - - Ok((new_wallet, keystore_json)) -} - -pub fn read_key_from_file>(file_path: P) -> std::io::Result { - let key_content = std::fs::read_to_string(file_path)?; - let key_content: String = strip_0x_prefix!(key_content.trim()); - Ok(key_content) -} - -pub fn private_key_file_to_wallet>( - private_key_path: P, -) -> AppResult { - let private_key = read_key_from_file(private_key_path)?; - let wallet: LocalWallet = private_key.parse().map_err(|err| { - tracing::error!("Invalid private key: '{}'", private_key); - tracing::error!("{err}"); - AppError::new(AppErrorKind::ParseError, "Invalid private key".to_string()) - })?; - Ok(wallet) -} - -/// Generate a random wallet. -/// Mostly used for calling view and pure functions -pub fn generate_random_wallet() -> LocalWallet { - LocalWallet::new(&mut rand::thread_rng()) -} From 4907c2aca10531b78c2193f4f6de740163c16963 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:25:22 +0100 Subject: [PATCH 08/11] update command args --- coral-cli/docs/validator.md | 11 ++++++----- coral-cli/src/commands/validator/mod.rs | 12 ++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/coral-cli/docs/validator.md b/coral-cli/docs/validator.md index 313691d..d13a949 100644 --- a/coral-cli/docs/validator.md +++ b/coral-cli/docs/validator.md @@ -38,12 +38,13 @@ Sign voluntary exit message and stop validating ``` coral-cli validator sign-voluntary-exit \ - --bls_pukey 0x0439afaa6c9c26c342c7463d8fd116d72f18ed1980a10bd6a2707a2a498315bb17ff4352b91c18b2d34391503fe15fe48b42f95fafc96d4a758172de61dd9a91e7 \ + --bls-public-key 0x0439afaa6c9c26c342c7463d8fd116d72f18ed1980a10bd6a2707a2a498315bb17ff4352b91c18b2d34391503fe15fe48b42f95fafc96d4a758172de61dd9a91e7 \ + --beacon-index 10 \ --enclave-url http://localhost:9001 \ - --beacon_url http://localhost:5052 \ + --beacon-url http://localhost:5052 \ --fork-previous-version 0x01017000 \ --fork-current-version 0x01017000 \ - --epoch 5 - --genesis_validators_root 0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69 \ - --output-file registration_001.json \ + --epoch 5 \ + --genesis-validators-root 0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69 \ + --output-file sign_vem_001.json ``` \ No newline at end of file diff --git a/coral-cli/src/commands/validator/mod.rs b/coral-cli/src/commands/validator/mod.rs index 7f19f0e..6801463 100644 --- a/coral-cli/src/commands/validator/mod.rs +++ b/coral-cli/src/commands/validator/mod.rs @@ -42,8 +42,10 @@ pub enum ValidatorCommand { input_file: PathBuf, }, SignVoluntaryExit { - #[arg(long = "validator-public-key")] - bls_pukey: String, + #[arg(long = "bls-public-key")] + bls_pubkey: String, + #[arg(long = "beacon-index")] + beacon_index: u64, #[arg(long = "enclave-url")] enclave_url: String, #[arg(long = "beacon-url")] @@ -96,7 +98,8 @@ impl ValidatorCommand { } Self::SignVoluntaryExit { enclave_url, - bls_pukey, + bls_pubkey, + beacon_index, beacon_url, fork_current_version, fork_previous_version, @@ -106,7 +109,8 @@ impl ValidatorCommand { } => { sign_vem::sign_vem_from_cmd( enclave_url, - bls_pukey, + bls_pubkey, + beacon_index, beacon_url, fork_current_version, fork_previous_version, From 3146fedeab4cc30fd12a170493e116b131ca5cb8 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:38:55 +0100 Subject: [PATCH 09/11] remove beacon url --- coral-cli/docs/validator.md | 9 ++++----- coral-cli/src/commands/validator/mod.rs | 4 ---- coral-cli/src/commands/validator/sign_vem.rs | 3 --- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/coral-cli/docs/validator.md b/coral-cli/docs/validator.md index d13a949..aedd04a 100644 --- a/coral-cli/docs/validator.md +++ b/coral-cli/docs/validator.md @@ -41,10 +41,9 @@ coral-cli validator sign-voluntary-exit \ --bls-public-key 0x0439afaa6c9c26c342c7463d8fd116d72f18ed1980a10bd6a2707a2a498315bb17ff4352b91c18b2d34391503fe15fe48b42f95fafc96d4a758172de61dd9a91e7 \ --beacon-index 10 \ --enclave-url http://localhost:9001 \ - --beacon-url http://localhost:5052 \ - --fork-previous-version 0x01017000 \ - --fork-current-version 0x01017000 \ - --epoch 5 \ - --genesis-validators-root 0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69 \ + --fork-previous-version 0x04017000 \ + --fork-current-version 0x05017000 \ + --epoch 29696 \ + --genesis-validators-root 0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1 \ --output-file sign_vem_001.json ``` \ No newline at end of file diff --git a/coral-cli/src/commands/validator/mod.rs b/coral-cli/src/commands/validator/mod.rs index 6801463..f0efe82 100644 --- a/coral-cli/src/commands/validator/mod.rs +++ b/coral-cli/src/commands/validator/mod.rs @@ -48,8 +48,6 @@ pub enum ValidatorCommand { beacon_index: u64, #[arg(long = "enclave-url")] enclave_url: String, - #[arg(long = "beacon-url")] - beacon_url: String, #[arg(long = "fork-previous-version")] fork_previous_version: String, #[arg(long = "fork-current-version")] @@ -100,7 +98,6 @@ impl ValidatorCommand { enclave_url, bls_pubkey, beacon_index, - beacon_url, fork_current_version, fork_previous_version, epoch, @@ -111,7 +108,6 @@ impl ValidatorCommand { enclave_url, bls_pubkey, beacon_index, - beacon_url, fork_current_version, fork_previous_version, epoch, diff --git a/coral-cli/src/commands/validator/sign_vem.rs b/coral-cli/src/commands/validator/sign_vem.rs index e0a6ebd..e812e4f 100644 --- a/coral-cli/src/commands/validator/sign_vem.rs +++ b/coral-cli/src/commands/validator/sign_vem.rs @@ -21,7 +21,6 @@ pub struct SignVoluntaryExitMessageInput { pub bls_pubkey: String, pub beacon_index: u64, pub enclave_url: String, - pub beacon_url: String, pub fork: Fork, pub genesis_validators_root: [u8; 32], pub output_file: String, @@ -32,7 +31,6 @@ pub async fn sign_vem_from_cmd( enclave_url: String, bls_pubkey: String, beacon_index: u64, - beacon_url: String, fork_current_version: String, fork_previous_version: String, epoch: u64, @@ -51,7 +49,6 @@ pub async fn sign_vem_from_cmd( bls_pubkey, beacon_index, enclave_url, - beacon_url, fork: converted_fork_info.fork, genesis_validators_root: converted_fork_info.genesis_validators_root, output_file, From b0f554589c281d02a5a3b116e3d222c227f55f47 Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:58:17 +0100 Subject: [PATCH 10/11] update example, secure-signer branch --- Cargo.lock | 2 +- coral-cli/Cargo.toml | 2 +- coral-cli/docs/validator.md | 4 ++-- coral-lib/Cargo.toml | 2 +- coral-lib/src/lib.rs | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b19ea92..f9594e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3285,7 +3285,7 @@ dependencies = [ [[package]] name = "puffersecuresigner" version = "0.1.0" -source = "git+https://github.com/PufferFinance/secure-signer.git#36a8c31ef566efaa7d302ce930fec0ef197b93ab" +source = "git+https://github.com/PufferFinance/secure-signer.git?branch=feature/error#e5fc8307eda4371d0022b1b00803c2a259a06cc0" dependencies = [ "anyhow", "async-trait", diff --git a/coral-cli/Cargo.toml b/coral-cli/Cargo.toml index 984089c..809be48 100644 --- a/coral-cli/Cargo.toml +++ b/coral-cli/Cargo.toml @@ -25,4 +25,4 @@ tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } # Puffer dependencies coral-lib = { path = "../coral-lib" } -puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git" } +puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git", branch = "feature/error" } diff --git a/coral-cli/docs/validator.md b/coral-cli/docs/validator.md index aedd04a..6db82d6 100644 --- a/coral-cli/docs/validator.md +++ b/coral-cli/docs/validator.md @@ -38,8 +38,8 @@ Sign voluntary exit message and stop validating ``` coral-cli validator sign-voluntary-exit \ - --bls-public-key 0x0439afaa6c9c26c342c7463d8fd116d72f18ed1980a10bd6a2707a2a498315bb17ff4352b91c18b2d34391503fe15fe48b42f95fafc96d4a758172de61dd9a91e7 \ - --beacon-index 10 \ + --bls-public-key 0x94505f60bb8e48ddafb8835ec08537c48ed1bb9bc6a95fe941f37869b5eb0950c9023b7a997fe12d8aa79076561e009f \ + --beacon-index 1605300 \ --enclave-url http://localhost:9001 \ --fork-previous-version 0x04017000 \ --fork-current-version 0x05017000 \ diff --git a/coral-lib/Cargo.toml b/coral-lib/Cargo.toml index b6e91d2..83708ba 100644 --- a/coral-lib/Cargo.toml +++ b/coral-lib/Cargo.toml @@ -19,4 +19,4 @@ tower-http = { version = "0.5.0", features = [ "cors", "trace" ] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } -puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git" } +puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git", branch = "feature/error" } diff --git a/coral-lib/src/lib.rs b/coral-lib/src/lib.rs index 1b286f0..8ba13c6 100644 --- a/coral-lib/src/lib.rs +++ b/coral-lib/src/lib.rs @@ -1,7 +1,6 @@ pub mod error; pub mod structs; - #[inline] pub fn strip_0x_prefix(s: &str) -> &str { s.strip_prefix("0x").unwrap_or(s) From c96a6e9541964d78807e2a19faeab03e7bfb2e5c Mon Sep 17 00:00:00 2001 From: lean-apple <78718413+lean-apple@users.noreply.github.com> Date: Mon, 26 Feb 2024 19:14:16 +0100 Subject: [PATCH 11/11] remove useless deps and udpate some --- Cargo.lock | 69 ++++++++++++++++++++------------------------ coral-cli/Cargo.toml | 20 ++++++------- coral-lib/Cargo.toml | 12 ++------ 3 files changed, 45 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9594e8..dbd1b8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -178,7 +178,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -206,7 +206,7 @@ checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -329,7 +329,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -528,9 +528,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "regex-automata 0.4.5", @@ -619,9 +619,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" dependencies = [ "libc", ] @@ -696,7 +696,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -775,9 +775,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d59688ad0945eaf6b84cb44fedbe93484c81b48970e98f09db8a22832d7961" +checksum = "efbd12d49ab0eaf8193ba9175e45f56bbc2e4b27d57b8cfe62aa47942a46b9a9" dependencies = [ "cfg-if", "cpufeatures", @@ -837,13 +837,8 @@ dependencies = [ name = "coral-lib" version = "0.1.0" dependencies = [ - "async-trait", "axum 0.7.4", - "base64 0.21.7", "ethers", - "openssl", - "puffersecuresigner", - "rand_core 0.6.4", "reqwest", "serde", "serde_json", @@ -1484,7 +1479,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.50", + "syn 2.0.51", "toml", "walkdir", ] @@ -1502,7 +1497,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -1528,7 +1523,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.50", + "syn 2.0.51", "tempfile", "thiserror", "tiny-keccak", @@ -1861,7 +1856,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -2056,9 +2051,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" [[package]] name = "hex" @@ -2791,7 +2786,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -2863,7 +2858,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -3093,7 +3088,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -3131,7 +3126,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -3199,7 +3194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -3285,7 +3280,7 @@ dependencies = [ [[package]] name = "puffersecuresigner" version = "0.1.0" -source = "git+https://github.com/PufferFinance/secure-signer.git?branch=feature/error#e5fc8307eda4371d0022b1b00803c2a259a06cc0" +source = "git+https://github.com/PufferFinance/secure-signer.git#d360de54559d10af148ede47a40ff7249a120655" dependencies = [ "anyhow", "async-trait", @@ -3855,7 +3850,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4122,7 +4117,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4164,9 +4159,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c" dependencies = [ "proc-macro2", "quote", @@ -4255,7 +4250,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4359,7 +4354,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4543,7 +4538,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4812,7 +4807,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", "wasm-bindgen-shared", ] @@ -4846,7 +4841,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5130,7 +5125,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] diff --git a/coral-cli/Cargo.toml b/coral-cli/Cargo.toml index 809be48..faae0d4 100644 --- a/coral-cli/Cargo.toml +++ b/coral-cli/Cargo.toml @@ -4,25 +4,25 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.2" -chrono = "0.4.31" -clap = { version = "4.4.11", features = ["derive"] } -clap_complete = "4.4.4" +axum = "0.7.4" +chrono = "0.4.34" +clap = { version = "4.5.1", features = ["derive"] } +clap_complete = "4.5.1" colored = "2.1.0" dirs-next = "2.0.0" ecies = { version = "0.2.6", default-features = false, features = ["pure"] } hex = "0.4.3" lazy_static = "1.4.0" -reqwest = { version = "0.11.23", features = ["json"] } -serde = { version = "1.0.193", features = ["derive"] } -serde_json = "1.0.108" +reqwest = { version = "0.11.24", features = ["json"] } +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.114" shellexpand = { version = "3.1.0", features = ["full"] } -tokio = { version = "1.35.1", features = ["full"] } -tower-http = { version = "0.5.0", features = [ "cors", "trace" ] } +tokio = { version = "1.36.0", features = ["full"] } +tower-http = { version = "0.5.2", features = [ "cors", "trace" ] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } # Puffer dependencies coral-lib = { path = "../coral-lib" } -puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git", branch = "feature/error" } +puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git" } diff --git a/coral-lib/Cargo.toml b/coral-lib/Cargo.toml index 83708ba..d2c47c1 100644 --- a/coral-lib/Cargo.toml +++ b/coral-lib/Cargo.toml @@ -4,19 +4,13 @@ version = "0.1.0" edition = "2021" [dependencies] -async-trait = "0.1.77" axum = "0.7.4" -base64 = "0.21.7" ethers = "2.0.13" -openssl = "0.10.64" -rand_core = "0.6.4" reqwest = { version = "0.11.24", features = ["json"] } -serde = { version = "1.0.195", features = ["derive"] } +serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.111" tokio = { version = "1.36.0", features = ["full"] } toml = "0.8.10" -tower-http = { version = "0.5.0", features = [ "cors", "trace" ] } +tower-http = { version = "0.5.2", features = [ "cors", "trace" ] } tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } - -puffersecuresigner = { git ="https://github.com/PufferFinance/secure-signer.git", branch = "feature/error" } +tracing-subscriber = { version = "0.3.18", features = [ "std", "env-filter" ] } \ No newline at end of file