From ab9bcdca690faa0f857bf1368bc63a0dfa807312 Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 16 Jun 2023 11:32:47 -0500 Subject: [PATCH 01/25] chore: config for running in dev --- .example.env | 3 +++ .example.env.dev | 5 ++++- .gitignore | 1 + docker-compose-dev.yml | 1 + docker-compose.yml | 1 + docs/tech/configuration.md | 9 +++++++++ example.env.dev.sh | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 56 insertions(+), 1 deletion(-) create mode 100755 example.env.dev.sh diff --git a/.example.env b/.example.env index 96eb64f..3a1f889 100644 --- a/.example.env +++ b/.example.env @@ -33,3 +33,6 @@ ACCESS_TOKEN_LIFE = 360000000 RATE_LIMIT_WINDOW = 5 RATE_LIMIT_MAX_REQUESTS = 100 + +# custom variables +export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" diff --git a/.example.env.dev b/.example.env.dev index c9a1772..141c0c2 100644 --- a/.example.env.dev +++ b/.example.env.dev @@ -31,4 +31,7 @@ ACCESS_TOKEN_LIFE = 360000000 #RATE LIMIT RATE_LIMIT_WINDOW = 5 -RATE_LIMIT_MAX_REQUESTS = 100 \ No newline at end of file +RATE_LIMIT_MAX_REQUESTS = 100 + +# custom variables +export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" diff --git a/.gitignore b/.gitignore index 1452ac5..ea60631 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ not-commitable/ ### dotenv ### +.env.dev.sh .env.dev .env.test .env.prod diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 68d2efe..7571159 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -36,6 +36,7 @@ services: ACCESS_TOKEN_LIFE: "${ACCESS_TOKEN_LIFE}" RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" + TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" restart: on-failure diff --git a/docker-compose.yml b/docker-compose.yml index 4c50847..078110f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,6 +41,7 @@ services: ACCESS_TOKEN_LIFE: "${ACCESS_TOKEN_LIFE}" RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" + TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" restart: on-failure diff --git a/docs/tech/configuration.md b/docs/tech/configuration.md index 355ed58..74cea2f 100644 --- a/docs/tech/configuration.md +++ b/docs/tech/configuration.md @@ -18,6 +18,15 @@ LacPass Trusted List is the component that allows getting all public keys that a In order to run the app with Docker, you should install or update to the latest version, we recommend to install [Docker-Desktop](https://docs.docker.com/get-docker/) due to composer and some cool CLI-UI tools are included. +## Running directly + +```sh +cp example.env.dev.sh .env.dev.sh +chmod +x .env.dev.sh +./.env.dev.sh +RUST_LOG="debug,tower_http=trace" cargo run # RUST_LOG="debug,tower_http=trace" cargo watch -x run (if you have "watch" installed) +``` + ### Development with Docker The following commands will build and run all you need to start working on the base, without any other installation requirements. Important: if you already have postgres running locally, you'll need to kill the service before run `docker-compose up`. diff --git a/example.env.dev.sh b/example.env.dev.sh new file mode 100755 index 0000000..c50084b --- /dev/null +++ b/example.env.dev.sh @@ -0,0 +1,37 @@ +#PORT + +export PORT=80 # use port 80 when running with docker +export EXPOSED_CONTAINER_SERVER_PORT=3025 + +#TYPEORM + +export TYPEORM_TYPE=postgres +export TYPEORM_HOST=localhost +export TYPEORM_USERNAME=postgres +export TYPEORM_PASSWORD=postgres +export TYPEORM_DATABASE=lacpass_trusted_list_development +export TYPEORM_PORT=5432 +export TYPEORM_SYNCHRONIZE=false +export TYPEORM_LOGGING=true +export TYPEORM_MIGRATIONS_RUN=true +export EXPOSED_CONTAINER_TYPEORM_PORT=5455 + +#REDIS + +export REDIS_HOST=redis +export REDIS_PORT=6379 +export REDIS_PASSWORD=redis +export EXPOSED_CONTAINER_REDIS_PORT=6405 + +#TOKEN + +export JWT_SECRET=some-secret-string +export ACCESS_TOKEN_LIFE=360000000 + +#RATE LIMIT + +export RATE_LIMIT_WINDOW=5 +export RATE_LIMIT_MAX_REQUESTS=100 + +# custom variables +export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" From 73c49b4d801cabab521e5d638d79686fae2d045e Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 16 Jun 2023 11:34:43 -0500 Subject: [PATCH 02/25] chore: scafolding to run job manager to update public keys --- Cargo.lock | 1 + Cargo.toml | 1 + src/jobs.rs | 3 ++ src/jobs/index.rs | 26 ++++++++++++++++ src/jobs/trusted_registries.rs | 56 ++++++++++++++++++++++++++++++++++ src/jobs/trusted_registry.rs | 27 ++++++++++++++++ src/main.rs | 5 +++ 7 files changed, 119 insertions(+) create mode 100644 src/jobs.rs create mode 100644 src/jobs/index.rs create mode 100644 src/jobs/trusted_registries.rs create mode 100644 src/jobs/trusted_registry.rs diff --git a/Cargo.lock b/Cargo.lock index 57808c1..b67fc75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -674,6 +674,7 @@ dependencies = [ "rocket_cors", "rocket_okapi", "serde", + "tokio", "uuid", "yansi", ] diff --git a/Cargo.toml b/Cargo.toml index ac15795..a95e0b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ env_logger = "0.9.0" chrono = "0.4.19" anyhow = "1.0.58" clap = "3.2.8" +tokio = { version = "1.28.2" } [dependencies.rocket_okapi] diff --git a/src/jobs.rs b/src/jobs.rs new file mode 100644 index 0000000..a081b87 --- /dev/null +++ b/src/jobs.rs @@ -0,0 +1,3 @@ +pub mod index; +pub mod trusted_registries; +pub mod trusted_registry; diff --git a/src/jobs/index.rs b/src/jobs/index.rs new file mode 100644 index 0000000..5c5b1b2 --- /dev/null +++ b/src/jobs/index.rs @@ -0,0 +1,26 @@ +use std::{thread, time::Duration}; + +use log::info; + +use crate::jobs::trusted_registries::TrustedRegistries; + +#[derive(Debug)] +pub struct JobManager {} +impl JobManager { + pub fn sweep_trusted_registries() { + info!("Starting Trusted Registres Worker"); + let _p = TrustedRegistries::new() + .registries + .into_iter() + .map(|r| { + tokio::spawn(async move { + thread::sleep(Duration::from_secs(r.start_up)); + loop { + r.sweep(); + thread::sleep(Duration::from_secs(r.period_seconds)) + } + }) + }) + .collect::>(); + } +} diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs new file mode 100644 index 0000000..47b2ec9 --- /dev/null +++ b/src/jobs/trusted_registries.rs @@ -0,0 +1,56 @@ +use crate::utils::utils::Utils; +use serde::{Deserialize, Serialize}; + +use super::trusted_registry::{Contract, TrustedRegistry}; + +#[derive(Deserialize, Serialize)] +pub struct TrustedRegistries { + pub registries: Vec, +} + +impl TrustedRegistries { + pub fn new() -> TrustedRegistries { + let mut s = TrustedRegistries { + registries: Vec::new(), + }; + s.set_trusted_registries(); + s.set_start_up_and_period(); + s + } + fn get_trusted_registries(&self) -> String { + match Utils::get_env_or_err("TRUSTED_REGISTRIES") { + Ok(s) => s, + Err(_) => panic!("Please set TRUSTED_REGISTRIES environment variable"), + } + } + + fn set_trusted_registries(&mut self) -> () { + let _raw_trusted_registries = self.get_trusted_registries(); + let t1 = TrustedRegistry { + period_seconds: 400, + start_up: 5, + public_directory: Contract { + chain_id: 0x9e55c, + contract_address: "0x4A1bD1198890af301AF9b6F3a3a11952a86C1c8e".to_owned(), + }, + chain_of_trust: Contract { + chain_id: 0x9e55c, + contract_address: "0xEBB6854aa875867f684dd1d2338eC20908039c67".to_owned(), + }, + }; + let mut trs: Vec = Vec::new(); + trs.push(t1); + self.registries = trs; + } + + fn set_start_up_and_period(&mut self) -> () { + // TODO: improve start up + let _p = (0..self.registries.len()) + .into_iter() + .map(|i| { + self.registries[i].start_up = (i as u64) * 100; + self.registries[i].period_seconds = 2000; + }) + .collect::>(); + } +} diff --git a/src/jobs/trusted_registry.rs b/src/jobs/trusted_registry.rs new file mode 100644 index 0000000..1d3b5f5 --- /dev/null +++ b/src/jobs/trusted_registry.rs @@ -0,0 +1,27 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug)] +pub struct Contract { + pub chain_id: i32, + pub contract_address: String, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct TrustedRegistry { + pub public_directory: Contract, + pub chain_of_trust: Contract, + pub period_seconds: u64, + pub start_up: u64, +} + +impl TrustedRegistry { + pub fn sweep(&self) { + info!( + "Sweeping trusted registry ... {:?} {:?}", + self.public_directory, self.chain_of_trust + ); + // read public directory last changes + // read chain of trust last changes + // read did registry changes + } +} diff --git a/src/main.rs b/src/main.rs index 7bd83ed..fa08329 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod config; pub mod controllers; pub mod dto; +pub mod jobs; mod logger_config; pub mod responses; pub mod services; @@ -10,6 +11,7 @@ pub mod utils; extern crate rocket; use controllers::index::stage; +use jobs::index::JobManager; use crate::config::get_envs; use crate::logger_config::setup_logger; @@ -18,5 +20,8 @@ use crate::logger_config::setup_logger; async fn rocket() -> _ { let envs = get_envs().await.unwrap(); setup_logger(true, envs.value_of("log-conf")); + tokio::spawn(async move { + JobManager::sweep_trusted_registries(); + }); rocket::build().attach(stage()) } From 923767e08e110015d17412323ecdda2baafcdee6 Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 16 Jun 2023 23:23:07 -0500 Subject: [PATCH 03/25] fix: database connection data fix --- .example.env | 2 +- .example.env.dev | 2 +- Dockerfile.prod | 4 ++-- docker-compose-dev.yml | 9 +++++---- docker-compose.yml | 9 +++++---- example.env.dev.sh | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.example.env b/.example.env index 3a1f889..bfb1448 100644 --- a/.example.env +++ b/.example.env @@ -7,7 +7,7 @@ EXPOSED_CONTAINER_SERVER_PORT = 3025 #TYPEORM TYPEORM_TYPE = postgres -TYPEORM_HOST = localhost +TYPEORM_HOST = postgres TYPEORM_USERNAME = postgres TYPEORM_PASSWORD = postgres TYPEORM_DATABASE = lacpass_trusted_list diff --git a/.example.env.dev b/.example.env.dev index 141c0c2..1a5981a 100644 --- a/.example.env.dev +++ b/.example.env.dev @@ -6,7 +6,7 @@ EXPOSED_CONTAINER_SERVER_PORT = 3025 #TYPEORM TYPEORM_TYPE = postgres -TYPEORM_HOST = localhost +TYPEORM_HOST = postgres TYPEORM_USERNAME = postgres TYPEORM_PASSWORD = postgres TYPEORM_DATABASE = lacpass_trusted_list_development diff --git a/Dockerfile.prod b/Dockerfile.prod index 6a3c3ed..deb3691 100644 --- a/Dockerfile.prod +++ b/Dockerfile.prod @@ -2,7 +2,7 @@ FROM rust:1.70.0 as builder WORKDIR /usr/src/lacpass-trusted-list COPY . . RUN cargo install --path . -FROM debian:buster-slim -RUN apt-get update & apt-get install -y extra-runtime-dependencies & rm -rf /var/lib/apt/lists/* +FROM debian:bullseye-slim +RUN apt-get update & apt-get install -y extra-runtime-dependencies openssl & rm -rf /var/lib/apt/lists/* COPY --from=builder /usr/local/cargo/bin/lacpass-trusted-list /usr/local/bin/lacpass-trusted-list CMD ["lacpass-trusted-list"] \ No newline at end of file diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 7571159..880bba2 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -24,10 +24,10 @@ services: environment: PORT: "${PORT}" JWT_SECRET: "${JWT_SECRET}" - TYPEORM_TYPE: postgres - TYPEORM_HOST: postgres - TYPEORM_USERNAME: postgres - TYPEORM_PASSWORD: postgres + TYPEORM_TYPE: "${TYPEORM_TYPE}" + TYPEORM_HOST: "${TYPEORM_HOST}" + TYPEORM_USERNAME: "${TYPEORM_USERNAME}" + TYPEORM_PASSWORD: "{TYPEORM_PASSWORD}" TYPEORM_DATABASE: "${TYPEORM_DATABASE}" TYPEORM_PORT: "${TYPEORM_PORT}" TYPEORM_SYNCHRONIZE: "true" @@ -37,6 +37,7 @@ services: RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" + DATABASE_URL: "postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" restart: on-failure diff --git a/docker-compose.yml b/docker-compose.yml index 078110f..0ae880f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,10 +29,10 @@ services: environment: PORT: "${PORT}" JWT_SECRET: "${JWT_SECRET}" - TYPEORM_TYPE: postgres - TYPEORM_HOST: postgres - TYPEORM_USERNAME: postgres - TYPEORM_PASSWORD: postgres + TYPEORM_TYPE: "${TYPEORM_TYPE}" + TYPEORM_HOST: "${TYPEORM_HOST}" + TYPEORM_USERNAME: "${TYPEORM_USERNAME}" + TYPEORM_PASSWORD: "{TYPEORM_PASSWORD}" TYPEORM_DATABASE: "${TYPEORM_DATABASE}" TYPEORM_PORT: "${TYPEORM_PORT}" TYPEORM_SYNCHRONIZE: "true" @@ -42,6 +42,7 @@ services: RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" + DATABASE_URL: "postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" restart: on-failure diff --git a/example.env.dev.sh b/example.env.dev.sh index c50084b..212f26f 100755 --- a/example.env.dev.sh +++ b/example.env.dev.sh @@ -6,7 +6,7 @@ export EXPOSED_CONTAINER_SERVER_PORT=3025 #TYPEORM export TYPEORM_TYPE=postgres -export TYPEORM_HOST=localhost +export TYPEORM_HOST=127.0.0.1 export TYPEORM_USERNAME=postgres export TYPEORM_PASSWORD=postgres export TYPEORM_DATABASE=lacpass_trusted_list_development From cf42b5e4ac100f9d3b788ace5de591bd5e65586c Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 16 Jun 2023 23:27:41 -0500 Subject: [PATCH 04/25] chore: add database configuration --- Cargo.lock | 1984 ++++++++++++++++- Cargo.toml | 6 + src/config.rs | 16 +- .../config.rs => config/env_config.rs} | 18 + src/config/log_config.rs | 14 + src/controllers.rs | 1 - src/controllers/index.rs | 2 +- src/databases.rs | 1 + src/databases/pool.rs | 39 + src/jobs/index.rs | 19 +- src/jobs/trusted_registries.rs | 2 + src/jobs/trusted_registry.rs | 23 +- src/main.rs | 7 +- 13 files changed, 2051 insertions(+), 81 deletions(-) rename src/{controllers/config.rs => config/env_config.rs} (81%) create mode 100644 src/config/log_config.rs create mode 100644 src/databases.rs create mode 100644 src/databases/pool.rs diff --git a/Cargo.lock b/Cargo.lock index b67fc75..b3f3b36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,34 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.0.2" @@ -11,6 +39,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + +[[package]] +name = "allocator-api2" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -32,6 +72,12 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "arrayvec" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8868f09ff8cea88b079da74ae569d9b8c62a23c68c746240b704ee6f7525c89c" + [[package]] name = "async-stream" version = "0.3.5" @@ -65,6 +111,15 @@ dependencies = [ "syn 2.0.18", ] +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic" version = "0.5.3" @@ -88,6 +143,42 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bae" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "bigdecimal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "binascii" version = "0.1.4" @@ -106,12 +197,140 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" +[[package]] +name = "bitvec" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" +dependencies = [ + "funty 1.1.0", + "radium 0.6.2", + "tap", + "wyz 0.2.0", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty 2.0.0", + "radium 0.7.0", + "tap", + "wyz 0.5.1", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "borsh" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +dependencies = [ + "borsh-derive", + "hashbrown 0.12.3", +] + +[[package]] +name = "borsh-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bumpalo" version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "bytecheck" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.4.0" @@ -140,6 +359,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "time 0.1.45", "wasm-bindgen", "winapi", @@ -169,6 +389,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.17.0" @@ -180,12 +406,66 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "cpufeatures" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.13.4" @@ -221,14 +501,47 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "devise" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595" +dependencies = [ + "devise_codegen 0.3.1", + "devise_core 0.3.1", +] + [[package]] name = "devise" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6eacefd3f541c66fc61433d65e54e0e46e0a029a819a7dbbc7a7b489e8a85f8" dependencies = [ - "devise_codegen", - "devise_core", + "devise_codegen 0.4.1", + "devise_core 0.4.1", +] + +[[package]] +name = "devise_codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" +dependencies = [ + "devise_core 0.3.1", + "quote", ] [[package]] @@ -237,8 +550,21 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8cf4b8dd484ede80fd5c547592c46c3745a617c8af278e2b72bea86b2dfed6" dependencies = [ - "devise_core", + "devise_core 0.4.1", + "quote", +] + +[[package]] +name = "devise_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" +dependencies = [ + "bitflags 1.3.2", + "proc-macro2", + "proc-macro2-diagnostics 0.9.1", "quote", + "syn 1.0.109", ] [[package]] @@ -249,11 +575,57 @@ checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" dependencies = [ "bitflags 2.3.2", "proc-macro2", - "proc-macro2-diagnostics", + "proc-macro2-diagnostics 0.10.0", "quote", "syn 2.0.18", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dyn-clone" version = "1.0.11" @@ -296,7 +668,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -309,6 +681,54 @@ dependencies = [ "libc", ] +[[package]] +name = "ethabi" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c98847055d934070b90e806e12d3936b787d0a115068981c1d8dfd5dfef5a5" +dependencies = [ + "ethereum-types", + "hex", + "serde", + "serde_json", + "sha3 0.9.1", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fastrand" version = "1.9.0" @@ -327,16 +747,43 @@ dependencies = [ "atomic", "pear", "serde", - "toml", + "toml 0.7.4", "uncased", "version_check", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "fixed-hash" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" @@ -347,6 +794,18 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.28" @@ -355,6 +814,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -377,12 +837,45 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + [[package]] name = "futures-io" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "futures-sink" version = "0.3.28" @@ -395,6 +888,12 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.28" @@ -404,6 +903,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -425,6 +925,16 @@ dependencies = [ "windows", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -466,6 +976,71 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "ahash 0.8.3", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +dependencies = [ + "hashbrown 0.14.0", +] + +[[package]] +name = "headers" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +dependencies = [ + "base64 0.13.1", + "bitflags 1.3.2", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "hermit-abi" @@ -491,6 +1066,30 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "http" version = "0.2.9" @@ -555,6 +1154,19 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "iana-time-zone" version = "0.1.57" @@ -584,6 +1196,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.4.0" @@ -594,6 +1217,44 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-codec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -601,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "serde", ] @@ -628,9 +1289,15 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + [[package]] name = "is-terminal" version = "0.4.7" @@ -640,7 +1307,16 @@ dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", ] [[package]] @@ -658,6 +1334,30 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + [[package]] name = "lacpass-trusted-list" version = "0.1.0" @@ -673,9 +1373,14 @@ dependencies = [ "rocket", "rocket_cors", "rocket_okapi", + "sea-orm", + "sea-orm-rocket", "serde", + "serde_json", + "sha3 0.10.8", "tokio", "uuid", + "web3", "yansi", ] @@ -737,6 +1442,21 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "md-5" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "memchr" version = "2.5.0" @@ -749,6 +1469,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "mio" version = "0.8.8" @@ -757,7 +1483,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -774,12 +1500,40 @@ dependencies = [ "log", "memchr", "mime", - "spin", + "spin 0.9.8", "tokio", "tokio-util", "version_check", ] +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -790,6 +1544,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -828,40 +1603,170 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] -name = "os_str_bytes" -version = "6.5.1" +name = "opaque-debug" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "overload" -version = "0.1.1" +name = "openssl" +version = "0.10.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] [[package]] -name = "parking_lot" -version = "0.12.1" +name = "openssl-macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "lock_api", - "parking_lot_core", + "proc-macro2", + "quote", + "syn 2.0.18", ] [[package]] -name = "parking_lot_core" -version = "0.9.8" +name = "openssl-probe" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "os_str_bytes" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" + +[[package]] +name = "ouroboros" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1358bd1558bd2a083fed428ffeda486fbfb323e698cdda7794259d592ca72db" +dependencies = [ + "aliasable", + "ouroboros_macro", +] + +[[package]] +name = "ouroboros_macro" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parity-scale-codec" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" +dependencies = [ + "arrayvec", + "bitvec 0.20.4", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if", + "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", "smallvec", "windows-targets", ] +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + [[package]] name = "pear" version = "0.2.4" @@ -880,7 +1785,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9661a3a53f93f09f2ea882018e4d7c88f6ff2956d809a276060476fd8c879d3c" dependencies = [ "proc-macro2", - "proc-macro2-diagnostics", + "proc-macro2-diagnostics 0.10.0", "quote", "syn 2.0.18", ] @@ -891,6 +1796,26 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -903,12 +1828,74 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "primitive-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.60" @@ -918,6 +1905,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", + "yansi", +] + [[package]] name = "proc-macro2-diagnostics" version = "0.10.0" @@ -931,6 +1931,26 @@ dependencies = [ "yansi", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quote" version = "1.0.28" @@ -940,6 +1960,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.5" @@ -970,6 +2002,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -979,6 +2020,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "ref-cast" version = "1.0.16" @@ -1031,6 +2083,107 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +[[package]] +name = "rend" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64 0.21.2", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rkyv" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +dependencies = [ + "bitvec 1.0.1", + "bytecheck", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rocket" version = "0.5.0-rc.3" @@ -1051,7 +2204,7 @@ dependencies = [ "memchr", "multer", "num_cpus", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "rand", "ref-cast", @@ -1076,7 +2229,7 @@ version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7093353f14228c744982e409259fb54878ba9563d08214f2d880d59ff2fc508b" dependencies = [ - "devise", + "devise 0.4.1", "glob", "indexmap", "proc-macro2", @@ -1155,6 +2308,39 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rust_decimal" +version = "1.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0446843641c69436765a35a5a77088e28c2e6a12da93e84aa3ab1cd4aa5a042" +dependencies = [ + "arrayvec", + "borsh", + "bytecheck", + "byteorder", + "bytes", + "num-traits", + "rand", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.37.20" @@ -1166,7 +2352,38 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", ] [[package]] @@ -1181,6 +2398,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + [[package]] name = "schemars" version = "0.8.12" @@ -1218,6 +2444,178 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sea-orm" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fade86e8d41fd1a4721f84cb834f4ca2783f973cc30e6212b7fafc134f169214" +dependencies = [ + "async-stream", + "async-trait", + "bigdecimal", + "chrono", + "futures", + "log", + "ouroboros", + "rust_decimal", + "sea-orm-macros", + "sea-query", + "sea-query-binder", + "sea-strum", + "serde", + "serde_json", + "sqlx", + "thiserror", + "time 0.3.22", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "sea-orm-macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28936f26d62234ff0be16f80115dbdeb3237fe9c25cf18fbcd1e3b3592360f20" +dependencies = [ + "bae", + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sea-orm-rocket" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30f30b2cf45d317def42af8542635e341fa4ae12fb0697a713346750ff426aa2" +dependencies = [ + "rocket", + "sea-orm-rocket-codegen", +] + +[[package]] +name = "sea-orm-rocket-codegen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfd750adb2541f30b855e2d86e90bf7031ac17e048ac5226a8e8c8d8a6022f2" +dependencies = [ + "devise 0.3.1", + "quote", +] + +[[package]] +name = "sea-query" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbab99b8cd878ab7786157b7eb8df96333a6807cc6e45e8888c85b51534b401a" +dependencies = [ + "bigdecimal", + "chrono", + "rust_decimal", + "sea-query-derive", + "serde_json", + "time 0.3.22", + "uuid", +] + +[[package]] +name = "sea-query-binder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cea85029985b40dfbf18318d85fe985c04db7c1b4e5e8e0a0a0cdff5f1e30f9" +dependencies = [ + "bigdecimal", + "chrono", + "rust_decimal", + "sea-query", + "serde_json", + "sqlx", + "time 0.3.22", + "uuid", +] + +[[package]] +name = "sea-query-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "sea-strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" +dependencies = [ + "sea-strum_macros", +] + +[[package]] +name = "sea-strum_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.164" @@ -1239,34 +2637,90 @@ dependencies = [ ] [[package]] -name = "serde_derive_internals" -version = "0.26.0" +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "cfg-if", + "cpufeatures", + "digest 0.10.7", ] [[package]] -name = "serde_json" -version = "1.0.96" +name = "sha3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "itoa", - "ryu", - "serde", + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug", ] [[package]] -name = "serde_spanned" -version = "0.6.2" +name = "sha3" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "serde", + "digest 0.10.7", + "keccak", ] [[package]] @@ -1287,6 +2741,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "slab" version = "0.4.8" @@ -1312,12 +2772,125 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "sqlformat" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +dependencies = [ + "ahash 0.7.6", + "atoi", + "base64 0.13.1", + "bigdecimal", + "bitflags 1.3.2", + "byteorder", + "bytes", + "chrono", + "crossbeam-queue", + "dirs", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "hkdf", + "hmac", + "indexmap", + "itoa", + "libc", + "log", + "md-5", + "memchr", + "num-bigint", + "once_cell", + "paste", + "percent-encoding", + "rand", + "rust_decimal", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "time 0.3.22", + "tokio-stream", + "url", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.1", + "once_cell", + "proc-macro2", + "quote", + "serde_json", + "sqlx-core", + "sqlx-rt", + "syn 1.0.109", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" +dependencies = [ + "native-tls", + "once_cell", + "tokio", + "tokio-native-tls", +] + [[package]] name = "stable-pattern" version = "0.1.0" @@ -1336,12 +2909,34 @@ dependencies = [ "loom", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -1364,6 +2959,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.6.0" @@ -1373,9 +2974,9 @@ dependencies = [ "autocfg", "cfg-if", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1393,6 +2994,26 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -1441,6 +3062,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1471,7 +3101,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1485,6 +3115,26 @@ dependencies = [ "syn 2.0.18", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -1510,6 +3160,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.7.4" @@ -1557,6 +3216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1618,6 +3278,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + [[package]] name = "ubyte" version = "0.10.3" @@ -1627,6 +3293,18 @@ dependencies = [ "serde", ] +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "uncased" version = "0.9.9" @@ -1667,12 +3345,30 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-xid" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.4.0" @@ -1680,7 +3376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", - "idna", + "idna 0.4.0", "percent-encoding", ] @@ -1691,6 +3387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" dependencies = [ "getrandom", + "serde", ] [[package]] @@ -1699,6 +3396,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" @@ -1752,6 +3455,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.87" @@ -1781,6 +3496,74 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web3" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f258e254752d210b84fe117b31f1e3cc9cbf04c0d747eb7f8cf7cf5e370f6d" +dependencies = [ + "arrayvec", + "base64 0.13.1", + "bytes", + "derive_more", + "ethabi", + "ethereum-types", + "futures", + "futures-timer", + "headers", + "hex", + "idna 0.2.3", + "jsonrpc-core", + "log", + "parking_lot 0.12.1", + "pin-project", + "reqwest", + "rlp", + "serde", + "serde_json", + "tiny-keccak", + "url", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "whoami" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c70234412ca409cc04e864e89523cb0fc37f5e1344ebed5a3ebf4192b6b9f68" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1821,6 +3604,21 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1836,51 +3634,93 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -1896,6 +3736,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "yansi" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index a95e0b7..b0a13a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,13 @@ chrono = "0.4.19" anyhow = "1.0.58" clap = "3.2.8" tokio = { version = "1.28.2" } +web3 = { version = "0.18.0", default-features = false, features = ["http-rustls-tls"] } +serde_json = "1.0.39" +sha3 = "0.10" +sea-orm = { version = "0.11.3", features = ["runtime-tokio-native-tls", "sqlx-postgres"]} +[dependencies.sea-orm-rocket] +version = "0.5.2" [dependencies.rocket_okapi] version = "0.8.0-rc.3" diff --git a/src/config.rs b/src/config.rs index 8bf0966..417d98c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,14 +1,2 @@ -use clap::{Arg, ArgMatches, Command}; -pub async fn get_envs() -> anyhow::Result { - let matches = Command::new("data manager") - .version(option_env!("CARGO_PKG_VERSION").unwrap_or("")) - .about("Simple command line producer") - .arg( - Arg::new("log-conf") - .long("log-conf") - .help("Configure the logging format (example: 'rdkafka=trace')") - .takes_value(true), - ) - .get_matches(); - Ok(matches) -} +pub mod env_config; +pub mod log_config; diff --git a/src/controllers/config.rs b/src/config/env_config.rs similarity index 81% rename from src/controllers/config.rs rename to src/config/env_config.rs index 7c36410..f7f31ff 100644 --- a/src/controllers/config.rs +++ b/src/config/env_config.rs @@ -18,11 +18,17 @@ enum Profiles { DEFAULT, } +#[derive(Deserialize, Serialize)] +pub struct Database { + pub url: String, +} + #[derive(Deserialize, Serialize)] pub struct Config { port: i32, profile: Profiles, address: String, + pub database: Database, } impl Default for Config { @@ -31,6 +37,9 @@ impl Default for Config { port: Config::get_port(constants::PORT), profile: Profiles::DEFAULT, address: "0.0.0.0".to_string(), + database: Database { + url: Config::get_database_url(constants::URL_POSTGRES_CONNECTION_NAME), + }, } } } @@ -51,6 +60,9 @@ impl Config { port: Config::get_port(constants::DEV_PORT), profile: Profiles::DEV, address: "0.0.0.0".to_string(), + database: Database { + url: Config::get_database_url(constants::DEV_URL_POSTGRES_CONNECTION_NAME), + }, } } @@ -59,6 +71,9 @@ impl Config { port: Config::get_port(constants::PROD_PORT), profile: Profiles::PROD, address: "0.0.0.0".to_string(), + database: Database { + url: Config::get_database_url(constants::PROD_URL_POSTGRES_CONNECTION_NAME), + }, } } @@ -106,4 +121,7 @@ impl Config { Err(_) => 3025, } } + fn get_database_url(name: &'static str) -> String { + Utils::get_env(name) + } } diff --git a/src/config/log_config.rs b/src/config/log_config.rs new file mode 100644 index 0000000..8bf0966 --- /dev/null +++ b/src/config/log_config.rs @@ -0,0 +1,14 @@ +use clap::{Arg, ArgMatches, Command}; +pub async fn get_envs() -> anyhow::Result { + let matches = Command::new("data manager") + .version(option_env!("CARGO_PKG_VERSION").unwrap_or("")) + .about("Simple command line producer") + .arg( + Arg::new("log-conf") + .long("log-conf") + .help("Configure the logging format (example: 'rdkafka=trace')") + .takes_value(true), + ) + .get_matches(); + Ok(matches) +} diff --git a/src/controllers.rs b/src/controllers.rs index 097dbcb..9bd2c76 100644 --- a/src/controllers.rs +++ b/src/controllers.rs @@ -1,3 +1,2 @@ pub mod certificate_controller; -pub mod config; pub mod index; diff --git a/src/controllers/index.rs b/src/controllers/index.rs index f184aa1..512d2e6 100644 --- a/src/controllers/index.rs +++ b/src/controllers/index.rs @@ -8,7 +8,7 @@ use rocket_okapi::settings::{OpenApiSettings, UrlObject}; use rocket_okapi::swagger_ui::{make_swagger_ui, SwaggerUIConfig}; use rocket_okapi::{mount_endpoints_and_merged_docs, openapi_get_routes_spec}; -use crate::controllers::config::Config; +use crate::config::env_config::Config; pub fn stage() -> AdHoc { AdHoc::on_ignite("SQLx Stage", |_rocket_instance| async { diff --git a/src/databases.rs b/src/databases.rs new file mode 100644 index 0000000..c9e2bb1 --- /dev/null +++ b/src/databases.rs @@ -0,0 +1 @@ +pub mod pool; diff --git a/src/databases/pool.rs b/src/databases/pool.rs new file mode 100644 index 0000000..e079271 --- /dev/null +++ b/src/databases/pool.rs @@ -0,0 +1,39 @@ +use async_trait::async_trait; +use sea_orm::ConnectOptions; +use sea_orm_rocket::{rocket::figment::Figment, Config, Database}; +use std::time::Duration; + +#[derive(Database, Debug)] +#[database("trustlist")] +pub struct Db(SeaOrmPool); + +#[derive(Debug, Clone)] +pub struct SeaOrmPool { + pub conn: sea_orm::DatabaseConnection, +} + +#[async_trait] +impl sea_orm_rocket::Pool for SeaOrmPool { + type Error = sea_orm::DbErr; + + type Connection = sea_orm::DatabaseConnection; + + async fn init(figment: &Figment) -> Result { + let config = figment.extract::().unwrap(); + let mut options: ConnectOptions = config.url.into(); + options + .max_connections(config.max_connections as u32) + .min_connections(config.min_connections.unwrap_or_default()) + .connect_timeout(Duration::from_secs(config.connect_timeout)); + if let Some(idle_timeout) = config.idle_timeout { + options.idle_timeout(Duration::from_secs(idle_timeout)); + } + let conn = sea_orm::Database::connect(options).await?; + + Ok(SeaOrmPool { conn }) + } + + fn borrow(&self) -> &Self::Connection { + &self.conn + } +} diff --git a/src/jobs/index.rs b/src/jobs/index.rs index 5c5b1b2..c8133b1 100644 --- a/src/jobs/index.rs +++ b/src/jobs/index.rs @@ -16,11 +16,26 @@ impl JobManager { tokio::spawn(async move { thread::sleep(Duration::from_secs(r.start_up)); loop { - r.sweep(); - thread::sleep(Duration::from_secs(r.period_seconds)) + match r.sweep().await { + Ok(_) => { + info!( + "Sucessful update, next update will take place in {:?} seconds ...", + r.period_seconds + ); + thread::sleep(Duration::from_secs(r.period_seconds)); + } + Err(_e) => { + error!( + "Failed sweep: {:?} ... retrying in {:?} seconds ...", + r, r.retry_period + ); + thread::sleep(Duration::from_secs(r.retry_period)); + } + } } }) }) + //.map(|th| async { th.await.unwrap() }) .collect::>(); } } diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs index 47b2ec9..2119f4e 100644 --- a/src/jobs/trusted_registries.rs +++ b/src/jobs/trusted_registries.rs @@ -37,6 +37,7 @@ impl TrustedRegistries { chain_id: 0x9e55c, contract_address: "0xEBB6854aa875867f684dd1d2338eC20908039c67".to_owned(), }, + retry_period: 0, }; let mut trs: Vec = Vec::new(); trs.push(t1); @@ -50,6 +51,7 @@ impl TrustedRegistries { .map(|i| { self.registries[i].start_up = (i as u64) * 100; self.registries[i].period_seconds = 2000; + self.registries[i].retry_period = 30; }) .collect::>(); } diff --git a/src/jobs/trusted_registry.rs b/src/jobs/trusted_registry.rs index 1d3b5f5..8bbc580 100644 --- a/src/jobs/trusted_registry.rs +++ b/src/jobs/trusted_registry.rs @@ -1,5 +1,9 @@ +use log::info; +use sea_orm::Database; use serde::{Deserialize, Serialize}; +use crate::config::env_config::Config; + #[derive(Deserialize, Serialize, Debug)] pub struct Contract { pub chain_id: i32, @@ -12,14 +16,31 @@ pub struct TrustedRegistry { pub chain_of_trust: Contract, pub period_seconds: u64, pub start_up: u64, + pub retry_period: u64, } impl TrustedRegistry { - pub fn sweep(&self) { + pub async fn sweep(&self) -> anyhow::Result<()> { info!( "Sweeping trusted registry ... {:?} {:?}", self.public_directory, self.chain_of_trust ); + info!("Connection is {}", Config::get_config().database.url); + match Database::connect(Config::get_config().database.url).await { + Ok(_c) => { + info!("Successfully connected a database connection"); + Ok(()) + } + Err(e) => { + let message = format!("There was an error connecting to the database: {:?}", e); + error!("{}", &message); + Err(e.into()) + // panic!("{}", message) + } + } + // read from database the last block saved for public directory configured smart contract + // let s = Config::get_config(); + // let _p = Database::connect(s.); // read public directory last changes // read chain of trust last changes // read did registry changes diff --git a/src/main.rs b/src/main.rs index fa08329..f03320f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod config; pub mod controllers; +pub mod databases; pub mod dto; pub mod jobs; mod logger_config; @@ -13,7 +14,7 @@ extern crate rocket; use controllers::index::stage; use jobs::index::JobManager; -use crate::config::get_envs; +use crate::config::log_config::get_envs; use crate::logger_config::setup_logger; #[launch] @@ -22,6 +23,8 @@ async fn rocket() -> _ { setup_logger(true, envs.value_of("log-conf")); tokio::spawn(async move { JobManager::sweep_trusted_registries(); - }); + }) + .await + .unwrap(); rocket::build().attach(stage()) } From 10d262ee4c306d9889b6958a105301ce74090685 Mon Sep 17 00:00:00 2001 From: eum602 Date: Sat, 17 Jun 2023 11:38:09 -0500 Subject: [PATCH 05/25] chore: add database connection for web server --- example.env.dev.sh | 7 ++++--- src/config/env_config.rs | 26 ++++++++++++++++++-------- src/controllers/index.rs | 3 +++ src/databases/pool.rs | 2 +- src/jobs/trusted_registry.rs | 3 +-- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/example.env.dev.sh b/example.env.dev.sh index 212f26f..9668e82 100755 --- a/example.env.dev.sh +++ b/example.env.dev.sh @@ -1,12 +1,12 @@ #PORT -export PORT=80 # use port 80 when running with docker +export PORT=8000 # use port 80 when running with docker export EXPOSED_CONTAINER_SERVER_PORT=3025 #TYPEORM export TYPEORM_TYPE=postgres -export TYPEORM_HOST=127.0.0.1 +export TYPEORM_HOST=localhost export TYPEORM_USERNAME=postgres export TYPEORM_PASSWORD=postgres export TYPEORM_DATABASE=lacpass_trusted_list_development @@ -34,4 +34,5 @@ export RATE_LIMIT_WINDOW=5 export RATE_LIMIT_MAX_REQUESTS=100 # custom variables -export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" +export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" +export DATABASE_URL="postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${EXPOSED_CONTAINER_TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection diff --git a/src/config/env_config.rs b/src/config/env_config.rs index f7f31ff..30a1fdb 100644 --- a/src/config/env_config.rs +++ b/src/config/env_config.rs @@ -19,16 +19,20 @@ enum Profiles { } #[derive(Deserialize, Serialize)] -pub struct Database { +pub struct D { pub url: String, } +#[derive(Deserialize, Serialize)] +pub struct Databases { + pub dbconnection: D, +} #[derive(Deserialize, Serialize)] pub struct Config { port: i32, profile: Profiles, address: String, - pub database: Database, + pub databases: Databases, } impl Default for Config { @@ -37,8 +41,10 @@ impl Default for Config { port: Config::get_port(constants::PORT), profile: Profiles::DEFAULT, address: "0.0.0.0".to_string(), - database: Database { - url: Config::get_database_url(constants::URL_POSTGRES_CONNECTION_NAME), + databases: Databases { + dbconnection: D { + url: Config::get_database_url(constants::URL_POSTGRES_CONNECTION_NAME), + }, }, } } @@ -60,8 +66,10 @@ impl Config { port: Config::get_port(constants::DEV_PORT), profile: Profiles::DEV, address: "0.0.0.0".to_string(), - database: Database { - url: Config::get_database_url(constants::DEV_URL_POSTGRES_CONNECTION_NAME), + databases: Databases { + dbconnection: D { + url: Config::get_database_url(constants::DEV_URL_POSTGRES_CONNECTION_NAME), + }, }, } } @@ -71,8 +79,10 @@ impl Config { port: Config::get_port(constants::PROD_PORT), profile: Profiles::PROD, address: "0.0.0.0".to_string(), - database: Database { - url: Config::get_database_url(constants::PROD_URL_POSTGRES_CONNECTION_NAME), + databases: Databases { + dbconnection: D { + url: Config::get_database_url(constants::PROD_URL_POSTGRES_CONNECTION_NAME), + }, }, } } diff --git a/src/controllers/index.rs b/src/controllers/index.rs index 512d2e6..4aaae92 100644 --- a/src/controllers/index.rs +++ b/src/controllers/index.rs @@ -7,13 +7,16 @@ use rocket_okapi::rapidoc::{make_rapidoc, GeneralConfig, HideShowConfig, RapiDoc use rocket_okapi::settings::{OpenApiSettings, UrlObject}; use rocket_okapi::swagger_ui::{make_swagger_ui, SwaggerUIConfig}; use rocket_okapi::{mount_endpoints_and_merged_docs, openapi_get_routes_spec}; +use sea_orm_rocket::Database; use crate::config::env_config::Config; +use crate::databases::pool::Db; pub fn stage() -> AdHoc { AdHoc::on_ignite("SQLx Stage", |_rocket_instance| async { let figment = Config::figment(); let mut building_rocket = rocket::custom(figment) + .attach(Db::init()) .mount( "/swagger-ui/", make_swagger_ui(&SwaggerUIConfig { diff --git a/src/databases/pool.rs b/src/databases/pool.rs index e079271..104a438 100644 --- a/src/databases/pool.rs +++ b/src/databases/pool.rs @@ -4,7 +4,7 @@ use sea_orm_rocket::{rocket::figment::Figment, Config, Database}; use std::time::Duration; #[derive(Database, Debug)] -#[database("trustlist")] +#[database("dbconnection")] pub struct Db(SeaOrmPool); #[derive(Debug, Clone)] diff --git a/src/jobs/trusted_registry.rs b/src/jobs/trusted_registry.rs index 8bbc580..1955e49 100644 --- a/src/jobs/trusted_registry.rs +++ b/src/jobs/trusted_registry.rs @@ -25,8 +25,7 @@ impl TrustedRegistry { "Sweeping trusted registry ... {:?} {:?}", self.public_directory, self.chain_of_trust ); - info!("Connection is {}", Config::get_config().database.url); - match Database::connect(Config::get_config().database.url).await { + match Database::connect(Config::get_config().databases.dbconnection.url).await { Ok(_c) => { info!("Successfully connected a database connection"); Ok(()) From 6d1b7574f17c37fce9575477d25c28f538173723 Mon Sep 17 00:00:00 2001 From: eum602 Date: Sat, 17 Jun 2023 13:49:49 -0500 Subject: [PATCH 06/25] chore: config for running source code directly (no docker embedded) --- example.env.dev.sh => .example.env.dev.sh | 2 +- docker-compose-dbs.yml | 23 +++++++++++++++++++++++ docs/tech/configuration.md | 12 ++++++++++-- src/main.rs | 6 +++--- 4 files changed, 37 insertions(+), 6 deletions(-) rename example.env.dev.sh => .example.env.dev.sh (95%) create mode 100644 docker-compose-dbs.yml diff --git a/example.env.dev.sh b/.example.env.dev.sh similarity index 95% rename from example.env.dev.sh rename to .example.env.dev.sh index 9668e82..a92e8ae 100755 --- a/example.env.dev.sh +++ b/.example.env.dev.sh @@ -1,6 +1,6 @@ #PORT -export PORT=8000 # use port 80 when running with docker +export PORT=3025 # use port 80 when running with docker export EXPOSED_CONTAINER_SERVER_PORT=3025 #TYPEORM diff --git a/docker-compose-dbs.yml b/docker-compose-dbs.yml new file mode 100644 index 0000000..4f1cc7c --- /dev/null +++ b/docker-compose-dbs.yml @@ -0,0 +1,23 @@ +version: "3" +services: + postgres: + image: postgres:latest + ports: + - "${EXPOSED_CONTAINER_TYPEORM_PORT}:${TYPEORM_PORT}" + environment: + POSTGRES_PASSWORD: ${TYPEORM_PASSWORD} + volumes: + - ./docker_postgres_init.sql:/docker-entrypoint-initdb.d/docker_postgres_init.sql + networks: + - backend + redis: + image: redis:latest + command: redis-server --requirepass ${REDIS_PASSWORD} + ports: + - "${EXPOSED_CONTAINER_REDIS_PORT}:${REDIS_PORT}" + networks: + - backend +networks: + backend: + name: backend + external: true diff --git a/docs/tech/configuration.md b/docs/tech/configuration.md index 74cea2f..54be30b 100644 --- a/docs/tech/configuration.md +++ b/docs/tech/configuration.md @@ -20,10 +20,18 @@ In order to run the app with Docker, you should install or update to the latest ## Running directly +- Prepare databases + +```sh +docker-compose -f docker-compose-dbs.yml --env-file .env.dev up +``` + +- Prepare environment variables and run + ```sh -cp example.env.dev.sh .env.dev.sh +cp .example.env.dev.sh .env.dev.sh chmod +x .env.dev.sh -./.env.dev.sh +. ./.env.dev.sh RUST_LOG="debug,tower_http=trace" cargo run # RUST_LOG="debug,tower_http=trace" cargo watch -x run (if you have "watch" installed) ``` diff --git a/src/main.rs b/src/main.rs index f03320f..1cbcf2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,10 @@ mod config; pub mod controllers; pub mod databases; pub mod dto; +pub mod entities; pub mod jobs; mod logger_config; +pub mod migration; pub mod responses; pub mod services; pub mod utils; @@ -23,8 +25,6 @@ async fn rocket() -> _ { setup_logger(true, envs.value_of("log-conf")); tokio::spawn(async move { JobManager::sweep_trusted_registries(); - }) - .await - .unwrap(); + }); rocket::build().attach(stage()) } From 4a136f1ad8986037bd2ceb345f03d8adb07ad36a Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 19 Jun 2023 10:29:24 -0500 Subject: [PATCH 07/25] chore: add migration dependency and public-directory migration files --- Cargo.lock | 72 +++++++++++++++++++ Cargo.toml | 10 +++ docs/tech/configuration.md | 4 ++ docs/tech/migrations.md | 67 +++++++++++++++++ src/controllers/index.rs | 3 +- src/migration.rs | 2 + src/migration/index.rs | 19 +++++ .../m20230617_195505_public_directory.rs | 51 +++++++++++++ 8 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 docs/tech/migrations.md create mode 100644 src/migration.rs create mode 100644 src/migration/index.rs create mode 100644 src/migration/m20230617_195505_public_directory.rs diff --git a/Cargo.lock b/Cargo.lock index b3f3b36..aabec4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -373,13 +373,28 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags 1.3.2", + "clap_derive", "clap_lex", "indexmap", + "once_cell", "strsim", "termcolor", "textwrap", ] +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck 0.4.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -1374,6 +1389,7 @@ dependencies = [ "rocket_cors", "rocket_okapi", "sea-orm", + "sea-orm-migration", "sea-orm-rocket", "serde", "serde_json", @@ -2482,6 +2498,22 @@ dependencies = [ "uuid", ] +[[package]] +name = "sea-orm-cli" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbf34a2caf70c2e3be9bb1e674e9540f6dfd7c8f40f6f05daf3b9740e476005" +dependencies = [ + "chrono", + "clap", + "dotenvy", + "regex", + "sea-schema", + "tracing", + "tracing-subscriber", + "url", +] + [[package]] name = "sea-orm-macros" version = "0.11.3" @@ -2495,6 +2527,23 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "sea-orm-migration" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278d3adfd0832b6ffc17d3cfbc574d3695a5c1b38814e0bc8ac238d33f3d87cf" +dependencies = [ + "async-trait", + "clap", + "dotenvy", + "futures", + "sea-orm", + "sea-orm-cli", + "sea-schema", + "tracing", + "tracing-subscriber", +] + [[package]] name = "sea-orm-rocket" version = "0.5.2" @@ -2559,6 +2608,29 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sea-schema" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeb2940bb5a10bc6cd05b450ce6cd3993e27fddd7eface2becb97fc5af3a040e" +dependencies = [ + "futures", + "sea-query", + "sea-schema-derive", +] + +[[package]] +name = "sea-schema-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "sea-strum" version = "0.23.0" diff --git a/Cargo.toml b/Cargo.toml index b0a13a4..b2e03c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,16 @@ sea-orm = { version = "0.11.3", features = ["runtime-tokio-native-tls", "sqlx-po [dependencies.sea-orm-rocket] version = "0.5.2" +[dependencies.sea-orm-migration] +version = "0.11.3" +features = [ + # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. + # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. + # e.g. + #"runtime-tokio-rustls", # `ASYNC_RUNTIME` feature + #"sqlx-postgres", # `DATABASE_DRIVER` feature +] + [dependencies.rocket_okapi] version = "0.8.0-rc.3" features = ["swagger", "rapidoc"] diff --git a/docs/tech/configuration.md b/docs/tech/configuration.md index 54be30b..544c084 100644 --- a/docs/tech/configuration.md +++ b/docs/tech/configuration.md @@ -104,3 +104,7 @@ After running the server you will find OpenAPI Specification here: `http:// AdHoc { AdHoc::on_ignite("SQLx Stage", |_rocket_instance| async { let figment = Config::figment(); let mut building_rocket = rocket::custom(figment) .attach(Db::init()) + .attach(AdHoc::try_on_ignite("Migrations", run_migrations)) .mount( "/swagger-ui/", make_swagger_ui(&SwaggerUIConfig { @@ -45,7 +47,6 @@ pub fn stage() -> AdHoc { // let custom_route_spec = (vec![], custom_openapi_spec()); mount_endpoints_and_merged_docs! { building_rocket, "/api/v1".to_owned(), openapi_settings, - // "" => custom_route_spec, "/certificates" => get_routes_and_docs(&openapi_settings) }; building_rocket diff --git a/src/migration.rs b/src/migration.rs new file mode 100644 index 0000000..eab0348 --- /dev/null +++ b/src/migration.rs @@ -0,0 +1,2 @@ +pub mod index; +pub mod m20230617_195505_public_directory; diff --git a/src/migration/index.rs b/src/migration/index.rs new file mode 100644 index 0000000..ca55a6b --- /dev/null +++ b/src/migration/index.rs @@ -0,0 +1,19 @@ +use rocket::{fairing, Build, Rocket}; +pub use sea_orm_migration::prelude::*; +use sea_orm_rocket::Database; + +use crate::{databases::pool::Db, migration::m20230617_195505_public_directory}; +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20230617_195505_public_directory::Migration)] + } +} + +pub async fn run_migrations(rocket: Rocket) -> fairing::Result { + let conn = &Db::fetch(&rocket).unwrap().conn; + let _ = Migrator::up(conn, None).await; + Ok(rocket) +} diff --git a/src/migration/m20230617_195505_public_directory.rs b/src/migration/m20230617_195505_public_directory.rs new file mode 100644 index 0000000..6f6201c --- /dev/null +++ b/src/migration/m20230617_195505_public_directory.rs @@ -0,0 +1,51 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(PublicDirectory::Table) + .if_not_exists() + .col( + ColumnDef::new(PublicDirectory::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(PublicDirectory::ContractAddress) + .string() + .not_null() + .unique_key(), + ) + .col( + ColumnDef::new(PublicDirectory::LastBlockSaved) + .big_integer() + .not_null(), + ) + .col(ColumnDef::new(PublicDirectory::ChainId).string().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(PublicDirectory::Table).to_owned()) + .await + } +} + +#[derive(Iden)] +enum PublicDirectory { + Table, + Id, + ContractAddress, + LastBlockSaved, + ChainId, +} From 5913697bb43d5d1b50c78eb0dd499b7776923789 Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 19 Jun 2023 10:32:26 -0500 Subject: [PATCH 08/25] chore: add public directory entity --- src/entities.rs | 3 +++ src/entities/entities.rs | 1 + src/entities/models.rs | 1 + src/entities/public_directory.rs | 2 ++ src/entities/public_directory/model.rs | 20 ++++++++++++++++++++ src/entities/public_directory/select.rs | 13 +++++++++++++ 6 files changed, 40 insertions(+) create mode 100644 src/entities.rs create mode 100644 src/entities/entities.rs create mode 100644 src/entities/models.rs create mode 100644 src/entities/public_directory.rs create mode 100644 src/entities/public_directory/model.rs create mode 100644 src/entities/public_directory/select.rs diff --git a/src/entities.rs b/src/entities.rs new file mode 100644 index 0000000..e97103d --- /dev/null +++ b/src/entities.rs @@ -0,0 +1,3 @@ +pub mod entities; +pub mod models; +pub mod public_directory; diff --git a/src/entities/entities.rs b/src/entities/entities.rs new file mode 100644 index 0000000..6afd78e --- /dev/null +++ b/src/entities/entities.rs @@ -0,0 +1 @@ +pub use crate::entities::public_directory::model::Entity as PublicDirectoryEntity; diff --git a/src/entities/models.rs b/src/entities/models.rs new file mode 100644 index 0000000..98434d5 --- /dev/null +++ b/src/entities/models.rs @@ -0,0 +1 @@ +pub use crate::entities::public_directory::model::Model as PublicDirectoryModel; diff --git a/src/entities/public_directory.rs b/src/entities/public_directory.rs new file mode 100644 index 0000000..46698dd --- /dev/null +++ b/src/entities/public_directory.rs @@ -0,0 +1,2 @@ +pub mod model; +pub mod select; diff --git a/src/entities/public_directory/model.rs b/src/entities/public_directory/model.rs new file mode 100644 index 0000000..f6ef276 --- /dev/null +++ b/src/entities/public_directory/model.rs @@ -0,0 +1,20 @@ +use rocket::serde::{Deserialize, Serialize}; +use sea_orm::entity::prelude::*; +use uuid::Uuid; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] +#[serde(crate = "rocket::serde")] +#[sea_orm(table_name = "public_directory")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + #[sea_orm(column_type = "Text")] + pub contract_address: String, + pub last_block_saved: i64, + pub chain_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entities/public_directory/select.rs b/src/entities/public_directory/select.rs new file mode 100644 index 0000000..2fbd37e --- /dev/null +++ b/src/entities/public_directory/select.rs @@ -0,0 +1,13 @@ +use super::*; +use crate::entities::entities::PublicDirectoryEntity; +use sea_orm::{entity::*, query::*}; + +impl PublicDirectoryEntity { + pub fn find_by_contract_address(contract_address: &str, chain_id: &str) -> Select { + Self::find().filter( + model::Column::ContractAddress + .contains(contract_address) + .and(model::Column::ChainId.contains(chain_id)), + ) + } +} From 2161a18419dc691ade45f54fcd7cb68051b985c9 Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 19 Jun 2023 10:37:23 -0500 Subject: [PATCH 09/25] chore: add public-directory entity database connection for trusted registry task --- src/jobs/index.rs | 22 +++++++++++++++------- src/jobs/trusted_registry.rs | 28 ++++++++++++++++++++++++---- src/services.rs | 1 + src/services/public_directory.rs | 17 +++++++++++++++++ 4 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 src/services/public_directory.rs diff --git a/src/jobs/index.rs b/src/jobs/index.rs index c8133b1..d2e2640 100644 --- a/src/jobs/index.rs +++ b/src/jobs/index.rs @@ -1,6 +1,7 @@ use std::{thread, time::Duration}; use log::info; +use yansi::Paint; use crate::jobs::trusted_registries::TrustedRegistries; @@ -18,18 +19,25 @@ impl JobManager { loop { match r.sweep().await { Ok(_) => { - info!( - "Sucessful update, next update will take place in {:?} seconds ...", - r.period_seconds + let message = format!( + "{} {} {} {}", + Paint::masked("🌀"), + Paint::green( + "Sucessful public key update, next update will take place in" + ) + .bold(), + r.period_seconds, + "seconds..." ); - thread::sleep(Duration::from_secs(r.period_seconds)); + info!("{}", message); + tokio::time::sleep(Duration::from_secs(r.period_seconds)).await; } Err(_e) => { + let message = format!("{} {} {}", Paint::masked("❌") ,Paint::red("Failed to sweep, ... retrying in "), r.retry_period); error!( - "Failed sweep: {:?} ... retrying in {:?} seconds ...", - r, r.retry_period + "{}", message ); - thread::sleep(Duration::from_secs(r.retry_period)); + tokio::time::sleep(Duration::from_secs(r.retry_period)).await; } } } diff --git a/src/jobs/trusted_registry.rs b/src/jobs/trusted_registry.rs index 1955e49..797bea9 100644 --- a/src/jobs/trusted_registry.rs +++ b/src/jobs/trusted_registry.rs @@ -2,7 +2,7 @@ use log::info; use sea_orm::Database; use serde::{Deserialize, Serialize}; -use crate::config::env_config::Config; +use crate::{config::env_config::Config, services::public_directory::PublicDirectoryService}; #[derive(Deserialize, Serialize, Debug)] pub struct Contract { @@ -26,15 +26,35 @@ impl TrustedRegistry { self.public_directory, self.chain_of_trust ); match Database::connect(Config::get_config().databases.dbconnection.url).await { - Ok(_c) => { + Ok(c) => { info!("Successfully connected a database connection"); - Ok(()) + match PublicDirectoryService::get_public_directory( + &c, + &self.public_directory.contract_address, + &self.public_directory.chain_id.to_string(), + ) + .await + { + Ok(result) => match result { + Some(v) => { + info!("Last block saved is {:?}", v); + Ok(()) + } + None => { + info!("Nothing was found"); + Ok(()) + } + }, + Err(e) => { + error!("There was an error while trying to retrieve public directory last block saved {:?}", e); + Err(e.into()) + } + } } Err(e) => { let message = format!("There was an error connecting to the database: {:?}", e); error!("{}", &message); Err(e.into()) - // panic!("{}", message) } } // read from database the last block saved for public directory configured smart contract diff --git a/src/services.rs b/src/services.rs index 55a846a..71b6d43 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1 +1,2 @@ pub mod certificate_service; +pub mod public_directory; diff --git a/src/services/public_directory.rs b/src/services/public_directory.rs new file mode 100644 index 0000000..be400e6 --- /dev/null +++ b/src/services/public_directory.rs @@ -0,0 +1,17 @@ +use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::models::PublicDirectoryModel; +use sea_orm::DatabaseConnection; + +pub struct PublicDirectoryService {} + +impl PublicDirectoryService { + pub async fn get_public_directory( + db: &DatabaseConnection, + public_directory_address: &str, + chain_id: &str, + ) -> Result, sea_orm::DbErr> { + PublicDirectoryEntity::find_by_contract_address(public_directory_address, chain_id) + .one(db) + .await + } +} From 0fe63da42c817a0c2ab050cb73d1f3bc17e0d3bb Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 19 Jun 2023 20:01:16 -0500 Subject: [PATCH 10/25] refactor: trusted registry --- Cargo.lock | 1 + Cargo.toml | 1 + src/jobs.rs | 1 - src/jobs/index.rs | 1 - src/jobs/trusted_registries.rs | 23 +++++-- src/jobs/trusted_registry.rs | 67 ------------------- src/services.rs | 1 + src/services/trusted_registry.rs | 1 + .../trusted_registry/trusted_registry.rs | 64 ++++++++++++++++++ 9 files changed, 84 insertions(+), 76 deletions(-) delete mode 100644 src/jobs/trusted_registry.rs create mode 100644 src/services/trusted_registry.rs create mode 100644 src/services/trusted_registry/trusted_registry.rs diff --git a/Cargo.lock b/Cargo.lock index aabec4d..80ff0f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1383,6 +1383,7 @@ dependencies = [ "clap", "env_logger", "figment", + "hex", "indexmap", "log", "rocket", diff --git a/Cargo.toml b/Cargo.toml index b2e03c9..54ef67c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ web3 = { version = "0.18.0", default-features = false, features = ["http-rustls- serde_json = "1.0.39" sha3 = "0.10" sea-orm = { version = "0.11.3", features = ["runtime-tokio-native-tls", "sqlx-postgres"]} +hex = "0.4" [dependencies.sea-orm-rocket] version = "0.5.2" diff --git a/src/jobs.rs b/src/jobs.rs index a081b87..06e25a4 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -1,3 +1,2 @@ pub mod index; pub mod trusted_registries; -pub mod trusted_registry; diff --git a/src/jobs/index.rs b/src/jobs/index.rs index d2e2640..8a5b82a 100644 --- a/src/jobs/index.rs +++ b/src/jobs/index.rs @@ -43,7 +43,6 @@ impl JobManager { } }) }) - //.map(|th| async { th.await.unwrap() }) .collect::>(); } } diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs index 2119f4e..c0d1f1f 100644 --- a/src/jobs/trusted_registries.rs +++ b/src/jobs/trusted_registries.rs @@ -1,7 +1,10 @@ -use crate::utils::utils::Utils; +use crate::{ + services::trusted_registry::trusted_registry::{Contract, TrustedRegistry}, + utils::utils::Utils, +}; +use hex::FromHex; use serde::{Deserialize, Serialize}; - -use super::trusted_registry::{Contract, TrustedRegistry}; +use web3::types::H160; #[derive(Deserialize, Serialize)] pub struct TrustedRegistries { @@ -26,16 +29,22 @@ impl TrustedRegistries { fn set_trusted_registries(&mut self) -> () { let _raw_trusted_registries = self.get_trusted_registries(); + let pd_str = "fee5C6939309a9906e292753B1947c8De1FD4423"; // "e647e8e076cffA10425c0C49aAaC1036a3b2ddB5"; // TODO: factor better error + let public_directory_address = + <[u8; 20]>::from_hex(pd_str).expect("Invalid public directory contract address"); + let cot_str = "EBB6854aa875867f684dd1d2338eC20908039c67"; + let cot_address = + <[u8; 20]>::from_hex(cot_str).expect("Invalid chain of trust contract address"); let t1 = TrustedRegistry { period_seconds: 400, start_up: 5, public_directory: Contract { - chain_id: 0x9e55c, - contract_address: "0x4A1bD1198890af301AF9b6F3a3a11952a86C1c8e".to_owned(), + chain_id: "0x9e55c".to_owned(), + contract_address: H160(public_directory_address), }, chain_of_trust: Contract { - chain_id: 0x9e55c, - contract_address: "0xEBB6854aa875867f684dd1d2338eC20908039c67".to_owned(), + chain_id: "0x9e55c".to_owned(), + contract_address: H160(cot_address), }, retry_period: 0, }; diff --git a/src/jobs/trusted_registry.rs b/src/jobs/trusted_registry.rs deleted file mode 100644 index 797bea9..0000000 --- a/src/jobs/trusted_registry.rs +++ /dev/null @@ -1,67 +0,0 @@ -use log::info; -use sea_orm::Database; -use serde::{Deserialize, Serialize}; - -use crate::{config::env_config::Config, services::public_directory::PublicDirectoryService}; - -#[derive(Deserialize, Serialize, Debug)] -pub struct Contract { - pub chain_id: i32, - pub contract_address: String, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct TrustedRegistry { - pub public_directory: Contract, - pub chain_of_trust: Contract, - pub period_seconds: u64, - pub start_up: u64, - pub retry_period: u64, -} - -impl TrustedRegistry { - pub async fn sweep(&self) -> anyhow::Result<()> { - info!( - "Sweeping trusted registry ... {:?} {:?}", - self.public_directory, self.chain_of_trust - ); - match Database::connect(Config::get_config().databases.dbconnection.url).await { - Ok(c) => { - info!("Successfully connected a database connection"); - match PublicDirectoryService::get_public_directory( - &c, - &self.public_directory.contract_address, - &self.public_directory.chain_id.to_string(), - ) - .await - { - Ok(result) => match result { - Some(v) => { - info!("Last block saved is {:?}", v); - Ok(()) - } - None => { - info!("Nothing was found"); - Ok(()) - } - }, - Err(e) => { - error!("There was an error while trying to retrieve public directory last block saved {:?}", e); - Err(e.into()) - } - } - } - Err(e) => { - let message = format!("There was an error connecting to the database: {:?}", e); - error!("{}", &message); - Err(e.into()) - } - } - // read from database the last block saved for public directory configured smart contract - // let s = Config::get_config(); - // let _p = Database::connect(s.); - // read public directory last changes - // read chain of trust last changes - // read did registry changes - } -} diff --git a/src/services.rs b/src/services.rs index 71b6d43..b727286 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1,2 +1,3 @@ pub mod certificate_service; pub mod public_directory; +pub mod trusted_registry; diff --git a/src/services/trusted_registry.rs b/src/services/trusted_registry.rs new file mode 100644 index 0000000..b1fddfb --- /dev/null +++ b/src/services/trusted_registry.rs @@ -0,0 +1 @@ +pub mod trusted_registry; diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs new file mode 100644 index 0000000..1b7e8ec --- /dev/null +++ b/src/services/trusted_registry/trusted_registry.rs @@ -0,0 +1,64 @@ +use log::info; +use sea_orm::Database; +use serde::{Deserialize, Serialize}; +use web3::types::H160; + +use crate::{ + config::env_config::Config, services::public_directory::index::PublicDirectoryService, +}; + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct Contract { + pub chain_id: String, + pub contract_address: H160, +} + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct TrustedRegistry { + pub public_directory: Contract, + pub chain_of_trust: Contract, + pub period_seconds: u64, + pub start_up: u64, + pub retry_period: u64, +} + +impl TrustedRegistry { + pub async fn sweep(&self) -> anyhow::Result<()> { + info!( + "Sweeping trusted registry ... {:?} {:?}", + self.public_directory, self.chain_of_trust + ); + match Database::connect(Config::get_config().databases.dbconnection.url).await { + Ok(c) => { + info!("Successfully connected a database connection"); + let public_directory_service_instance: PublicDirectoryService; + match PublicDirectoryService::new(self.public_directory.clone()).await { + Ok(result) => { + public_directory_service_instance = result; + } + Err(e) => { + return Err(e); + } + } + let mut _last_block_saved = 0; + match public_directory_service_instance.sweep(&c).await { + Ok(_) => { + // sweep chain of trust + // read did registry changes + } + Err(e) => { + error!("There was an error while trying to retrieve public directory last block saved {:?}", e); + return Err(e.into()); + } + } + // sweep to get members in the public directory and for each save it to the database + Ok(()) + } + Err(e) => { + let message = format!("There was an error connecting to the database: {:?}", e); + error!("{}", &message); + Err(e.into()) + } + } + } +} From 688785dbe510e9f5b0c9a73b97a6e3c6acfc74b1 Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 19 Jun 2023 21:22:02 -0500 Subject: [PATCH 11/25] feat: add public directory getter for last block --- .example.env | 1 + .example.env.dev | 1 + .example.env.dev.sh | 3 +- docker-compose-dev.yml | 1 + docker-compose.yml | 1 + src/config/env_config.rs | 18 +- src/jobs/trusted_registries.rs | 4 +- src/services/public_directory.rs | 20 +- src/services/public_directory/abi.json | 522 ++++++++++++++++++ .../public_directory/contract_interface.rs | 31 ++ .../public_directory/data_interface.rs | 37 ++ src/services/public_directory/index.rs | 65 +++ 12 files changed, 679 insertions(+), 25 deletions(-) create mode 100644 src/services/public_directory/abi.json create mode 100644 src/services/public_directory/contract_interface.rs create mode 100644 src/services/public_directory/data_interface.rs create mode 100644 src/services/public_directory/index.rs diff --git a/.example.env b/.example.env index bfb1448..a24d2aa 100644 --- a/.example.env +++ b/.example.env @@ -36,3 +36,4 @@ RATE_LIMIT_MAX_REQUESTS = 100 # custom variables export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" +export RPC_CONNECTION_648540="http://35.185.112.219" \ No newline at end of file diff --git a/.example.env.dev b/.example.env.dev index 1a5981a..25505dd 100644 --- a/.example.env.dev +++ b/.example.env.dev @@ -35,3 +35,4 @@ RATE_LIMIT_MAX_REQUESTS = 100 # custom variables export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" +export RPC_CONNECTION_648540="http://35.185.112.219" \ No newline at end of file diff --git a/.example.env.dev.sh b/.example.env.dev.sh index a92e8ae..aea1804 100755 --- a/.example.env.dev.sh +++ b/.example.env.dev.sh @@ -34,5 +34,6 @@ export RATE_LIMIT_WINDOW=5 export RATE_LIMIT_MAX_REQUESTS=100 # custom variables -export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" +export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,648540-0xEBB6854aa875867f684dd1d2338eC20908039c67,648540" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" export DATABASE_URL="postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${EXPOSED_CONTAINER_TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection +export RPC_CONNECTION_648540="http://35.185.112.219" diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 880bba2..c5501cc 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -37,6 +37,7 @@ services: RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" + RPC_CONNECTION_648540: "${RPC_CONNECTION_648540}" DATABASE_URL: "postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" diff --git a/docker-compose.yml b/docker-compose.yml index 0ae880f..7424da5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,7 @@ services: RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" + RPC_CONNECTION_648540: "${RPC_CONNECTION_648540}" DATABASE_URL: "postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" diff --git a/src/config/env_config.rs b/src/config/env_config.rs index 30a1fdb..20a7479 100644 --- a/src/config/env_config.rs +++ b/src/config/env_config.rs @@ -38,7 +38,7 @@ pub struct Config { impl Default for Config { fn default() -> Config { Config { - port: Config::get_port(constants::PORT), + port: Config::get_port(constants::PORT.to_owned()), profile: Profiles::DEFAULT, address: "0.0.0.0".to_string(), databases: Databases { @@ -63,7 +63,7 @@ impl Provider for Config { impl Config { fn development() -> Config { Config { - port: Config::get_port(constants::DEV_PORT), + port: Config::get_port(constants::DEV_PORT.to_owned()), profile: Profiles::DEV, address: "0.0.0.0".to_string(), databases: Databases { @@ -76,7 +76,7 @@ impl Config { fn production() -> Config { Config { - port: Config::get_port(constants::PROD_PORT), + port: Config::get_port(constants::PROD_PORT.to_owned()), profile: Profiles::PROD, address: "0.0.0.0".to_string(), databases: Databases { @@ -125,8 +125,8 @@ impl Config { info!("Using profile {:?}", Paint::blue(self.profile).bold()); } - fn get_port(name: &'static str) -> i32 { - match Utils::get_env_or_err(name) { + fn get_port(name: String) -> i32 { + match Utils::get_env_or_err(&name) { Ok(s) => Utils::i32_from_string(s), Err(_) => 3025, } @@ -134,4 +134,12 @@ impl Config { fn get_database_url(name: &'static str) -> String { Utils::get_env(name) } + pub fn get_provider(chain_id: String) -> String { + let mut key = "RPC_CONNECTION_".to_owned(); + key.push_str(&chain_id); + match Utils::get_env_or_err(&key) { + Ok(s) => s, // TODO: Validate is a valid http connection string + Err(e) => panic!("{}", e), + } + } } diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs index c0d1f1f..d24321a 100644 --- a/src/jobs/trusted_registries.rs +++ b/src/jobs/trusted_registries.rs @@ -39,11 +39,11 @@ impl TrustedRegistries { period_seconds: 400, start_up: 5, public_directory: Contract { - chain_id: "0x9e55c".to_owned(), + chain_id: "648540".to_owned(), contract_address: H160(public_directory_address), }, chain_of_trust: Contract { - chain_id: "0x9e55c".to_owned(), + chain_id: "648540".to_owned(), contract_address: H160(cot_address), }, retry_period: 0, diff --git a/src/services/public_directory.rs b/src/services/public_directory.rs index be400e6..a136cd0 100644 --- a/src/services/public_directory.rs +++ b/src/services/public_directory.rs @@ -1,17 +1,3 @@ -use crate::entities::entities::PublicDirectoryEntity; -use crate::entities::models::PublicDirectoryModel; -use sea_orm::DatabaseConnection; - -pub struct PublicDirectoryService {} - -impl PublicDirectoryService { - pub async fn get_public_directory( - db: &DatabaseConnection, - public_directory_address: &str, - chain_id: &str, - ) -> Result, sea_orm::DbErr> { - PublicDirectoryEntity::find_by_contract_address(public_directory_address, chain_id) - .one(db) - .await - } -} +pub mod contract_interface; +pub mod data_interface; +pub mod index; diff --git a/src/services/public_directory/abi.json b/src/services/public_directory/abi.json new file mode 100644 index 0000000..6fcaf32 --- /dev/null +++ b/src/services/public_directory/abi.json @@ -0,0 +1,522 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "cotAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "memberId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevBlock", + "type": "uint256" + } + ], + "name": "CoTChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "memberId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevBlock", + "type": "uint256" + } + ], + "name": "DidAssociated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "memberId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevBlock", + "type": "uint256" + } + ], + "name": "DidDisassociated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "memberId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "iat", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "expires", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "rawData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "currentTimestap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevBlock", + "type": "uint256" + } + ], + "name": "MemberChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "internalType": "uint256", + "name": "exp", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "expires", + "type": "bool" + }, + { + "internalType": "address", + "name": "chainOfTrustAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "rawData", + "type": "bytes" + } + ], + "internalType": "struct IPublicDirectory.setMember", + "name": "_member", + "type": "tuple" + } + ], + "name": "addMember", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "cotAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "did", + "type": "string" + } + ], + "name": "associateCoTAddressByDid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "internalType": "string", + "name": "didToAssociate", + "type": "string" + } + ], + "name": "associateDid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "cotAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "did", + "type": "string" + } + ], + "name": "disassociateCoTAddressByDid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "internalType": "string", + "name": "didToDisassociate", + "type": "string" + } + ], + "name": "disassociateDid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "did", + "type": "string" + } + ], + "name": "getMemberDetails", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "exp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "iat", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "uat", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "expires", + "type": "bool" + } + ], + "internalType": "struct IPublicDirectory.member", + "name": "memberData", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "memberId", + "type": "uint256" + } + ], + "internalType": "struct IPublicDirectory.fullDetails", + "name": "foundMember", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "id", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isCot", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "memberCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "memberDetails", + "outputs": [ + { + "internalType": "uint256", + "name": "exp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "iat", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "uat", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "expires", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prevBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "did", + "type": "string" + } + ], + "name": "removeMemberByDid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "did", + "type": "string" + }, + { + "internalType": "uint256", + "name": "exp", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "expires", + "type": "bool" + }, + { + "internalType": "address", + "name": "chainOfTrustAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "rawData", + "type": "bytes" + } + ], + "internalType": "struct IPublicDirectory.setMember", + "name": "_member", + "type": "tuple" + } + ], + "name": "updateMemberDetailsByDid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/services/public_directory/contract_interface.rs b/src/services/public_directory/contract_interface.rs new file mode 100644 index 0000000..fcdc8d5 --- /dev/null +++ b/src/services/public_directory/contract_interface.rs @@ -0,0 +1,31 @@ +use web3::{ + contract::{Contract, Options}, + transports::Http, + types::U256, +}; + +use crate::{ + config::env_config::Config, services::trusted_registry::trusted_registry::Contract as C, +}; + +pub struct ContractInterface { + contract_instance: Contract, +} + +impl ContractInterface { + pub async fn new(params: C) -> anyhow::Result { + let rpc_url = Config::get_provider(params.chain_id); + let http = web3::transports::Http::new(&rpc_url)?; + let web3 = web3::Web3::new(http); + let abi = include_bytes!("./abi.json"); + let contract_instance = Contract::from_json(web3.eth(), params.contract_address, abi)?; + Ok(ContractInterface { contract_instance }) + } + pub async fn get_last_block(&self) -> anyhow::Result { + let result = self + .contract_instance + .query("prevBlock", (), None, Options::default(), None); + let prev_block: U256 = result.await?; + Ok(i64::from(prev_block.as_u32())) + } +} diff --git a/src/services/public_directory/data_interface.rs b/src/services/public_directory/data_interface.rs new file mode 100644 index 0000000..692c914 --- /dev/null +++ b/src/services/public_directory/data_interface.rs @@ -0,0 +1,37 @@ +use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::models::PublicDirectoryModel; +use crate::services::trusted_registry::trusted_registry::Contract; +use sea_orm::DatabaseConnection; + +pub struct DataInterfaceService { + params: Contract, +} + +impl DataInterfaceService { + pub fn new(params: Contract) -> DataInterfaceService { + DataInterfaceService { params } + } + pub async fn get_public_directory_from_database( + &self, + db: &DatabaseConnection, + ) -> Result, sea_orm::DbErr> { + PublicDirectoryEntity::find_by_contract_address( + &self.params.contract_address.to_string(), + &self.params.chain_id, + ) + .one(db) + .await + } + + pub async fn get_last_block(&self, db: &DatabaseConnection) -> anyhow::Result { + match self.get_public_directory_from_database(&db).await { + Ok(result) => match result { + Some(v) => Ok(v.last_block_saved), + None => Ok(0), + }, + Err(e) => { + return Err(e.into()); + } + } + } +} diff --git a/src/services/public_directory/index.rs b/src/services/public_directory/index.rs new file mode 100644 index 0000000..cee1b3d --- /dev/null +++ b/src/services/public_directory/index.rs @@ -0,0 +1,65 @@ +use log::info; +use sea_orm::DatabaseConnection; + +use crate::services::trusted_registry::trusted_registry::Contract; + +use super::{contract_interface::ContractInterface, data_interface::DataInterfaceService}; + +pub struct PublicDirectoryService { + pub contract_interface: ContractInterface, + pub data_interface: DataInterfaceService, +} + +impl PublicDirectoryService { + pub async fn new(params: Contract) -> anyhow::Result { + let contract_interface: ContractInterface; + match ContractInterface::new(params.clone()).await { + Ok(v) => { + contract_interface = v; + } + Err(e) => { + return Err(e); + } + } + Ok(PublicDirectoryService { + contract_interface, + data_interface: DataInterfaceService::new(params), + }) + } + pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { + let contract_last_block: i64; + match self.contract_interface.get_last_block().await { + Ok(result) => { + if result == 0 { + info!("No need to sweep public directory ... skipping sweep"); + return Ok(()); + } + + contract_last_block = result; + } + Err(e) => { + return Err(e.into()); + } + } + let last_block_saved; + match self.data_interface.get_last_block(&db).await { + Ok(result) => { + last_block_saved = result; + } + Err(e) => { + return Err(e.into()); + } + } + + if contract_last_block > last_block_saved { + info!( + "Starting sweep; last block saved {}, last block on Public directory {}", + &last_block_saved, &contract_last_block + ); + // TODO: sweep from contract_last_block to last_block_saved (reverse order) + return Ok(()); + } + + panic!("Unexpected values, last block saved on database:{}, is greater than contract_last_block: {}", &last_block_saved, &contract_last_block); + } +} From 948f3821f80cb8ac1af0fac1385ac174003e4720 Mon Sep 17 00:00:00 2001 From: eum602 Date: Wed, 21 Jun 2023 12:03:42 -0500 Subject: [PATCH 12/25] chore: add public directory main listener structure --- src/jobs/trusted_registries.rs | 2 +- src/services.rs | 1 + src/services/public_directory/abi.json | 121 +++++++++++++- .../public_directory/contract_interface.rs | 36 ++++- src/services/public_directory/index.rs | 149 +++++++++++++++++- src/services/web3.rs | 2 + src/services/web3/event.rs | 103 ++++++++++++ src/services/web3/utils.rs | 21 +++ src/utils/utils.rs | 8 +- 9 files changed, 427 insertions(+), 16 deletions(-) create mode 100644 src/services/web3.rs create mode 100644 src/services/web3/event.rs create mode 100644 src/services/web3/utils.rs diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs index d24321a..14797d3 100644 --- a/src/jobs/trusted_registries.rs +++ b/src/jobs/trusted_registries.rs @@ -29,7 +29,7 @@ impl TrustedRegistries { fn set_trusted_registries(&mut self) -> () { let _raw_trusted_registries = self.get_trusted_registries(); - let pd_str = "fee5C6939309a9906e292753B1947c8De1FD4423"; // "e647e8e076cffA10425c0C49aAaC1036a3b2ddB5"; // TODO: factor better error + let pd_str = "BD74DE9059CD63AC60c3AaC25c92a798be8D18b9"; // "e647e8e076cffA10425c0C49aAaC1036a3b2ddB5"; // TODO: factor better error let public_directory_address = <[u8; 20]>::from_hex(pd_str).expect("Invalid public directory contract address"); let cot_str = "EBB6854aa875867f684dd1d2338eC20908039c67"; diff --git a/src/services.rs b/src/services.rs index b727286..4851f08 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1,3 +1,4 @@ pub mod certificate_service; pub mod public_directory; pub mod trusted_registry; +pub mod web3; diff --git a/src/services/public_directory/abi.json b/src/services/public_directory/abi.json index 6fcaf32..b184461 100644 --- a/src/services/public_directory/abi.json +++ b/src/services/public_directory/abi.json @@ -1,14 +1,40 @@ [ { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "trustedForwarderAddress", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" }, { "anonymous": false, @@ -45,7 +71,7 @@ "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "string", "name": "did", "type": "string" @@ -70,7 +96,7 @@ "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "string", "name": "did", "type": "string" @@ -91,6 +117,19 @@ "name": "DidDisassociated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -101,7 +140,7 @@ "type": "uint256" }, { - "indexed": true, + "indexed": false, "internalType": "string", "name": "did", "type": "string" @@ -165,6 +204,19 @@ "name": "OwnershipTransferred", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, { "inputs": [ { @@ -349,6 +401,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -446,6 +511,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -518,5 +596,36 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" } ] diff --git a/src/services/public_directory/contract_interface.rs b/src/services/public_directory/contract_interface.rs index fcdc8d5..0368007 100644 --- a/src/services/public_directory/contract_interface.rs +++ b/src/services/public_directory/contract_interface.rs @@ -1,25 +1,41 @@ use web3::{ contract::{Contract, Options}, + ethabi::Log, transports::Http, types::U256, }; use crate::{ - config::env_config::Config, services::trusted_registry::trusted_registry::Contract as C, + config::env_config::Config, + services::{trusted_registry::trusted_registry::Contract as C, web3::event::EventManager}, }; +use std::str; + pub struct ContractInterface { contract_instance: Contract, + event_manager: EventManager, } impl ContractInterface { pub async fn new(params: C) -> anyhow::Result { - let rpc_url = Config::get_provider(params.chain_id); + let rpc_url = Config::get_provider(params.chain_id.clone()); let http = web3::transports::Http::new(&rpc_url)?; let web3 = web3::Web3::new(http); let abi = include_bytes!("./abi.json"); - let contract_instance = Contract::from_json(web3.eth(), params.contract_address, abi)?; - Ok(ContractInterface { contract_instance }) + let contract_instance = + Contract::from_json(web3.eth(), params.contract_address.clone(), abi)?; + let str_abi = match str::from_utf8(abi) { + Ok(s) => s, + Err(e) => { + return Err(e.into()); + } + }; + let event_manager = EventManager::new(str_abi.to_owned(), params)?; + Ok(ContractInterface { + contract_instance, + event_manager, + }) } pub async fn get_last_block(&self) -> anyhow::Result { let result = self @@ -28,4 +44,16 @@ impl ContractInterface { let prev_block: U256 = result.await?; Ok(i64::from(prev_block.as_u32())) } + + pub async fn get_events_in_block_by_method( + &self, + name_or_signature: &str, + block: &str, + ) -> anyhow::Result> { + let member_changed = self + .event_manager + .sweep(block, block, name_or_signature) + .await?; + Ok(member_changed) + } } diff --git a/src/services/public_directory/index.rs b/src/services/public_directory/index.rs index cee1b3d..f876a54 100644 --- a/src/services/public_directory/index.rs +++ b/src/services/public_directory/index.rs @@ -1,7 +1,12 @@ +use std::collections::HashMap; + use log::info; use sea_orm::DatabaseConnection; -use crate::services::trusted_registry::trusted_registry::Contract; +use crate::services::{ + trusted_registry::trusted_registry::Contract, + web3::utils::{get_string_from_string_in_log, get_u64_from_log}, +}; use super::{contract_interface::ContractInterface, data_interface::DataInterfaceService}; @@ -51,15 +56,153 @@ impl PublicDirectoryService { } } + // TODO: find vector of intermediate blocks to sweep since the last processed block + self.process_events_in_block_range(contract_last_block, last_block_saved) + .await + } + + pub async fn process_events_in_block_range( + &self, + contract_last_block: i64, + last_block_saved: i64, + ) -> anyhow::Result<()> { if contract_last_block > last_block_saved { info!( "Starting sweep; last block saved {}, last block on Public directory {}", &last_block_saved, &contract_last_block ); - // TODO: sweep from contract_last_block to last_block_saved (reverse order) + match self + .process_events_in_block(contract_last_block.to_string()) + .await + { + Ok(_prev_block) => { + // TODO: update last block processed in database + // TODO: Get next block (moving backward) + // if prev_block <= last_block_saved {} + // TODO: repeat the flow + } + Err(e) => { + return Err(e.into()); + } + } + return Ok(()); + } + if contract_last_block == last_block_saved { return Ok(()); } - panic!("Unexpected values, last block saved on database:{}, is greater than contract_last_block: {}", &last_block_saved, &contract_last_block); } + + pub async fn get_did_associated_map( + &self, + block: &str, + ) -> anyhow::Result>> { + let did_associated_logs = self + .contract_interface + .get_events_in_block_by_method("DidAssociated", &block) + .await + .unwrap(); + let mut did_associated_map: HashMap> = HashMap::new(); + let _l = did_associated_logs + .into_iter() + .map(|did_associated_log| { + let did = get_string_from_string_in_log(&did_associated_log, "did"); + let member_id = get_u64_from_log(&did_associated_log, "memberId"); + match did_associated_map.get(&member_id) { + Some(f) => { + let mut _f = f.clone(); + _f.push(did); + did_associated_map.insert(member_id, _f); + } + None => { + let mut v = Vec::new(); + v.push(did); + did_associated_map.insert(member_id, v); + } + }; + }) + .collect::>(); + Ok(did_associated_map) + } + + //// Returns previous block + pub async fn process_events_in_block(&self, block: String) -> anyhow::Result { + let mut did_associated_map = match self.get_did_associated_map(&block).await { + Ok(v) => v, + Err(e) => { + return Err(e); + } + }; + let mut prev_block: u64 = 0; + match self + .contract_interface + .get_events_in_block_by_method("MemberChanged", &block) + .await + { + Ok(member_changed_logs) => { + let _ = member_changed_logs + .into_iter() + .map(|member_changed_log| { + let exp = get_u64_from_log(&member_changed_log, "exp"); + let iat = get_u64_from_log(&member_changed_log, "iat"); + let member_id = get_u64_from_log(&member_changed_log, "memberId"); + let did = get_string_from_string_in_log(&member_changed_log, "did"); + prev_block = get_u64_from_log(&member_changed_log, "prevBlock"); + let transaction_timestamp = + get_u64_from_log(&member_changed_log, "currentTimestap"); + if transaction_timestamp == iat { + info!("new member was added/updated {} {}", did, member_id); + // 1. remove existing did in did associated mapping + match did_associated_map.get_mut(&member_id) { + Some(v) => { + let pos = + v.into_iter().rposition(|e| e.to_string() == did).unwrap(); + v.remove(pos); + } + None => panic!( + "Expected value in didAssociated event but was not found {}", + did + ), + }; + // TODO: 2. save to database -> if there exist a registry in which the block_number is greater then skip otherwise update + } else if transaction_timestamp == exp { + // MemberChanged with currentTimestamp==exp -> remove the entity did and all its dids from the database + info!("a member was removed"); + } else { + panic!( + "Unexpected values for iat: {}, exp: {}, transaction timestamp: {}", + iat, exp, transaction_timestamp + ); + } + }) + .collect::>(); + } + Err(e) => { + return Err(e); + } + } + // DidAssociated && !Memberchanged -> just new Did associated to an existing member + let _ = did_associated_map + .into_iter() + .map(|_el| { + // TODO: find that member in database + // TODO: associate the new did with the db found member + }) + .collect::>(); + + // DidDisassociated -> remove just that did from database that did + match self + .contract_interface + .get_events_in_block_by_method("DidAssociated", &block) + .await + { + Ok(_did_disassociated_logs) => { + // TODO: remove these dids from database + } + Err(e) => { + return Err(e); + } + } + Ok(prev_block) + } } diff --git a/src/services/web3.rs b/src/services/web3.rs new file mode 100644 index 0000000..0a190d0 --- /dev/null +++ b/src/services/web3.rs @@ -0,0 +1,2 @@ +pub mod event; +pub mod utils; diff --git a/src/services/web3/event.rs b/src/services/web3/event.rs new file mode 100644 index 0000000..17b7b39 --- /dev/null +++ b/src/services/web3/event.rs @@ -0,0 +1,103 @@ +use crate::{ + config::env_config::Config, services::trusted_registry::trusted_registry::Contract as C, + utils::utils::Utils, +}; +use anyhow::anyhow; +use sha3::{Digest, Keccak256}; +use web3::{ + ethabi::{Bytes, Contract, Event, Hash, Log, RawLog}, + transports::Http, + types::{BlockNumber, FilterBuilder, H160, H256, U64}, + Web3, +}; + +pub struct EventManager { + abi: String, + web3: Web3, + address: Vec, +} + +impl EventManager { + pub fn new(abi: String, params: C) -> anyhow::Result { + let rpc_url = Config::get_provider(params.chain_id.clone()); + let http = web3::transports::Http::new(&rpc_url)?; + let web3 = web3::Web3::new(http); + let mut address = Vec::new(); + address.push(params.contract_address); + Ok(EventManager { abi, web3, address }) + } + + fn wrap_signature(&self, event: Event) -> anyhow::Result>> { + let signature = event.signature(); + let topic: Vec = vec![signature]; + Ok(Some(topic)) + } + + pub async fn sweep( + &self, + from: &str, + to: &str, + name_or_signature: &str, + ) -> anyhow::Result> { + let event = self.load_event(&self.abi, &name_or_signature)?; + let wrapped_topic = self.wrap_signature(event.clone()).unwrap(); // todo: improve + let from = Utils::integer_part(&from).unwrap(); + let to = Utils::integer_part(&to).unwrap(); + let filter = FilterBuilder::default() + .address(self.address.clone()) + .topics(wrapped_topic, None, None, None) + .from_block(BlockNumber::Number(U64::from(from))) + .to_block(BlockNumber::Number(U64::from(to))) + .build(); + let filter = self.web3.eth_filter().create_logs_filter(filter).await?; + let logs = filter.logs().await.unwrap(); + let result = logs + .into_iter() + .map(|log| { + let mapped_topics = log + .topics + .into_iter() + .map(|topic| Hash::from_slice(topic.as_bytes())) + .collect::>(); + match event.parse_log(RawLog { + topics: mapped_topics, + data: Bytes::from(log.data.0), + }) { + Ok(log) => log, + Err(e) => panic!("{}", e), + } + }) + .collect::>(); + Ok(result) + } + + fn load_event(&self, abi: &str, name_or_signature: &str) -> anyhow::Result { + let contract: Contract = serde_json::from_str(abi).unwrap(); + let params_start = name_or_signature.find('('); + match params_start { + Some(params_start) => { + let name = &name_or_signature[..params_start]; + let signature = Hash::from_slice( + Keccak256::digest(name_or_signature.replace(' ', "").as_bytes()).as_slice(), + ); + contract + .events_by_name(name)? + .iter() + .find(|event| event.signature() == signature) + .cloned() + .ok_or_else(|| anyhow!("Invalid Signature `{}`", signature)) + } + None => { + let events = contract.events_by_name(name_or_signature)?; + match events.len() { + 0 => unreachable!(), + 1 => Ok(events[0].clone()), + _ => Err(anyhow!( + "More than one function found for name `{}`, try providing full signature", + name_or_signature + )), + } + } + } + } +} diff --git a/src/services/web3/utils.rs b/src/services/web3/utils.rs new file mode 100644 index 0000000..4ff5d37 --- /dev/null +++ b/src/services/web3/utils.rs @@ -0,0 +1,21 @@ +use web3::ethabi::Log; + +pub fn get_u64_from_log(log: &Log, param_name: &str) -> u64 { + match log.params.iter().find(|¶m| param.name == param_name) { + Some(param) => match param.value.clone().into_uint() { + Some(value) => u64::from(value.as_u64()), // 10 digit timestamp + None => panic!("Error decoding param {}", param_name), + }, + None => panic!("No value found for `{}`", param_name), + } +} + +pub fn get_string_from_string_in_log(log: &Log, param_name: &str) -> String { + match log.params.iter().find(|¶m| param.name == param_name) { + Some(param) => match param.value.clone() { + web3::ethabi::Token::String(v) => v, + _ => panic!("Passed value is not a fixed bytes"), + }, + None => panic!("No value found for param {}", param_name), + } +} diff --git a/src/utils/utils.rs b/src/utils/utils.rs index 76eee67..a40c86b 100644 --- a/src/utils/utils.rs +++ b/src/utils/utils.rs @@ -1,5 +1,5 @@ use log::error; -use std::env; +use std::{env, num::ParseIntError}; pub struct Utils {} @@ -14,7 +14,7 @@ impl Utils { } } - pub fn get_env_or_err(env_name: &'static str) -> Result { + pub fn get_env_or_err(env_name: &str) -> Result { match env::var(env_name) { Ok(s) => Ok(s), Err(_) => Err("not found"), @@ -27,4 +27,8 @@ impl Utils { i => i, } } + pub fn integer_part(value: &str) -> Result { + let dot_pos = value.find(".").unwrap_or(value.len()); + value[..dot_pos].parse() + } } From 0767c6efa1c5208103ba5b4071dd590bb92b185e Mon Sep 17 00:00:00 2001 From: eum602 Date: Wed, 21 Jun 2023 19:58:16 -0500 Subject: [PATCH 13/25] chore: update public directory database model --- src/entities/models.rs | 1 + src/entities/public_directory/model.rs | 2 ++ src/migration/m20230617_195505_public_directory.rs | 12 ++++++++++++ src/services/public_directory/contract_interface.rs | 4 ++-- src/services/public_directory/data_interface.rs | 4 ++-- src/services/public_directory/index.rs | 6 +++--- src/services/web3/event.rs | 13 +++++-------- 7 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/entities/models.rs b/src/entities/models.rs index 98434d5..47d899d 100644 --- a/src/entities/models.rs +++ b/src/entities/models.rs @@ -1 +1,2 @@ +pub use crate::entities::public_directory::model::ActiveModel as PublicDirectoryActiveModel; pub use crate::entities::public_directory::model::Model as PublicDirectoryModel; diff --git a/src/entities/public_directory/model.rs b/src/entities/public_directory/model.rs index f6ef276..af55d0c 100644 --- a/src/entities/public_directory/model.rs +++ b/src/entities/public_directory/model.rs @@ -10,6 +10,8 @@ pub struct Model { pub id: Uuid, #[sea_orm(column_type = "Text")] pub contract_address: String, + pub upper_block: i64, + pub last_processed_block: i64, pub last_block_saved: i64, pub chain_id: String, } diff --git a/src/migration/m20230617_195505_public_directory.rs b/src/migration/m20230617_195505_public_directory.rs index 6f6201c..010769a 100644 --- a/src/migration/m20230617_195505_public_directory.rs +++ b/src/migration/m20230617_195505_public_directory.rs @@ -23,6 +23,16 @@ impl MigrationTrait for Migration { .not_null() .unique_key(), ) + .col( + ColumnDef::new(PublicDirectory::UpperBlock) + .big_integer() + .not_null(), + ) + .col( + ColumnDef::new(PublicDirectory::LastProcessedBlock) + .big_integer() + .not_null(), + ) .col( ColumnDef::new(PublicDirectory::LastBlockSaved) .big_integer() @@ -46,6 +56,8 @@ enum PublicDirectory { Table, Id, ContractAddress, + UpperBlock, + LastProcessedBlock, LastBlockSaved, ChainId, } diff --git a/src/services/public_directory/contract_interface.rs b/src/services/public_directory/contract_interface.rs index 0368007..7ba1137 100644 --- a/src/services/public_directory/contract_interface.rs +++ b/src/services/public_directory/contract_interface.rs @@ -37,12 +37,12 @@ impl ContractInterface { event_manager, }) } - pub async fn get_last_block(&self) -> anyhow::Result { + pub async fn get_last_block(&self) -> anyhow::Result { let result = self .contract_instance .query("prevBlock", (), None, Options::default(), None); let prev_block: U256 = result.await?; - Ok(i64::from(prev_block.as_u32())) + Ok(prev_block.as_u64()) } pub async fn get_events_in_block_by_method( diff --git a/src/services/public_directory/data_interface.rs b/src/services/public_directory/data_interface.rs index 692c914..dd3cea9 100644 --- a/src/services/public_directory/data_interface.rs +++ b/src/services/public_directory/data_interface.rs @@ -23,10 +23,10 @@ impl DataInterfaceService { .await } - pub async fn get_last_block(&self, db: &DatabaseConnection) -> anyhow::Result { + pub async fn get_last_block(&self, db: &DatabaseConnection) -> anyhow::Result { match self.get_public_directory_from_database(&db).await { Ok(result) => match result { - Some(v) => Ok(v.last_block_saved), + Some(v) => Ok(v.last_block_saved as u64), None => Ok(0), }, Err(e) => { diff --git a/src/services/public_directory/index.rs b/src/services/public_directory/index.rs index f876a54..53a34c0 100644 --- a/src/services/public_directory/index.rs +++ b/src/services/public_directory/index.rs @@ -32,7 +32,7 @@ impl PublicDirectoryService { }) } pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { - let contract_last_block: i64; + let contract_last_block: u64; match self.contract_interface.get_last_block().await { Ok(result) => { if result == 0 { @@ -63,8 +63,8 @@ impl PublicDirectoryService { pub async fn process_events_in_block_range( &self, - contract_last_block: i64, - last_block_saved: i64, + contract_last_block: u64, + last_block_saved: u64, ) -> anyhow::Result<()> { if contract_last_block > last_block_saved { info!( diff --git a/src/services/web3/event.rs b/src/services/web3/event.rs index 17b7b39..beabce4 100644 --- a/src/services/web3/event.rs +++ b/src/services/web3/event.rs @@ -1,6 +1,5 @@ use crate::{ config::env_config::Config, services::trusted_registry::trusted_registry::Contract as C, - utils::utils::Utils, }; use anyhow::anyhow; use sha3::{Digest, Keccak256}; @@ -35,19 +34,17 @@ impl EventManager { pub async fn sweep( &self, - from: &str, - to: &str, + from: &u64, + to: &u64, name_or_signature: &str, ) -> anyhow::Result> { let event = self.load_event(&self.abi, &name_or_signature)?; - let wrapped_topic = self.wrap_signature(event.clone()).unwrap(); // todo: improve - let from = Utils::integer_part(&from).unwrap(); - let to = Utils::integer_part(&to).unwrap(); + let wrapped_topic: Option> = self.wrap_signature(event.clone()).unwrap(); // todo: improve let filter = FilterBuilder::default() .address(self.address.clone()) .topics(wrapped_topic, None, None, None) - .from_block(BlockNumber::Number(U64::from(from))) - .to_block(BlockNumber::Number(U64::from(to))) + .from_block(BlockNumber::Number(U64::from(from.to_owned()))) + .to_block(BlockNumber::Number(U64::from(to.to_owned()))) .build(); let filter = self.web3.eth_filter().create_logs_filter(filter).await?; let logs = filter.logs().await.unwrap(); From c6e122314b537ef061a483439a9832a666049723 Mon Sep 17 00:00:00 2001 From: eum602 Date: Wed, 21 Jun 2023 20:01:30 -0500 Subject: [PATCH 14/25] chore: update public directory main listener structure --- .../public_directory/contract_interface.rs | 72 ++++++- src/services/public_directory/index.rs | 175 ++++++++++++++---- .../trusted_registry/trusted_registry.rs | 3 +- 3 files changed, 211 insertions(+), 39 deletions(-) diff --git a/src/services/public_directory/contract_interface.rs b/src/services/public_directory/contract_interface.rs index 7ba1137..0b7aa2d 100644 --- a/src/services/public_directory/contract_interface.rs +++ b/src/services/public_directory/contract_interface.rs @@ -7,7 +7,10 @@ use web3::{ use crate::{ config::env_config::Config, - services::{trusted_registry::trusted_registry::Contract as C, web3::event::EventManager}, + services::{ + trusted_registry::trusted_registry::Contract as C, + web3::{event::EventManager, utils::get_u64_from_log}, + }, }; use std::str; @@ -45,10 +48,75 @@ impl ContractInterface { Ok(prev_block.as_u64()) } + /// Returns block previous prior to the last block saved param on the smart contract + pub async fn find_previous_block(&self, block: &u64) -> anyhow::Result> { + match self + .find_previous_block_by_event_name("MemberChanged", block) + .await + { + Ok(v) => { + if let Some(s) = v { + return Ok(Some(s)); + } + } + Err(e) => { + return Err(e.into()); + } + }; + match self + .find_previous_block_by_event_name("DidAssociated", block) + .await + { + Ok(v) => { + if let Some(s) = v { + return Ok(Some(s)); + } + } + Err(e) => { + return Err(e.into()); + } + }; + match self + .find_previous_block_by_event_name("DidDisassociated", block) + .await + { + Ok(v) => { + if let Some(s) = v { + return Ok(Some(s)); + } + } + Err(e) => { + return Err(e.into()); + } + }; + Ok(None) + } + + pub async fn find_previous_block_by_event_name( + &self, + name_or_signature: &str, + block: &u64, + ) -> anyhow::Result> { + match self + .get_events_in_block_by_method(name_or_signature, block) + .await + { + Ok(logs) => { + if logs.len() == 0 { + return Ok(None); + } + Ok(Some(get_u64_from_log(&logs[0], "prevBlock"))) + } + Err(e) => { + return Err(e); + } + } + } + pub async fn get_events_in_block_by_method( &self, name_or_signature: &str, - block: &str, + block: &u64, ) -> anyhow::Result> { let member_changed = self .event_manager diff --git a/src/services/public_directory/index.rs b/src/services/public_directory/index.rs index 53a34c0..78288aa 100644 --- a/src/services/public_directory/index.rs +++ b/src/services/public_directory/index.rs @@ -1,16 +1,20 @@ use std::collections::HashMap; -use log::info; -use sea_orm::DatabaseConnection; +use log::{debug, info}; +use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; +use uuid::Uuid; use crate::services::{ trusted_registry::trusted_registry::Contract, web3::utils::{get_string_from_string_in_log, get_u64_from_log}, }; +use crate::entities::models::PublicDirectoryActiveModel; + use super::{contract_interface::ContractInterface, data_interface::DataInterfaceService}; pub struct PublicDirectoryService { + pub params: Contract, pub contract_interface: ContractInterface, pub data_interface: DataInterfaceService, } @@ -27,58 +31,159 @@ impl PublicDirectoryService { } } Ok(PublicDirectoryService { + params: params.clone(), contract_interface, data_interface: DataInterfaceService::new(params), }) } - pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { - let contract_last_block: u64; - match self.contract_interface.get_last_block().await { - Ok(result) => { - if result == 0 { - info!("No need to sweep public directory ... skipping sweep"); + + pub async fn exec_or_resume_scheduled_sweep( + &self, + db: &DatabaseConnection, + ) -> anyhow::Result<()> { + info!("excuting scheduled worker thread"); + match self + .data_interface + .get_public_directory_from_database(&db) + .await + { + Ok(v) => match v { + Some(v) => { + if v.upper_block == v.last_block_saved { + info!("All up to date in this scheduled task"); + return Ok(()); + } + + if v.upper_block >= v.last_processed_block + && v.last_processed_block > v.last_block_saved + { + info!("Found not finished job, resuming"); + match self + .contract_interface + .find_previous_block(&(v.last_processed_block as u64)) + .await + { + Ok(u) => { + if let Some(prev_to_last_processed_block) = u { + return self + .process_events_in_block_range( + prev_to_last_processed_block, + v.last_block_saved as u64, + ) + .await; + } + } + Err(e) => { + return Err(e); + } + } + } + info!("Starting scheduled job"); + return self + .process_events_in_block_range( + v.upper_block as u64, + v.last_block_saved as u64, + ) + .await; + } + None => { + debug!("None was found in the database"); return Ok(()); } - - contract_last_block = result; - } + }, Err(e) => { return Err(e.into()); } } - let last_block_saved; - match self.data_interface.get_last_block(&db).await { - Ok(result) => { - last_block_saved = result; + } + pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { + match self.exec_or_resume_scheduled_sweep(db).await { + Ok(_v) => { + let contract_last_block: u64; + match self.contract_interface.get_last_block().await { + Ok(result) => { + if result == 0 { + info!("No events found in contract... skipping sweep"); + return Ok(()); + } + + contract_last_block = result; + } + Err(e) => { + return Err(e.into()); + } + } + // set upper block to contract last saved block + // set last processed block to upper block + match self + .data_interface + .get_public_directory_from_database(&db) + .await + { + Ok(v) => match v { + Some(m) => { + // verify whether insert is needed + if contract_last_block > 0 + && contract_last_block == m.upper_block as u64 + && contract_last_block == m.last_block_saved as u64 + { + info!("There are no changes in the contract .. skipping sweep"); + return Ok(()); + } + let mut s: PublicDirectoryActiveModel = m.into(); + s.upper_block = Set(contract_last_block as i64); + s.last_processed_block = Set(0); + match s.update(db).await { + Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, + Err(err) => { + return Err(err.into()); + } + } + } + None => { + info!("Initializing metadata for contract in database"); + let db_registry = PublicDirectoryActiveModel { + id: Set(Uuid::new_v4()), + contract_address: Set(self.params.contract_address.to_string()), + upper_block: Set(contract_last_block as i64), + last_processed_block: Set(0), + last_block_saved: Set(0), + chain_id: Set(self.params.chain_id.clone()), + }; + match db_registry.insert(db).await { + Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, + Err(e) => { + return Err(e.into()); + } + } + } + }, + Err(e) => { + return Err(e.into()); + } + } } Err(e) => { - return Err(e.into()); + return Err(e); } } - - // TODO: find vector of intermediate blocks to sweep since the last processed block - self.process_events_in_block_range(contract_last_block, last_block_saved) - .await } pub async fn process_events_in_block_range( &self, - contract_last_block: u64, - last_block_saved: u64, + contract_block: u64, + target_block: u64, ) -> anyhow::Result<()> { - if contract_last_block > last_block_saved { + if contract_block > target_block { info!( - "Starting sweep; last block saved {}, last block on Public directory {}", - &last_block_saved, &contract_last_block + "Starting sweep; from block {}, to target block {}", + &contract_block, &target_block ); - match self - .process_events_in_block(contract_last_block.to_string()) - .await - { + match self.process_events_in_block(&contract_block).await { Ok(_prev_block) => { // TODO: update last block processed in database // TODO: Get next block (moving backward) - // if prev_block <= last_block_saved {} + // if prev_block <= target_block {} // TODO: repeat the flow } Err(e) => { @@ -87,15 +192,15 @@ impl PublicDirectoryService { } return Ok(()); } - if contract_last_block == last_block_saved { + if contract_block == target_block { return Ok(()); } - panic!("Unexpected values, last block saved on database:{}, is greater than contract_last_block: {}", &last_block_saved, &contract_last_block); + panic!("Unexpected values, last block saved on database:{}, is greater than passed contract block: {}", &target_block, &contract_block); } pub async fn get_did_associated_map( &self, - block: &str, + block: &u64, ) -> anyhow::Result>> { let did_associated_logs = self .contract_interface @@ -126,7 +231,7 @@ impl PublicDirectoryService { } //// Returns previous block - pub async fn process_events_in_block(&self, block: String) -> anyhow::Result { + pub async fn process_events_in_block(&self, block: &u64) -> anyhow::Result { let mut did_associated_map = match self.get_did_associated_map(&block).await { Ok(v) => v, Err(e) => { @@ -193,7 +298,7 @@ impl PublicDirectoryService { // DidDisassociated -> remove just that did from database that did match self .contract_interface - .get_events_in_block_by_method("DidAssociated", &block) + .get_events_in_block_by_method("DidDisassociated", &block) .await { Ok(_did_disassociated_logs) => { diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs index 1b7e8ec..86e6d0f 100644 --- a/src/services/trusted_registry/trusted_registry.rs +++ b/src/services/trusted_registry/trusted_registry.rs @@ -40,14 +40,13 @@ impl TrustedRegistry { return Err(e); } } - let mut _last_block_saved = 0; match public_directory_service_instance.sweep(&c).await { Ok(_) => { // sweep chain of trust // read did registry changes } Err(e) => { - error!("There was an error while trying to retrieve public directory last block saved {:?}", e); + error!("There was an error while trying to retrieve public directory last block saved ---> {:?}", e); return Err(e.into()); } } From 56a2975091ab382c1f8350eea305e0311f4a71d5 Mon Sep 17 00:00:00 2001 From: eum602 Date: Wed, 21 Jun 2023 21:03:55 -0500 Subject: [PATCH 15/25] chore: database model for did --- src/entities.rs | 1 + src/entities/did.rs | 2 ++ src/entities/did/model.rs | 21 ++++++++++++++ src/entities/did/select.rs | 9 ++++++ src/entities/entities.rs | 1 + src/entities/models.rs | 3 ++ src/migration.rs | 1 + src/migration/index.rs | 10 +++++-- src/migration/m20230622_011005_did.rs | 41 +++++++++++++++++++++++++++ 9 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/entities/did.rs create mode 100644 src/entities/did/model.rs create mode 100644 src/entities/did/select.rs create mode 100644 src/migration/m20230622_011005_did.rs diff --git a/src/entities.rs b/src/entities.rs index e97103d..c89247f 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -1,3 +1,4 @@ +pub mod did; pub mod entities; pub mod models; pub mod public_directory; diff --git a/src/entities/did.rs b/src/entities/did.rs new file mode 100644 index 0000000..46698dd --- /dev/null +++ b/src/entities/did.rs @@ -0,0 +1,2 @@ +pub mod model; +pub mod select; diff --git a/src/entities/did/model.rs b/src/entities/did/model.rs new file mode 100644 index 0000000..07369bb --- /dev/null +++ b/src/entities/did/model.rs @@ -0,0 +1,21 @@ +use rocket::serde::{Deserialize, Serialize}; +use sea_orm::entity::prelude::*; +use uuid::Uuid; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] +#[serde(crate = "rocket::serde")] +#[sea_orm(table_name = "did")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + #[sea_orm(column_type = "Text")] + pub did: String, + pub upper_block: i64, + pub last_processed_block: i64, + pub last_block_saved: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entities/did/select.rs b/src/entities/did/select.rs new file mode 100644 index 0000000..b260b5c --- /dev/null +++ b/src/entities/did/select.rs @@ -0,0 +1,9 @@ +use super::*; +use crate::entities::entities::DidEntity; +use sea_orm::{entity::*, query::*}; + +impl DidEntity { + pub fn find_by_did(did: &str) -> Select { + Self::find().filter(model::Column::Did.contains(did)) + } +} diff --git a/src/entities/entities.rs b/src/entities/entities.rs index 6afd78e..0402293 100644 --- a/src/entities/entities.rs +++ b/src/entities/entities.rs @@ -1 +1,2 @@ +pub use crate::entities::did::model::Entity as DidEntity; pub use crate::entities::public_directory::model::Entity as PublicDirectoryEntity; diff --git a/src/entities/models.rs b/src/entities/models.rs index 47d899d..8d5f22a 100644 --- a/src/entities/models.rs +++ b/src/entities/models.rs @@ -1,2 +1,5 @@ pub use crate::entities::public_directory::model::ActiveModel as PublicDirectoryActiveModel; pub use crate::entities::public_directory::model::Model as PublicDirectoryModel; + +pub use crate::entities::did::model::ActiveModel as DidActiveModel; +pub use crate::entities::did::model::Model as DidModel; diff --git a/src/migration.rs b/src/migration.rs index eab0348..2d7b88a 100644 --- a/src/migration.rs +++ b/src/migration.rs @@ -1,2 +1,3 @@ pub mod index; pub mod m20230617_195505_public_directory; +pub mod m20230622_011005_did; diff --git a/src/migration/index.rs b/src/migration/index.rs index ca55a6b..e7e008e 100644 --- a/src/migration/index.rs +++ b/src/migration/index.rs @@ -2,13 +2,19 @@ use rocket::{fairing, Build, Rocket}; pub use sea_orm_migration::prelude::*; use sea_orm_rocket::Database; -use crate::{databases::pool::Db, migration::m20230617_195505_public_directory}; +use crate::{ + databases::pool::Db, + migration::{m20230617_195505_public_directory, m20230622_011005_did}, +}; pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() -> Vec> { - vec![Box::new(m20230617_195505_public_directory::Migration)] + vec![ + Box::new(m20230617_195505_public_directory::Migration), + Box::new(m20230622_011005_did::Migration), + ] } } diff --git a/src/migration/m20230622_011005_did.rs b/src/migration/m20230622_011005_did.rs new file mode 100644 index 0000000..6075f65 --- /dev/null +++ b/src/migration/m20230622_011005_did.rs @@ -0,0 +1,41 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Did::Table) + .if_not_exists() + .col(ColumnDef::new(Did::Id).uuid().not_null().primary_key()) + .col(ColumnDef::new(Did::UpperBlock).big_integer().not_null()) + .col( + ColumnDef::new(Did::LastProcessedBlock) + .big_integer() + .not_null(), + ) + .col(ColumnDef::new(Did::LastBlockSaved).big_integer().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Did::Table).to_owned()) + .await + } +} + +#[derive(Iden)] +enum Did { + Table, + Id, + UpperBlock, + LastProcessedBlock, + LastBlockSaved, +} From f29af77c04b93a8c34d2351145b3eab1eb0585a1 Mon Sep 17 00:00:00 2001 From: eum602 Date: Wed, 21 Jun 2023 23:36:34 -0500 Subject: [PATCH 16/25] chore: database model for public directory member --- src/entities.rs | 1 + src/entities/entities.rs | 1 + src/entities/models.rs | 3 + src/entities/pd_member.rs | 1 + src/entities/pd_member/model.rs | 20 ++++++ src/migration.rs | 1 + src/migration/index.rs | 5 +- .../m20230617_195505_public_directory.rs | 2 +- src/migration/m20230622_035815_pd_member.rs | 62 +++++++++++++++++++ 9 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/entities/pd_member.rs create mode 100644 src/entities/pd_member/model.rs create mode 100644 src/migration/m20230622_035815_pd_member.rs diff --git a/src/entities.rs b/src/entities.rs index c89247f..d44669e 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -1,4 +1,5 @@ pub mod did; pub mod entities; pub mod models; +pub mod pd_member; pub mod public_directory; diff --git a/src/entities/entities.rs b/src/entities/entities.rs index 0402293..ecff5ba 100644 --- a/src/entities/entities.rs +++ b/src/entities/entities.rs @@ -1,2 +1,3 @@ pub use crate::entities::did::model::Entity as DidEntity; +pub use crate::entities::pd_member::model::Entity as PdMember; pub use crate::entities::public_directory::model::Entity as PublicDirectoryEntity; diff --git a/src/entities/models.rs b/src/entities/models.rs index 8d5f22a..847abf6 100644 --- a/src/entities/models.rs +++ b/src/entities/models.rs @@ -3,3 +3,6 @@ pub use crate::entities::public_directory::model::Model as PublicDirectoryModel; pub use crate::entities::did::model::ActiveModel as DidActiveModel; pub use crate::entities::did::model::Model as DidModel; + +pub use crate::entities::pd_member::model::ActiveModel as PdMemberActiveModel; +pub use crate::entities::pd_member::model::Model as PdMemberModel; diff --git a/src/entities/pd_member.rs b/src/entities/pd_member.rs new file mode 100644 index 0000000..65880be --- /dev/null +++ b/src/entities/pd_member.rs @@ -0,0 +1 @@ +pub mod model; diff --git a/src/entities/pd_member/model.rs b/src/entities/pd_member/model.rs new file mode 100644 index 0000000..87ca9e8 --- /dev/null +++ b/src/entities/pd_member/model.rs @@ -0,0 +1,20 @@ +use rocket::serde::{Deserialize, Serialize}; +use sea_orm::entity::prelude::*; +use uuid::Uuid; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] +#[serde(crate = "rocket::serde")] +#[sea_orm(table_name = "pd_member")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + pub member_id: i64, + pub exp: i64, + pub pubic_directory_id: i64, + pub block_number: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/migration.rs b/src/migration.rs index 2d7b88a..35f3192 100644 --- a/src/migration.rs +++ b/src/migration.rs @@ -1,3 +1,4 @@ pub mod index; pub mod m20230617_195505_public_directory; pub mod m20230622_011005_did; +pub mod m20230622_035815_pd_member; diff --git a/src/migration/index.rs b/src/migration/index.rs index e7e008e..f3acae2 100644 --- a/src/migration/index.rs +++ b/src/migration/index.rs @@ -4,7 +4,9 @@ use sea_orm_rocket::Database; use crate::{ databases::pool::Db, - migration::{m20230617_195505_public_directory, m20230622_011005_did}, + migration::{ + m20230617_195505_public_directory, m20230622_011005_did, m20230622_035815_pd_member, + }, }; pub struct Migrator; @@ -14,6 +16,7 @@ impl MigratorTrait for Migrator { vec![ Box::new(m20230617_195505_public_directory::Migration), Box::new(m20230622_011005_did::Migration), + Box::new(m20230622_035815_pd_member::Migration), ] } } diff --git a/src/migration/m20230617_195505_public_directory.rs b/src/migration/m20230617_195505_public_directory.rs index 010769a..6c72d98 100644 --- a/src/migration/m20230617_195505_public_directory.rs +++ b/src/migration/m20230617_195505_public_directory.rs @@ -52,7 +52,7 @@ impl MigrationTrait for Migration { } #[derive(Iden)] -enum PublicDirectory { +pub(crate) enum PublicDirectory { Table, Id, ContractAddress, diff --git a/src/migration/m20230622_035815_pd_member.rs b/src/migration/m20230622_035815_pd_member.rs new file mode 100644 index 0000000..fae3fd3 --- /dev/null +++ b/src/migration/m20230622_035815_pd_member.rs @@ -0,0 +1,62 @@ +use sea_orm_migration::prelude::*; + +use super::m20230617_195505_public_directory::PublicDirectory; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(PdMember::Table) + .if_not_exists() + .col(ColumnDef::new(PdMember::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(PdMember::MemberId) + .big_integer() + .not_null() + .unique_key(), + ) + .col(ColumnDef::new(PdMember::Exp).big_integer().not_null()) + .col( + ColumnDef::new(PdMember::BlockNumber) + .big_integer() + .not_null(), + ) + .col( + ColumnDef::new(PdMember::PublicDirectoryId) + .uuid() + .not_null(), + ) + .foreign_key( + ForeignKey::create() + .name("public_directory_id") + .from(PdMember::Table, PdMember::PublicDirectoryId) + .to(PublicDirectory::Table, PublicDirectory::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(PdMember::Table).to_owned()) + .await + } +} + +#[derive(Iden)] +enum PdMember { + Table, + Id, + MemberId, + Exp, + PublicDirectoryId, + BlockNumber, +} From e97cbac270eb0bcdf3aa6f17b2c4f89c48f19f77 Mon Sep 17 00:00:00 2001 From: eum602 Date: Thu, 22 Jun 2023 00:12:46 -0500 Subject: [PATCH 17/25] chore: database model for did in public directory --- src/entities.rs | 1 + src/entities/entities.rs | 1 + src/entities/models.rs | 3 + src/entities/pd_did_member.rs | 1 + src/entities/pd_did_member/model.rs | 19 ++++++ src/entities/pd_member/model.rs | 2 +- src/migration.rs | 1 + src/migration/index.rs | 2 + src/migration/m20230622_011005_did.rs | 2 +- src/migration/m20230622_035815_pd_member.rs | 2 +- .../m20230622_044839_pd_did_member.rs | 64 +++++++++++++++++++ 11 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 src/entities/pd_did_member.rs create mode 100644 src/entities/pd_did_member/model.rs create mode 100644 src/migration/m20230622_044839_pd_did_member.rs diff --git a/src/entities.rs b/src/entities.rs index d44669e..72a4751 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -1,5 +1,6 @@ pub mod did; pub mod entities; pub mod models; +pub mod pd_did_member; pub mod pd_member; pub mod public_directory; diff --git a/src/entities/entities.rs b/src/entities/entities.rs index ecff5ba..545aac5 100644 --- a/src/entities/entities.rs +++ b/src/entities/entities.rs @@ -1,3 +1,4 @@ pub use crate::entities::did::model::Entity as DidEntity; +pub use crate::entities::pd_did_member::model::Entity as PdDidMemberEntity; pub use crate::entities::pd_member::model::Entity as PdMember; pub use crate::entities::public_directory::model::Entity as PublicDirectoryEntity; diff --git a/src/entities/models.rs b/src/entities/models.rs index 847abf6..4fcb73a 100644 --- a/src/entities/models.rs +++ b/src/entities/models.rs @@ -6,3 +6,6 @@ pub use crate::entities::did::model::Model as DidModel; pub use crate::entities::pd_member::model::ActiveModel as PdMemberActiveModel; pub use crate::entities::pd_member::model::Model as PdMemberModel; + +pub use crate::entities::pd_did_member::model::ActiveModel as PdDidMemberActiveModel; +pub use crate::entities::pd_did_member::model::Model as PdDidMemberModel; diff --git a/src/entities/pd_did_member.rs b/src/entities/pd_did_member.rs new file mode 100644 index 0000000..65880be --- /dev/null +++ b/src/entities/pd_did_member.rs @@ -0,0 +1 @@ +pub mod model; diff --git a/src/entities/pd_did_member/model.rs b/src/entities/pd_did_member/model.rs new file mode 100644 index 0000000..838c808 --- /dev/null +++ b/src/entities/pd_did_member/model.rs @@ -0,0 +1,19 @@ +use rocket::serde::{Deserialize, Serialize}; +use sea_orm::entity::prelude::*; +use uuid::Uuid; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] +#[serde(crate = "rocket::serde")] +#[sea_orm(table_name = "pd_did_member")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + pub did_id: Uuid, + pub pd_member_id: Uuid, + pub block_number: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entities/pd_member/model.rs b/src/entities/pd_member/model.rs index 87ca9e8..d43bdae 100644 --- a/src/entities/pd_member/model.rs +++ b/src/entities/pd_member/model.rs @@ -10,7 +10,7 @@ pub struct Model { pub id: Uuid, pub member_id: i64, pub exp: i64, - pub pubic_directory_id: i64, + pub pubic_directory_id: Uuid, pub block_number: i64, } diff --git a/src/migration.rs b/src/migration.rs index 35f3192..15f32c3 100644 --- a/src/migration.rs +++ b/src/migration.rs @@ -2,3 +2,4 @@ pub mod index; pub mod m20230617_195505_public_directory; pub mod m20230622_011005_did; pub mod m20230622_035815_pd_member; +pub mod m20230622_044839_pd_did_member; diff --git a/src/migration/index.rs b/src/migration/index.rs index f3acae2..c66a151 100644 --- a/src/migration/index.rs +++ b/src/migration/index.rs @@ -6,6 +6,7 @@ use crate::{ databases::pool::Db, migration::{ m20230617_195505_public_directory, m20230622_011005_did, m20230622_035815_pd_member, + m20230622_044839_pd_did_member, }, }; pub struct Migrator; @@ -17,6 +18,7 @@ impl MigratorTrait for Migrator { Box::new(m20230617_195505_public_directory::Migration), Box::new(m20230622_011005_did::Migration), Box::new(m20230622_035815_pd_member::Migration), + Box::new(m20230622_044839_pd_did_member::Migration), ] } } diff --git a/src/migration/m20230622_011005_did.rs b/src/migration/m20230622_011005_did.rs index 6075f65..5f1ba50 100644 --- a/src/migration/m20230622_011005_did.rs +++ b/src/migration/m20230622_011005_did.rs @@ -32,7 +32,7 @@ impl MigrationTrait for Migration { } #[derive(Iden)] -enum Did { +pub(crate) enum Did { Table, Id, UpperBlock, diff --git a/src/migration/m20230622_035815_pd_member.rs b/src/migration/m20230622_035815_pd_member.rs index fae3fd3..210a41f 100644 --- a/src/migration/m20230622_035815_pd_member.rs +++ b/src/migration/m20230622_035815_pd_member.rs @@ -52,7 +52,7 @@ impl MigrationTrait for Migration { } #[derive(Iden)] -enum PdMember { +pub(crate) enum PdMember { Table, Id, MemberId, diff --git a/src/migration/m20230622_044839_pd_did_member.rs b/src/migration/m20230622_044839_pd_did_member.rs new file mode 100644 index 0000000..4df72fe --- /dev/null +++ b/src/migration/m20230622_044839_pd_did_member.rs @@ -0,0 +1,64 @@ +use sea_orm_migration::prelude::*; + +use super::{m20230622_011005_did::Did, m20230622_035815_pd_member::PdMember}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(PdDidMember::Table) + .if_not_exists() + .col( + ColumnDef::new(PdDidMember::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(PdDidMember::DidId).uuid().not_null()) + .col(ColumnDef::new(PdDidMember::PdMemberId).uuid().not_null()) + .col( + ColumnDef::new(PdDidMember::BlockNumber) + .big_integer() + .not_null(), + ) + .foreign_key( + ForeignKey::create() + .name("did_id") + .from(PdDidMember::Table, PdDidMember::DidId) + .to(Did::Table, Did::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .foreign_key( + ForeignKey::create() + .name("pd_member_id") + .from(PdDidMember::Table, PdDidMember::PdMemberId) + .to(PdMember::Table, PdMember::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(PdDidMember::Table).to_owned()) + .await + } +} + +#[derive(Iden)] +enum PdDidMember { + Table, + Id, + DidId, + PdMemberId, + BlockNumber, +} From 90d7b9bc40c1ed533a3eccc40bd12368962d3488 Mon Sep 17 00:00:00 2001 From: eum602 Date: Thu, 22 Jun 2023 13:00:43 -0500 Subject: [PATCH 18/25] chore: add pd_member entity and services --- src/entities/entities.rs | 2 +- src/entities/pd_member.rs | 1 + src/entities/pd_member/select.rs | 38 +++++++++ src/migration/m20230622_035815_pd_member.rs | 7 ++ src/services.rs | 1 + src/services/pd_member.rs | 1 + src/services/pd_member/data_interface.rs | 85 +++++++++++++++++++++ src/services/pd_member/index.rs | 0 8 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/entities/pd_member/select.rs create mode 100644 src/services/pd_member.rs create mode 100644 src/services/pd_member/data_interface.rs create mode 100644 src/services/pd_member/index.rs diff --git a/src/entities/entities.rs b/src/entities/entities.rs index 545aac5..f0efcd1 100644 --- a/src/entities/entities.rs +++ b/src/entities/entities.rs @@ -1,4 +1,4 @@ pub use crate::entities::did::model::Entity as DidEntity; pub use crate::entities::pd_did_member::model::Entity as PdDidMemberEntity; -pub use crate::entities::pd_member::model::Entity as PdMember; +pub use crate::entities::pd_member::model::Entity as PdMemberEntity; pub use crate::entities::public_directory::model::Entity as PublicDirectoryEntity; diff --git a/src/entities/pd_member.rs b/src/entities/pd_member.rs index 65880be..46698dd 100644 --- a/src/entities/pd_member.rs +++ b/src/entities/pd_member.rs @@ -1 +1,2 @@ pub mod model; +pub mod select; diff --git a/src/entities/pd_member/select.rs b/src/entities/pd_member/select.rs new file mode 100644 index 0000000..4c7aa80 --- /dev/null +++ b/src/entities/pd_member/select.rs @@ -0,0 +1,38 @@ +use super::*; +use crate::entities::entities::PdMemberEntity; +use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::public_directory::model::Column as Pd; +use sea_orm::sea_query::extension::postgres::PgExpr; +use sea_orm::sea_query::Expr; +use sea_orm::sea_query::IntoCondition; +use sea_orm::{entity::*, query::*}; + +impl PdMemberEntity { + pub fn find_by_public_directory_id(public_directory_id: &str) -> Select { + Self::find().filter(model::Column::PubicDirectoryId.contains(public_directory_id)) + } + + pub fn find_pd_member( + member_id: &i64, + public_directory_contract_address: &str, + chain_id: &str, + ) -> Select { + let public_directory_contract_address = public_directory_contract_address.to_owned(); + let chain_id = chain_id.to_owned(); + Self::find() + .join_rev( + JoinType::InnerJoin, + PdMemberEntity::belongs_to(PublicDirectoryEntity) + .from(crate::entities::pd_member::model::Column::PubicDirectoryId) + .to(Pd::Id) + .on_condition(move |_left, right| { + Expr::col((right, Pd::ContractAddress)) + .contains(public_directory_contract_address.clone()) + .and(Pd::ChainId.contains(&chain_id)) + .into_condition() + }) + .into(), + ) + .filter(model::Column::MemberId.eq(*member_id)) + } +} diff --git a/src/migration/m20230622_035815_pd_member.rs b/src/migration/m20230622_035815_pd_member.rs index 210a41f..abff1b3 100644 --- a/src/migration/m20230622_035815_pd_member.rs +++ b/src/migration/m20230622_035815_pd_member.rs @@ -39,6 +39,13 @@ impl MigrationTrait for Migration { .on_delete(ForeignKeyAction::Cascade) .on_update(ForeignKeyAction::Cascade), ) + .index( + Index::create() + .name("member_id_public_directory_id") + .col(PdMember::MemberId) + .col(PdMember::PublicDirectoryId) + .unique(), + ) .to_owned(), ) .await diff --git a/src/services.rs b/src/services.rs index 4851f08..ae0729e 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1,4 +1,5 @@ pub mod certificate_service; +pub mod pd_member; pub mod public_directory; pub mod trusted_registry; pub mod web3; diff --git a/src/services/pd_member.rs b/src/services/pd_member.rs new file mode 100644 index 0000000..aa85626 --- /dev/null +++ b/src/services/pd_member.rs @@ -0,0 +1 @@ +pub mod data_interface; diff --git a/src/services/pd_member/data_interface.rs b/src/services/pd_member/data_interface.rs new file mode 100644 index 0000000..0328905 --- /dev/null +++ b/src/services/pd_member/data_interface.rs @@ -0,0 +1,85 @@ +use crate::entities::entities::PdMemberEntity; +use crate::entities::models::{PdMemberActiveModel, PdMemberModel}; +use crate::services::public_directory::index::PublicDirectoryService; +use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; +use uuid::Uuid; + +pub struct DataInterfaceService { + public_directory: PublicDirectoryService, +} + +impl DataInterfaceService { + pub fn new(public_directory: PublicDirectoryService) -> DataInterfaceService { + DataInterfaceService { public_directory } + } + pub async fn get_pd_member_from_database( + &self, + db: &DatabaseConnection, + member_id: &i64, + ) -> Result, sea_orm::DbErr> { + PdMemberEntity::find_pd_member( + member_id, + &self.public_directory.params.contract_address.to_string(), + &self.public_directory.params.chain_id, + ) + .one(db) + .await + } + + /// insert or update public directory member to database + pub async fn save_pd_member_to_database( + &self, + db: &DatabaseConnection, + member_id: &i64, + exp: &i64, + block_number: &i64, + ) -> anyhow::Result<()> { + match self.get_pd_member_from_database(db, member_id).await { + Ok(u) => match u { + Some(v) => { + let mut s: PdMemberActiveModel = v.into(); + s.exp = Set(*exp); + s.block_number = Set(*block_number); + match s.update(db).await { + Ok(_) => return Ok(()), + Err(err) => { + return Err(err.into()); + } + } + } + None => { + match self + .public_directory + .data_interface + .get_public_directory_from_database(db) + .await + { + Ok(wrapped) => match wrapped { + Some(pd) => { + let db_registry = PdMemberActiveModel { + id: Set(Uuid::new_v4()), + exp: Set(*exp), + member_id: Set(*member_id), + pubic_directory_id: Set(pd.id), + block_number: Set(*block_number), + }; + match db_registry.insert(db).await { + Ok(_) => return Ok(()), + Err(e) => { + return Err(e.into()); + } + } + } + None => { + panic!("Public directory with contract address {} and chainId {} not found in database", self.public_directory.params.contract_address, self.public_directory.params.chain_id); + } + }, + Err(e) => return Err(e.into()), + } + } + }, + Err(_) => {} + } + Ok(()) + } +} diff --git a/src/services/pd_member/index.rs b/src/services/pd_member/index.rs new file mode 100644 index 0000000..e69de29 From 02a84638517a30d0dae3265c1b77f300ee3a8676 Mon Sep 17 00:00:00 2001 From: eum602 Date: Thu, 22 Jun 2023 16:29:12 -0500 Subject: [PATCH 19/25] refactor: add core worker --- src/services/public_directory/index.rs | 287 +--------------- src/services/trusted_registry.rs | 1 + src/services/trusted_registry/core_worker.rs | 321 ++++++++++++++++++ .../trusted_registry/trusted_registry.rs | 12 +- 4 files changed, 331 insertions(+), 290 deletions(-) create mode 100644 src/services/trusted_registry/core_worker.rs diff --git a/src/services/public_directory/index.rs b/src/services/public_directory/index.rs index 78288aa..305b520 100644 --- a/src/services/public_directory/index.rs +++ b/src/services/public_directory/index.rs @@ -1,15 +1,4 @@ -use std::collections::HashMap; - -use log::{debug, info}; -use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; -use uuid::Uuid; - -use crate::services::{ - trusted_registry::trusted_registry::Contract, - web3::utils::{get_string_from_string_in_log, get_u64_from_log}, -}; - -use crate::entities::models::PublicDirectoryActiveModel; +use crate::services::trusted_registry::trusted_registry::Contract; use super::{contract_interface::ContractInterface, data_interface::DataInterfaceService}; @@ -36,278 +25,4 @@ impl PublicDirectoryService { data_interface: DataInterfaceService::new(params), }) } - - pub async fn exec_or_resume_scheduled_sweep( - &self, - db: &DatabaseConnection, - ) -> anyhow::Result<()> { - info!("excuting scheduled worker thread"); - match self - .data_interface - .get_public_directory_from_database(&db) - .await - { - Ok(v) => match v { - Some(v) => { - if v.upper_block == v.last_block_saved { - info!("All up to date in this scheduled task"); - return Ok(()); - } - - if v.upper_block >= v.last_processed_block - && v.last_processed_block > v.last_block_saved - { - info!("Found not finished job, resuming"); - match self - .contract_interface - .find_previous_block(&(v.last_processed_block as u64)) - .await - { - Ok(u) => { - if let Some(prev_to_last_processed_block) = u { - return self - .process_events_in_block_range( - prev_to_last_processed_block, - v.last_block_saved as u64, - ) - .await; - } - } - Err(e) => { - return Err(e); - } - } - } - info!("Starting scheduled job"); - return self - .process_events_in_block_range( - v.upper_block as u64, - v.last_block_saved as u64, - ) - .await; - } - None => { - debug!("None was found in the database"); - return Ok(()); - } - }, - Err(e) => { - return Err(e.into()); - } - } - } - pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { - match self.exec_or_resume_scheduled_sweep(db).await { - Ok(_v) => { - let contract_last_block: u64; - match self.contract_interface.get_last_block().await { - Ok(result) => { - if result == 0 { - info!("No events found in contract... skipping sweep"); - return Ok(()); - } - - contract_last_block = result; - } - Err(e) => { - return Err(e.into()); - } - } - // set upper block to contract last saved block - // set last processed block to upper block - match self - .data_interface - .get_public_directory_from_database(&db) - .await - { - Ok(v) => match v { - Some(m) => { - // verify whether insert is needed - if contract_last_block > 0 - && contract_last_block == m.upper_block as u64 - && contract_last_block == m.last_block_saved as u64 - { - info!("There are no changes in the contract .. skipping sweep"); - return Ok(()); - } - let mut s: PublicDirectoryActiveModel = m.into(); - s.upper_block = Set(contract_last_block as i64); - s.last_processed_block = Set(0); - match s.update(db).await { - Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, - Err(err) => { - return Err(err.into()); - } - } - } - None => { - info!("Initializing metadata for contract in database"); - let db_registry = PublicDirectoryActiveModel { - id: Set(Uuid::new_v4()), - contract_address: Set(self.params.contract_address.to_string()), - upper_block: Set(contract_last_block as i64), - last_processed_block: Set(0), - last_block_saved: Set(0), - chain_id: Set(self.params.chain_id.clone()), - }; - match db_registry.insert(db).await { - Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, - Err(e) => { - return Err(e.into()); - } - } - } - }, - Err(e) => { - return Err(e.into()); - } - } - } - Err(e) => { - return Err(e); - } - } - } - - pub async fn process_events_in_block_range( - &self, - contract_block: u64, - target_block: u64, - ) -> anyhow::Result<()> { - if contract_block > target_block { - info!( - "Starting sweep; from block {}, to target block {}", - &contract_block, &target_block - ); - match self.process_events_in_block(&contract_block).await { - Ok(_prev_block) => { - // TODO: update last block processed in database - // TODO: Get next block (moving backward) - // if prev_block <= target_block {} - // TODO: repeat the flow - } - Err(e) => { - return Err(e.into()); - } - } - return Ok(()); - } - if contract_block == target_block { - return Ok(()); - } - panic!("Unexpected values, last block saved on database:{}, is greater than passed contract block: {}", &target_block, &contract_block); - } - - pub async fn get_did_associated_map( - &self, - block: &u64, - ) -> anyhow::Result>> { - let did_associated_logs = self - .contract_interface - .get_events_in_block_by_method("DidAssociated", &block) - .await - .unwrap(); - let mut did_associated_map: HashMap> = HashMap::new(); - let _l = did_associated_logs - .into_iter() - .map(|did_associated_log| { - let did = get_string_from_string_in_log(&did_associated_log, "did"); - let member_id = get_u64_from_log(&did_associated_log, "memberId"); - match did_associated_map.get(&member_id) { - Some(f) => { - let mut _f = f.clone(); - _f.push(did); - did_associated_map.insert(member_id, _f); - } - None => { - let mut v = Vec::new(); - v.push(did); - did_associated_map.insert(member_id, v); - } - }; - }) - .collect::>(); - Ok(did_associated_map) - } - - //// Returns previous block - pub async fn process_events_in_block(&self, block: &u64) -> anyhow::Result { - let mut did_associated_map = match self.get_did_associated_map(&block).await { - Ok(v) => v, - Err(e) => { - return Err(e); - } - }; - let mut prev_block: u64 = 0; - match self - .contract_interface - .get_events_in_block_by_method("MemberChanged", &block) - .await - { - Ok(member_changed_logs) => { - let _ = member_changed_logs - .into_iter() - .map(|member_changed_log| { - let exp = get_u64_from_log(&member_changed_log, "exp"); - let iat = get_u64_from_log(&member_changed_log, "iat"); - let member_id = get_u64_from_log(&member_changed_log, "memberId"); - let did = get_string_from_string_in_log(&member_changed_log, "did"); - prev_block = get_u64_from_log(&member_changed_log, "prevBlock"); - let transaction_timestamp = - get_u64_from_log(&member_changed_log, "currentTimestap"); - if transaction_timestamp == iat { - info!("new member was added/updated {} {}", did, member_id); - // 1. remove existing did in did associated mapping - match did_associated_map.get_mut(&member_id) { - Some(v) => { - let pos = - v.into_iter().rposition(|e| e.to_string() == did).unwrap(); - v.remove(pos); - } - None => panic!( - "Expected value in didAssociated event but was not found {}", - did - ), - }; - // TODO: 2. save to database -> if there exist a registry in which the block_number is greater then skip otherwise update - } else if transaction_timestamp == exp { - // MemberChanged with currentTimestamp==exp -> remove the entity did and all its dids from the database - info!("a member was removed"); - } else { - panic!( - "Unexpected values for iat: {}, exp: {}, transaction timestamp: {}", - iat, exp, transaction_timestamp - ); - } - }) - .collect::>(); - } - Err(e) => { - return Err(e); - } - } - // DidAssociated && !Memberchanged -> just new Did associated to an existing member - let _ = did_associated_map - .into_iter() - .map(|_el| { - // TODO: find that member in database - // TODO: associate the new did with the db found member - }) - .collect::>(); - - // DidDisassociated -> remove just that did from database that did - match self - .contract_interface - .get_events_in_block_by_method("DidDisassociated", &block) - .await - { - Ok(_did_disassociated_logs) => { - // TODO: remove these dids from database - } - Err(e) => { - return Err(e); - } - } - Ok(prev_block) - } } diff --git a/src/services/trusted_registry.rs b/src/services/trusted_registry.rs index b1fddfb..8683008 100644 --- a/src/services/trusted_registry.rs +++ b/src/services/trusted_registry.rs @@ -1 +1,2 @@ +pub mod core_worker; pub mod trusted_registry; diff --git a/src/services/trusted_registry/core_worker.rs b/src/services/trusted_registry/core_worker.rs new file mode 100644 index 0000000..f4210b8 --- /dev/null +++ b/src/services/trusted_registry/core_worker.rs @@ -0,0 +1,321 @@ +use std::collections::HashMap; + +use log::{debug, info}; +use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; +use uuid::Uuid; + +use crate::services::{ + public_directory::index::PublicDirectoryService, + web3::utils::{get_string_from_string_in_log, get_u64_from_log}, +}; + +use crate::entities::models::PublicDirectoryActiveModel; + +pub struct CoreWorkerService { + pub public_directory_service: PublicDirectoryService, +} + +impl CoreWorkerService { + pub fn new(public_directory_service: PublicDirectoryService) -> CoreWorkerService { + CoreWorkerService { + public_directory_service, + } + } + + pub async fn exec_or_resume_scheduled_sweep( + &self, + db: &DatabaseConnection, + ) -> anyhow::Result<()> { + info!("excuting scheduled worker thread"); + match self + .public_directory_service + .data_interface + .get_public_directory_from_database(&db) + .await + { + Ok(v) => match v { + Some(v) => { + if v.upper_block == v.last_block_saved { + info!("All up to date in this scheduled task"); + return Ok(()); + } + + if v.upper_block >= v.last_processed_block + && v.last_processed_block > v.last_block_saved + { + info!("Found not finished job, resuming"); + match self + .public_directory_service + .contract_interface + .find_previous_block(&(v.last_processed_block as u64)) + .await + { + Ok(u) => { + if let Some(prev_to_last_processed_block) = u { + return self + .process_events_in_block_range( + prev_to_last_processed_block, + v.last_block_saved as u64, + ) + .await; + } + } + Err(e) => { + return Err(e); + } + } + } + info!("Starting scheduled job"); + return self + .process_events_in_block_range( + v.upper_block as u64, + v.last_block_saved as u64, + ) + .await; + } + None => { + debug!("None was found in the database"); + return Ok(()); + } + }, + Err(e) => { + return Err(e.into()); + } + } + } + pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { + match self.exec_or_resume_scheduled_sweep(db).await { + Ok(_v) => { + let contract_last_block: u64; + match self + .public_directory_service + .contract_interface + .get_last_block() + .await + { + Ok(result) => { + if result == 0 { + info!("No events found in contract... skipping sweep"); + return Ok(()); + } + + contract_last_block = result; + } + Err(e) => { + return Err(e.into()); + } + } + // set upper block to contract last saved block + // set last processed block to upper block + match self + .public_directory_service + .data_interface + .get_public_directory_from_database(&db) + .await + { + Ok(v) => match v { + Some(m) => { + // verify whether insert is needed + if contract_last_block > 0 + && contract_last_block == m.upper_block as u64 + && contract_last_block == m.last_block_saved as u64 + { + info!("There are no changes in the contract .. skipping sweep"); + return Ok(()); + } + let mut s: PublicDirectoryActiveModel = m.into(); + s.upper_block = Set(contract_last_block as i64); + s.last_processed_block = Set(0); + match s.update(db).await { + Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, + Err(err) => { + return Err(err.into()); + } + } + } + None => { + info!("Initializing metadata for contract in database"); + let db_registry = PublicDirectoryActiveModel { + id: Set(Uuid::new_v4()), + contract_address: Set(self + .public_directory_service + .params + .contract_address + .to_string()), + upper_block: Set(contract_last_block as i64), + last_processed_block: Set(0), + last_block_saved: Set(0), + chain_id: Set(self + .public_directory_service + .params + .chain_id + .clone()), + }; + match db_registry.insert(db).await { + Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, + Err(e) => { + return Err(e.into()); + } + } + } + }, + Err(e) => { + return Err(e.into()); + } + } + } + Err(e) => { + return Err(e); + } + } + } + + pub async fn process_events_in_block_range( + &self, + contract_block: u64, + target_block: u64, + ) -> anyhow::Result<()> { + if contract_block > target_block { + info!( + "Starting sweep; from block {}, to target block {}", + &contract_block, &target_block + ); + match self.process_events_in_block(&contract_block).await { + Ok(_prev_block) => { + // TODO: update last block processed in database + // TODO: Get next block (moving backward) + // if prev_block <= target_block {} + // TODO: repeat the flow + } + Err(e) => { + return Err(e.into()); + } + } + return Ok(()); + } + if contract_block == target_block { + return Ok(()); + } + panic!("Unexpected values, last block saved on database:{}, is greater than passed contract block: {}", &target_block, &contract_block); + } + + pub async fn get_did_associated_map( + &self, + block: &u64, + ) -> anyhow::Result>> { + let did_associated_logs = self + .public_directory_service + .contract_interface + .get_events_in_block_by_method("DidAssociated", &block) + .await + .unwrap(); + let mut did_associated_map: HashMap> = HashMap::new(); + let _l = did_associated_logs + .into_iter() + .map(|did_associated_log| { + let did = get_string_from_string_in_log(&did_associated_log, "did"); + let member_id = get_u64_from_log(&did_associated_log, "memberId"); + match did_associated_map.get(&member_id) { + Some(f) => { + let mut _f = f.clone(); + _f.push(did); + did_associated_map.insert(member_id, _f); + } + None => { + let mut v = Vec::new(); + v.push(did); + did_associated_map.insert(member_id, v); + } + }; + }) + .collect::>(); + Ok(did_associated_map) + } + + //// Returns previous block + pub async fn process_events_in_block(&self, block: &u64) -> anyhow::Result { + let mut did_associated_map = match self.get_did_associated_map(&block).await { + Ok(v) => v, + Err(e) => { + return Err(e); + } + }; + let mut prev_block: u64 = 0; + match self + .public_directory_service + .contract_interface + .get_events_in_block_by_method("MemberChanged", &block) + .await + { + Ok(member_changed_logs) => { + let _ = member_changed_logs + .into_iter() + .map(|member_changed_log| { + let exp = get_u64_from_log(&member_changed_log, "exp"); + let iat = get_u64_from_log(&member_changed_log, "iat"); + let member_id = get_u64_from_log(&member_changed_log, "memberId"); + let did = get_string_from_string_in_log(&member_changed_log, "did"); + prev_block = get_u64_from_log(&member_changed_log, "prevBlock"); + let transaction_timestamp = + get_u64_from_log(&member_changed_log, "currentTimestap"); + if transaction_timestamp == iat { + info!("new member was added/updated {} {}", did, member_id); + // 1. remove existing did in did associated mapping + match did_associated_map.get_mut(&member_id) { + Some(v) => { + let pos = + v.into_iter().rposition(|e| e.to_string() == did).unwrap(); + v.remove(pos); + } + None => panic!( + "Expected value in didAssociated event but was not found {}", + did + ), + }; + // TODO: 2. save to database -> if there exist a registry in which the block_number is greater then skip otherwise update + // let pd_member = + // "SAVE" to PdMember table + // "SAVE" to Did table + // "SAVE" to pd_did_member table + } else if transaction_timestamp == exp { + // MemberChanged with currentTimestamp==exp -> remove the entity did and all its dids from the database + info!("a member was removed"); + } else { + panic!( + "Unexpected values for iat: {}, exp: {}, transaction timestamp: {}", + iat, exp, transaction_timestamp + ); + } + }) + .collect::>(); + } + Err(e) => { + return Err(e); + } + } + // DidAssociated && !Memberchanged -> just new Did associated to an existing member + let _ = did_associated_map + .into_iter() + .map(|_el| { + // TODO: find that member in database + // TODO: associate the new did with the db found member + }) + .collect::>(); + + // DidDisassociated -> remove just that did from database that did + match self + .public_directory_service + .contract_interface + .get_events_in_block_by_method("DidDisassociated", &block) + .await + { + Ok(_did_disassociated_logs) => { + // TODO: remove these dids from database + } + Err(e) => { + return Err(e); + } + } + Ok(prev_block) + } +} diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs index 86e6d0f..e38bc66 100644 --- a/src/services/trusted_registry/trusted_registry.rs +++ b/src/services/trusted_registry/trusted_registry.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use web3::types::H160; use crate::{ - config::env_config::Config, services::public_directory::index::PublicDirectoryService, + config::env_config::Config, + services::{ + public_directory::index::PublicDirectoryService, + trusted_registry::core_worker::CoreWorkerService, + }, }; #[derive(Deserialize, Serialize, Debug, Clone)] @@ -31,16 +35,16 @@ impl TrustedRegistry { match Database::connect(Config::get_config().databases.dbconnection.url).await { Ok(c) => { info!("Successfully connected a database connection"); - let public_directory_service_instance: PublicDirectoryService; + let core_worker_service: CoreWorkerService; match PublicDirectoryService::new(self.public_directory.clone()).await { Ok(result) => { - public_directory_service_instance = result; + core_worker_service = CoreWorkerService::new(result); } Err(e) => { return Err(e); } } - match public_directory_service_instance.sweep(&c).await { + match core_worker_service.sweep(&c).await { Ok(_) => { // sweep chain of trust // read did registry changes From d28669db67a4b571db1b3de7b09e09be4454c6cc Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 23 Jun 2023 16:46:35 -0500 Subject: [PATCH 20/25] feat: add public directory sweep component --- src/entities/did/model.rs | 3 - src/entities/pd_did_member.rs | 1 + src/entities/pd_did_member/select.rs | 18 + src/entities/pd_member/model.rs | 2 +- src/entities/pd_member/select.rs | 14 +- src/migration/m20230622_011005_did.rs | 12 +- .../m20230622_044839_pd_did_member.rs | 7 + src/services.rs | 2 + src/services/did.rs | 2 + src/services/did/data_interface.rs | 39 ++ src/services/did/did_service.rs | 13 + src/services/pd_did_member.rs | 1 + src/services/pd_did_member/data_interface.rs | 131 +++++ src/services/pd_member/data_interface.rs | 129 +++-- src/services/public_directory.rs | 1 + .../public_directory/contract_interface.rs | 1 + .../public_directory/data_interface.rs | 94 ++++ .../public_directory_worker_service.rs | 481 ++++++++++++++++++ src/services/trusted_registry.rs | 1 - src/services/trusted_registry/core_worker.rs | 321 ------------ .../trusted_registry/trusted_registry.rs | 10 +- src/services/web3/event.rs | 1 + 22 files changed, 900 insertions(+), 384 deletions(-) create mode 100644 src/entities/pd_did_member/select.rs create mode 100644 src/services/did.rs create mode 100644 src/services/did/data_interface.rs create mode 100644 src/services/did/did_service.rs create mode 100644 src/services/pd_did_member.rs create mode 100644 src/services/pd_did_member/data_interface.rs create mode 100644 src/services/public_directory/public_directory_worker_service.rs delete mode 100644 src/services/trusted_registry/core_worker.rs diff --git a/src/entities/did/model.rs b/src/entities/did/model.rs index 07369bb..55e126e 100644 --- a/src/entities/did/model.rs +++ b/src/entities/did/model.rs @@ -10,9 +10,6 @@ pub struct Model { pub id: Uuid, #[sea_orm(column_type = "Text")] pub did: String, - pub upper_block: i64, - pub last_processed_block: i64, - pub last_block_saved: i64, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/entities/pd_did_member.rs b/src/entities/pd_did_member.rs index 65880be..46698dd 100644 --- a/src/entities/pd_did_member.rs +++ b/src/entities/pd_did_member.rs @@ -1 +1,2 @@ pub mod model; +pub mod select; diff --git a/src/entities/pd_did_member/select.rs b/src/entities/pd_did_member/select.rs new file mode 100644 index 0000000..da05989 --- /dev/null +++ b/src/entities/pd_did_member/select.rs @@ -0,0 +1,18 @@ +use super::*; +use crate::entities::entities::PdDidMemberEntity; +use sea_orm::{entity::*, query::*}; +use uuid::Uuid; + +impl PdDidMemberEntity { + pub fn find_pd_did_member(did_id: Uuid, pd_member_id: Uuid) -> Select { + Self::find().filter( + model::Column::DidId + .eq(did_id) + .and(model::Column::PdMemberId.eq(pd_member_id)), + ) + } + + pub fn find_by_pd_did_member_id(pd_did_member_id: &Uuid) -> Select { + Self::find().filter(model::Column::Id.eq(*pd_did_member_id)) + } +} diff --git a/src/entities/pd_member/model.rs b/src/entities/pd_member/model.rs index d43bdae..e70a9c8 100644 --- a/src/entities/pd_member/model.rs +++ b/src/entities/pd_member/model.rs @@ -10,7 +10,7 @@ pub struct Model { pub id: Uuid, pub member_id: i64, pub exp: i64, - pub pubic_directory_id: Uuid, + pub public_directory_id: Uuid, pub block_number: i64, } diff --git a/src/entities/pd_member/select.rs b/src/entities/pd_member/select.rs index 4c7aa80..3b33f64 100644 --- a/src/entities/pd_member/select.rs +++ b/src/entities/pd_member/select.rs @@ -2,14 +2,18 @@ use super::*; use crate::entities::entities::PdMemberEntity; use crate::entities::entities::PublicDirectoryEntity; use crate::entities::public_directory::model::Column as Pd; -use sea_orm::sea_query::extension::postgres::PgExpr; use sea_orm::sea_query::Expr; use sea_orm::sea_query::IntoCondition; use sea_orm::{entity::*, query::*}; +use uuid::Uuid; impl PdMemberEntity { pub fn find_by_public_directory_id(public_directory_id: &str) -> Select { - Self::find().filter(model::Column::PubicDirectoryId.contains(public_directory_id)) + Self::find().filter(model::Column::PublicDirectoryId.contains(public_directory_id)) + } + + pub fn find_by_pd_member_id(pd_member_id: &Uuid) -> Select { + Self::find().filter(model::Column::Id.eq(*pd_member_id)) } pub fn find_pd_member( @@ -20,14 +24,14 @@ impl PdMemberEntity { let public_directory_contract_address = public_directory_contract_address.to_owned(); let chain_id = chain_id.to_owned(); Self::find() - .join_rev( + .join( JoinType::InnerJoin, PdMemberEntity::belongs_to(PublicDirectoryEntity) - .from(crate::entities::pd_member::model::Column::PubicDirectoryId) + .from(crate::entities::pd_member::model::Column::PublicDirectoryId) .to(Pd::Id) .on_condition(move |_left, right| { Expr::col((right, Pd::ContractAddress)) - .contains(public_directory_contract_address.clone()) + .eq(public_directory_contract_address.clone()) .and(Pd::ChainId.contains(&chain_id)) .into_condition() }) diff --git a/src/migration/m20230622_011005_did.rs b/src/migration/m20230622_011005_did.rs index 5f1ba50..88e9139 100644 --- a/src/migration/m20230622_011005_did.rs +++ b/src/migration/m20230622_011005_did.rs @@ -12,13 +12,7 @@ impl MigrationTrait for Migration { .table(Did::Table) .if_not_exists() .col(ColumnDef::new(Did::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(Did::UpperBlock).big_integer().not_null()) - .col( - ColumnDef::new(Did::LastProcessedBlock) - .big_integer() - .not_null(), - ) - .col(ColumnDef::new(Did::LastBlockSaved).big_integer().not_null()) + .col(ColumnDef::new(Did::Did).string().not_null().unique_key()) .to_owned(), ) .await @@ -35,7 +29,5 @@ impl MigrationTrait for Migration { pub(crate) enum Did { Table, Id, - UpperBlock, - LastProcessedBlock, - LastBlockSaved, + Did, } diff --git a/src/migration/m20230622_044839_pd_did_member.rs b/src/migration/m20230622_044839_pd_did_member.rs index 4df72fe..79e4159 100644 --- a/src/migration/m20230622_044839_pd_did_member.rs +++ b/src/migration/m20230622_044839_pd_did_member.rs @@ -42,6 +42,13 @@ impl MigrationTrait for Migration { .on_delete(ForeignKeyAction::Cascade) .on_update(ForeignKeyAction::Cascade), ) + .index( + Index::create() + .name("pd_did_member_id") + .col(PdDidMember::PdMemberId) + .col(PdDidMember::DidId) + .unique(), + ) .to_owned(), ) .await diff --git a/src/services.rs b/src/services.rs index ae0729e..b1fbe7c 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1,4 +1,6 @@ pub mod certificate_service; +pub mod did; +pub mod pd_did_member; pub mod pd_member; pub mod public_directory; pub mod trusted_registry; diff --git a/src/services/did.rs b/src/services/did.rs new file mode 100644 index 0000000..5948491 --- /dev/null +++ b/src/services/did.rs @@ -0,0 +1,2 @@ +pub mod data_interface; +pub mod did_service; diff --git a/src/services/did/data_interface.rs b/src/services/did/data_interface.rs new file mode 100644 index 0000000..6909ca0 --- /dev/null +++ b/src/services/did/data_interface.rs @@ -0,0 +1,39 @@ +use crate::entities::entities::DidEntity; +use crate::entities::models::DidActiveModel; +use crate::entities::models::DidModel; +use sea_orm::ActiveModelTrait; +use sea_orm::DatabaseConnection; +use sea_orm::Set; +use uuid::Uuid; + +pub struct DidDataInterfaceService {} + +impl DidDataInterfaceService { + pub fn new() -> DidDataInterfaceService { + DidDataInterfaceService {} + } + pub async fn get_did_from_database( + &self, + db: &DatabaseConnection, + did: &str, + ) -> Result, sea_orm::DbErr> { + DidEntity::find_by_did(did).one(db).await + } + + pub async fn insert_did_to_database( + &self, + db: &DatabaseConnection, + did: &str, + ) -> anyhow::Result { + let db_registry = DidActiveModel { + id: Set(Uuid::new_v4()), + did: Set(did.to_owned()), + }; + match db_registry.insert(db).await { + Ok(res) => return Ok(res), + Err(e) => { + return Err(e.into()); + } + } + } +} diff --git a/src/services/did/did_service.rs b/src/services/did/did_service.rs new file mode 100644 index 0000000..f0ce86f --- /dev/null +++ b/src/services/did/did_service.rs @@ -0,0 +1,13 @@ +use super::data_interface::DidDataInterfaceService; + +pub struct DidService { + pub did_data_interface_service: DidDataInterfaceService, +} + +impl DidService { + pub fn new() -> DidService { + DidService { + did_data_interface_service: DidDataInterfaceService {}, + } + } +} diff --git a/src/services/pd_did_member.rs b/src/services/pd_did_member.rs new file mode 100644 index 0000000..aa85626 --- /dev/null +++ b/src/services/pd_did_member.rs @@ -0,0 +1 @@ +pub mod data_interface; diff --git a/src/services/pd_did_member/data_interface.rs b/src/services/pd_did_member/data_interface.rs new file mode 100644 index 0000000..10fd608 --- /dev/null +++ b/src/services/pd_did_member/data_interface.rs @@ -0,0 +1,131 @@ +use sea_orm::ActiveModelTrait; +use sea_orm::DatabaseConnection; +use sea_orm::Set; +use uuid::Uuid; + +use crate::services::did::did_service::DidService; +use crate::services::pd_member::data_interface::PdMemberDataInterfaceService; + +use crate::entities::entities::PdDidMemberEntity; +use crate::entities::models::PdDidMemberActiveModel; +use crate::entities::models::PdDidMemberModel; + +pub struct PdDidMemberDataInterfaceService { + pub pd_member_data_service: PdMemberDataInterfaceService, + pub did_service: DidService, +} + +impl PdDidMemberDataInterfaceService { + pub fn new( + pd_member_data_service: PdMemberDataInterfaceService, + did_service: DidService, + ) -> Self { + Self { + pd_member_data_service, + did_service, + } + } + + pub async fn get_pd_did_member( + &self, + db: &DatabaseConnection, + did: &str, + member_id: &i64, + ) -> Result, sea_orm::DbErr> { + match self + .did_service + .did_data_interface_service + .get_did_from_database(db, did) + .await + { + Ok(u) => match u { + Some(found_did) => match self + .pd_member_data_service + .get_pd_member_from_database(db, member_id) + .await + { + Ok(u) => match u { + Some(found_pd_member) => { + PdDidMemberEntity::find_pd_did_member(found_did.id, found_pd_member.id) + .one(db) + .await + } + None => return Ok(None), + }, + Err(e) => return Err(e.into()), + }, + None => return Ok(None), + }, + Err(e) => return Err(e.into()), + } + } + + pub async fn get_pd_did_member_by_ids( + &self, + db: &DatabaseConnection, + did_id: &Uuid, + pd_member_id: &Uuid, + ) -> Result, sea_orm::DbErr> { + PdDidMemberEntity::find_pd_did_member(*did_id, *pd_member_id) + .one(db) + .await + } + + pub async fn insert_did_pd_member( + &self, + db: &DatabaseConnection, + pd_member_id: &Uuid, + did_id: &Uuid, + block_number: &i64, + ) -> anyhow::Result { + let db_registry = PdDidMemberActiveModel { + id: Set(Uuid::new_v4()), + did_id: Set(*did_id), + pd_member_id: Set(*pd_member_id), + block_number: Set(*block_number), + }; + match db_registry.insert(db).await { + Ok(res) => return Ok(res), + Err(e) => { + return Err(e.into()); + } + } + } + + pub async fn get_pd_did_member_by_id( + &self, + db: &DatabaseConnection, + pd_did_member_id: &Uuid, + ) -> Result, sea_orm::DbErr> { + PdDidMemberEntity::find_by_pd_did_member_id(pd_did_member_id) + .one(db) + .await + } + + pub async fn update_pd_did_member( + &self, + db: &DatabaseConnection, + pd_did_member_id: Uuid, + block_number: &i64, + ) -> anyhow::Result { + match self.get_pd_did_member_by_id(db, &pd_did_member_id).await { + Ok(v) => match v { + Some(v) => { + let mut s: PdDidMemberActiveModel = v.into(); + s.block_number = Set(*block_number); + match s.update(db).await { + Ok(res) => return Ok(res), + Err(err) => { + return Err(err.into()); + } + } + } + None => panic!( + "Pd Did member with id {:?} does not exist", + pd_did_member_id + ), + }, + Err(e) => return Err(e.into()), + } + } +} diff --git a/src/services/pd_member/data_interface.rs b/src/services/pd_member/data_interface.rs index 0328905..c26037e 100644 --- a/src/services/pd_member/data_interface.rs +++ b/src/services/pd_member/data_interface.rs @@ -4,13 +4,15 @@ use crate::services::public_directory::index::PublicDirectoryService; use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; use uuid::Uuid; -pub struct DataInterfaceService { - public_directory: PublicDirectoryService, +pub struct PdMemberDataInterfaceService { + pub public_directory_service: PublicDirectoryService, } -impl DataInterfaceService { - pub fn new(public_directory: PublicDirectoryService) -> DataInterfaceService { - DataInterfaceService { public_directory } +impl PdMemberDataInterfaceService { + pub fn new(public_directory_service: PublicDirectoryService) -> PdMemberDataInterfaceService { + PdMemberDataInterfaceService { + public_directory_service, + } } pub async fn get_pd_member_from_database( &self, @@ -19,13 +21,91 @@ impl DataInterfaceService { ) -> Result, sea_orm::DbErr> { PdMemberEntity::find_pd_member( member_id, - &self.public_directory.params.contract_address.to_string(), - &self.public_directory.params.chain_id, + &self + .public_directory_service + .params + .contract_address + .to_string(), + &self.public_directory_service.params.chain_id, ) .one(db) .await } + pub async fn get_pd_member_by_id( + &self, + db: &DatabaseConnection, + pd_member_id: &Uuid, + ) -> Result, sea_orm::DbErr> { + PdMemberEntity::find_by_pd_member_id(pd_member_id) + .one(db) + .await + } + + /// insert public directory member to database + pub async fn insert_pd_member( + &self, + db: &DatabaseConnection, + member_id: &i64, + exp: &i64, + block_number: &i64, + ) -> anyhow::Result { + match self + .public_directory_service + .data_interface + .get_public_directory_from_database(db) + .await + { + Ok(wrapped) => match wrapped { + Some(pd) => { + let db_registry = PdMemberActiveModel { + id: Set(Uuid::new_v4()), + exp: Set(*exp), + member_id: Set(*member_id), + public_directory_id: Set(pd.id), + block_number: Set(*block_number), + }; + match db_registry.insert(db).await { + Ok(res) => return Ok(res), + Err(e) => { + return Err(e.into()); + } + } + } + None => { + panic!("Public directory with contract address {} and chainId {} not found in database", self.public_directory_service.params.contract_address, self.public_directory_service.params.chain_id); + } + }, + Err(e) => return Err(e.into()), + } + } + + /// insert or update public directory member to database + pub async fn update_pd_member( + &self, + db: &DatabaseConnection, + pd_member_id: Uuid, + exp: &i64, + block_number: &i64, + ) -> anyhow::Result { + match self.get_pd_member_by_id(db, &pd_member_id).await { + Ok(v) => match v { + Some(v) => { + let mut s: PdMemberActiveModel = v.into(); + s.exp = Set(*exp); + s.block_number = Set(*block_number); + match s.update(db).await { + Ok(res) => return Ok(res), + Err(err) => { + return Err(err.into()); + } + } + } + None => panic!("Pd member with id {:?} does not exist", pd_member_id), + }, + Err(e) => return Err(e.into()), + } + } /// insert or update public directory member to database pub async fn save_pd_member_to_database( &self, @@ -33,7 +113,7 @@ impl DataInterfaceService { member_id: &i64, exp: &i64, block_number: &i64, - ) -> anyhow::Result<()> { + ) -> anyhow::Result { match self.get_pd_member_from_database(db, member_id).await { Ok(u) => match u { Some(v) => { @@ -41,45 +121,18 @@ impl DataInterfaceService { s.exp = Set(*exp); s.block_number = Set(*block_number); match s.update(db).await { - Ok(_) => return Ok(()), + Ok(res) => return Ok(res), Err(err) => { return Err(err.into()); } } } None => { - match self - .public_directory - .data_interface - .get_public_directory_from_database(db) + self.insert_pd_member(db, member_id, exp, block_number) .await - { - Ok(wrapped) => match wrapped { - Some(pd) => { - let db_registry = PdMemberActiveModel { - id: Set(Uuid::new_v4()), - exp: Set(*exp), - member_id: Set(*member_id), - pubic_directory_id: Set(pd.id), - block_number: Set(*block_number), - }; - match db_registry.insert(db).await { - Ok(_) => return Ok(()), - Err(e) => { - return Err(e.into()); - } - } - } - None => { - panic!("Public directory with contract address {} and chainId {} not found in database", self.public_directory.params.contract_address, self.public_directory.params.chain_id); - } - }, - Err(e) => return Err(e.into()), - } } }, - Err(_) => {} + Err(e) => Err(e.into()), } - Ok(()) } } diff --git a/src/services/public_directory.rs b/src/services/public_directory.rs index a136cd0..e2fd8d1 100644 --- a/src/services/public_directory.rs +++ b/src/services/public_directory.rs @@ -1,3 +1,4 @@ pub mod contract_interface; pub mod data_interface; pub mod index; +pub mod public_directory_worker_service; diff --git a/src/services/public_directory/contract_interface.rs b/src/services/public_directory/contract_interface.rs index 0b7aa2d..5ea5a2f 100644 --- a/src/services/public_directory/contract_interface.rs +++ b/src/services/public_directory/contract_interface.rs @@ -15,6 +15,7 @@ use crate::{ use std::str; +#[derive(Debug, Clone)] pub struct ContractInterface { contract_instance: Contract, event_manager: EventManager, diff --git a/src/services/public_directory/data_interface.rs b/src/services/public_directory/data_interface.rs index dd3cea9..3f4ae9e 100644 --- a/src/services/public_directory/data_interface.rs +++ b/src/services/public_directory/data_interface.rs @@ -1,8 +1,13 @@ use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::models::PublicDirectoryActiveModel; use crate::entities::models::PublicDirectoryModel; use crate::services::trusted_registry::trusted_registry::Contract; +use sea_orm::ActiveModelTrait; use sea_orm::DatabaseConnection; +use sea_orm::Set; +use uuid::Uuid; +#[derive(Debug, Clone)] pub struct DataInterfaceService { params: Contract, } @@ -34,4 +39,93 @@ impl DataInterfaceService { } } } + + /// updates + pub async fn update( + &self, + db: &DatabaseConnection, + upper_block: Option, + last_processed_block: Option, + last_block_saved: Option, + ) -> anyhow::Result { + match self.get_public_directory_from_database(&db).await { + Ok(v) => match v { + Some(m) => { + let mut s: PublicDirectoryActiveModel = m.into(); + match upper_block { + Some(v) => { + s.upper_block = Set(v as i64); + } + _ => {} + } + + match last_processed_block { + Some(v) => { + s.last_processed_block = Set(v as i64); + } + _ => {} + } + + match last_block_saved { + Some(v) => { + s.last_block_saved = Set(v as i64); + } + _ => {} + } + match s.update(db).await { + Ok(v) => Ok(v), + Err(err) => { + return Err(err.into()); + } + } + } + None => panic!("Error, registry doesn't exist"), + }, + Err(e) => { + return Err(e.into()); + } + } + } + + /// updates or inserts + pub async fn save_contract_last_block( + &self, + db: &DatabaseConnection, + contract_last_block: &u64, + ) -> anyhow::Result { + match self.get_public_directory_from_database(&db).await { + Ok(v) => match v { + Some(m) => { + let mut s: PublicDirectoryActiveModel = m.into(); + s.upper_block = Set(*contract_last_block as i64); + s.last_processed_block = Set(0); + match s.update(db).await { + Ok(v) => Ok(v), + Err(err) => { + return Err(err.into()); + } + } + } + None => { + let db_registry = PublicDirectoryActiveModel { + id: Set(Uuid::new_v4()), + contract_address: Set(self.params.contract_address.to_string()), + upper_block: Set(*contract_last_block as i64), + last_processed_block: Set(0), + last_block_saved: Set(0), + chain_id: Set(self.params.chain_id.clone()), + }; + match db_registry.insert(db).await { + Ok(v) => Ok(v), + Err(e) => { + return Err(e.into()); + } + } + } + }, + Err(e) => { + return Err(e.into()); + } + } + } } diff --git a/src/services/public_directory/public_directory_worker_service.rs b/src/services/public_directory/public_directory_worker_service.rs new file mode 100644 index 0000000..be1a92a --- /dev/null +++ b/src/services/public_directory/public_directory_worker_service.rs @@ -0,0 +1,481 @@ +use std::collections::HashMap; + +use log::{debug, info}; +use sea_orm::DatabaseConnection; +use uuid::Uuid; +use web3::ethabi::Log; + +use crate::services::{ + did::did_service::DidService, + pd_did_member::data_interface::PdDidMemberDataInterfaceService, + pd_member::data_interface::PdMemberDataInterfaceService, + public_directory::index::PublicDirectoryService, + web3::utils::{get_string_from_string_in_log, get_u64_from_log}, +}; + +pub struct PublicDirectoryWorkerService { + pub pd_did_member_data_interface_service: PdDidMemberDataInterfaceService, +} + +impl PublicDirectoryWorkerService { + pub fn new(public_directory_service: PublicDirectoryService) -> PublicDirectoryWorkerService { + let pd_member_data_service = PdMemberDataInterfaceService::new(public_directory_service); + PublicDirectoryWorkerService { + pd_did_member_data_interface_service: PdDidMemberDataInterfaceService::new( + pd_member_data_service, + DidService::new(), + ), + } + } + + pub async fn exec_or_resume_scheduled_sweep( + &self, + db: &DatabaseConnection, + ) -> anyhow::Result<()> { + info!("excuting scheduled worker thread"); + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .data_interface + .get_public_directory_from_database(&db) + .await + { + Ok(v) => match v { + Some(v) => { + if v.upper_block == v.last_block_saved { + info!("All up to date in this scheduled task"); + return Ok(()); + } + + if v.upper_block >= v.last_processed_block + && v.last_processed_block > v.last_block_saved + { + info!("Found not finished job, resuming"); + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .contract_interface + .find_previous_block(&(v.last_processed_block as u64)) + .await + { + Ok(u) => { + if let Some(prev_to_last_processed_block) = u { + return self + .process_events_in_block_range( + db, + prev_to_last_processed_block, + v.last_block_saved as u64, + ) + .await; + } + } + Err(e) => { + return Err(e); + } + } + } + info!("Starting scheduled job"); + return self + .process_events_in_block_range( + db, + v.upper_block as u64, + v.last_block_saved as u64, + ) + .await; + } + None => { + debug!("None was found in the database"); + return Ok(()); + } + }, + Err(e) => { + return Err(e.into()); + } + } + } + + pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { + match self.exec_or_resume_scheduled_sweep(db).await { + Ok(_v) => { + let contract_last_block: u64; + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .contract_interface + .get_last_block() + .await + { + Ok(result) => { + if result == 0 { + info!("No events found in contract... skipping sweep"); + return Ok(()); + } + + contract_last_block = result; + } + Err(e) => { + return Err(e.into()); + } + } + // set upper block to contract last saved block + // set last processed block to zero value + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .data_interface + .get_public_directory_from_database(&db) + .await + { + Ok(v) => { + match v { + Some(m) => { + // verify whether insert is needed + if contract_last_block > 0 + && contract_last_block == m.upper_block as u64 + && contract_last_block == m.last_block_saved as u64 + { + info!("There are no changes in the contract. Last block saved is {}", contract_last_block); + return Ok(()); + } + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .data_interface + .update(db, Some(contract_last_block), Some(0), None) + .await + { + Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, + Err(err) => { + return Err(err.into()); + } + } + } + None => { + info!("Initializing metadata for contract in database"); + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .data_interface + .save_contract_last_block(db, &contract_last_block) + .await + { + Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, + Err(e) => { + return Err(e.into()); + } + } + } + } + } + Err(e) => { + return Err(e.into()); + } + } + } + Err(e) => { + return Err(e); + } + } + } + + pub async fn process_events_in_block_range( + &self, + db: &DatabaseConnection, + contract_block: u64, + target_block: u64, + ) -> anyhow::Result<()> { + let mut block_to_process = contract_block; + while block_to_process > target_block { + info!( + "Starting sweep; from block {}, to target block {}", + &block_to_process, &target_block + ); + match self + .public_directory_process_events_in_block(db, &block_to_process) + .await + { + Ok(prev_block) => { + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .data_interface + .update(db, None, Some(block_to_process), None) + .await + { + Ok(_) => {} + Err(e) => { + return Err(e.into()); + } + } + block_to_process = prev_block; + } + Err(e) => { + return Err(e.into()); + } + } + } + if block_to_process == target_block { + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .data_interface + .update(db, None, Some(0), Some(contract_block)) + .await + { + Ok(_) => { + info!("Reached target block {}", block_to_process); + Ok(()) + } + Err(e) => { + return Err(e.into()); + } + } + } else { + panic!("Unexpected values, last block saved on database:{}, is greater than passed contract block: {}", &target_block, &block_to_process); + } + } + + pub async fn get_did_associated_map( + &self, + block: &u64, + ) -> anyhow::Result>> { + let did_associated_logs = self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .contract_interface + .get_events_in_block_by_method("DidAssociated", &block) + .await + .unwrap(); + let mut did_associated_map: HashMap> = HashMap::new(); + let _l = did_associated_logs + .into_iter() + .map(|did_associated_log| { + let did = get_string_from_string_in_log(&did_associated_log, "did"); + let member_id = get_u64_from_log(&did_associated_log, "memberId"); + match did_associated_map.get(&member_id) { + Some(f) => { + let mut _f = f.clone(); + _f.push(did); + did_associated_map.insert(member_id, _f); + } + None => { + let mut v = Vec::new(); + v.push(did); + did_associated_map.insert(member_id, v); + } + }; + }) + .collect::>(); + Ok(did_associated_map) + } + + //// Returns previous block + pub async fn public_directory_process_events_in_block( + &self, + db: &DatabaseConnection, + block: &u64, + ) -> anyhow::Result { + // TODO: implement did associated cases + // let did_associated_map = match self.get_did_associated_map(&block).await { + // Ok(v) => v, + // Err(e) => { + // return Err(e); + // } + // }; + let prev_block: u64; + + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .public_directory_service + .contract_interface + .get_events_in_block_by_method("MemberChanged", &block) + .await + { + Ok(member_changed_logs) => { + match self + .process_member_changed_event(db, member_changed_logs, block) + .await + { + Err(e) => return Err(e.into()), + Ok(v) => { + prev_block = v; + } + } + } + Err(e) => { + return Err(e); + } + } + // TODO: implement did disassociated cases + // // DidAssociated && !Memberchanged -> just new Did associated to an existing member + // let _ = did_associated_map + // .into_iter() + // .map(|_el| { + // // TODO: find that member in database + // // TODO: associate the new did with the db found member + // }) + // .collect::>(); + + // // DidDisassociated -> remove just that did from database that did + // match self + // .public_directory_service + // .contract_interface + // .get_events_in_block_by_method("DidDisassociated", &block) + // .await + // { + // Ok(_did_disassociated_logs) => { + // // TODO: remove these dids from database + // } + // Err(e) => { + // return Err(e); + // } + // } + Ok(prev_block) + } + + pub async fn process_member_changed_event( + &self, + db: &DatabaseConnection, + member_changed_logs: Vec, + block: &u64, + ) -> anyhow::Result { + let mut prev_block: u64 = 0; + for member_changed_log in member_changed_logs { + let exp = get_u64_from_log(&member_changed_log, "exp"); + let iat = get_u64_from_log(&member_changed_log, "iat"); + let member_id = get_u64_from_log(&member_changed_log, "memberId"); + let did = get_string_from_string_in_log(&member_changed_log, "did"); + prev_block = get_u64_from_log(&member_changed_log, "prevBlock"); + let transaction_timestamp = get_u64_from_log(&member_changed_log, "currentTimestap"); + if transaction_timestamp == iat { + // issuance case scenario + info!("new member was added/updated {} {}", did, member_id); + let pd_member_id: Uuid; + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .get_pd_member_from_database(db, &(member_id as i64)) + .await + { + // "SAVE" to PdMember table + Ok(wrapped) => match wrapped { + Some(found_pd_member) => { + pd_member_id = found_pd_member.id; + if (found_pd_member.block_number as u64) < *block { + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .update_pd_member( + db, + found_pd_member.id, + &(exp as i64), + &(*block as i64), + ) + .await + { + Ok(_) => {} + Err(e) => return Err(e.into()), + } + } + } + None => { + match self + .pd_did_member_data_interface_service + .pd_member_data_service + .insert_pd_member( + db, + &(member_id as i64), + &(exp as i64), + &(*block as i64), + ) + .await + { + Ok(saved_pd_member) => pd_member_id = saved_pd_member.id, + Err(e) => return Err(e.into()), + } + } + }, + Err(e) => return Err(e.into()), + } + + // "SAVE" to Did table + let did_id: Uuid; + match self + .pd_did_member_data_interface_service + .did_service + .did_data_interface_service + .get_did_from_database(db, &did) + .await + { + Ok(v) => match v { + Some(existing_did) => { + did_id = existing_did.id; + } + None => { + match self + .pd_did_member_data_interface_service + .did_service + .did_data_interface_service + .insert_did_to_database(db, &did) + .await + { + Ok(v) => did_id = v.id, + Err(e) => return Err(e.into()), + } + } + }, + Err(e) => return Err(e.into()), + } + + // "SAVE" to pd_did_member table + match self + .pd_did_member_data_interface_service + .get_pd_did_member_by_ids(db, &did_id, &pd_member_id) + .await + { + Ok(v) => match v { + Some(pd_did_member_found) => { + if pd_did_member_found.block_number as u64 >= *block { + continue; + } + match self + .pd_did_member_data_interface_service + .update_pd_did_member(db, pd_member_id, &(*block as i64)) + .await + { + Ok(_) => {} + Err(e) => return Err(e.into()), + } + } + None => { + match self + .pd_did_member_data_interface_service + .insert_did_pd_member(db, &pd_member_id, &did_id, &(*block as i64)) + .await + { + Ok(_) => {} + Err(e) => return Err(e.into()), + } + } + }, + Err(e) => return Err(e.into()), + } + } else if transaction_timestamp == exp { + // revocation case scenario + // TODO: MemberChanged with currentTimestamp==exp -> remove the entity did and all its dids from the database + info!("a member was removed"); + } + } + Ok(prev_block) + } +} diff --git a/src/services/trusted_registry.rs b/src/services/trusted_registry.rs index 8683008..b1fddfb 100644 --- a/src/services/trusted_registry.rs +++ b/src/services/trusted_registry.rs @@ -1,2 +1 @@ -pub mod core_worker; pub mod trusted_registry; diff --git a/src/services/trusted_registry/core_worker.rs b/src/services/trusted_registry/core_worker.rs deleted file mode 100644 index f4210b8..0000000 --- a/src/services/trusted_registry/core_worker.rs +++ /dev/null @@ -1,321 +0,0 @@ -use std::collections::HashMap; - -use log::{debug, info}; -use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; -use uuid::Uuid; - -use crate::services::{ - public_directory::index::PublicDirectoryService, - web3::utils::{get_string_from_string_in_log, get_u64_from_log}, -}; - -use crate::entities::models::PublicDirectoryActiveModel; - -pub struct CoreWorkerService { - pub public_directory_service: PublicDirectoryService, -} - -impl CoreWorkerService { - pub fn new(public_directory_service: PublicDirectoryService) -> CoreWorkerService { - CoreWorkerService { - public_directory_service, - } - } - - pub async fn exec_or_resume_scheduled_sweep( - &self, - db: &DatabaseConnection, - ) -> anyhow::Result<()> { - info!("excuting scheduled worker thread"); - match self - .public_directory_service - .data_interface - .get_public_directory_from_database(&db) - .await - { - Ok(v) => match v { - Some(v) => { - if v.upper_block == v.last_block_saved { - info!("All up to date in this scheduled task"); - return Ok(()); - } - - if v.upper_block >= v.last_processed_block - && v.last_processed_block > v.last_block_saved - { - info!("Found not finished job, resuming"); - match self - .public_directory_service - .contract_interface - .find_previous_block(&(v.last_processed_block as u64)) - .await - { - Ok(u) => { - if let Some(prev_to_last_processed_block) = u { - return self - .process_events_in_block_range( - prev_to_last_processed_block, - v.last_block_saved as u64, - ) - .await; - } - } - Err(e) => { - return Err(e); - } - } - } - info!("Starting scheduled job"); - return self - .process_events_in_block_range( - v.upper_block as u64, - v.last_block_saved as u64, - ) - .await; - } - None => { - debug!("None was found in the database"); - return Ok(()); - } - }, - Err(e) => { - return Err(e.into()); - } - } - } - pub async fn sweep(&self, db: &DatabaseConnection) -> anyhow::Result<()> { - match self.exec_or_resume_scheduled_sweep(db).await { - Ok(_v) => { - let contract_last_block: u64; - match self - .public_directory_service - .contract_interface - .get_last_block() - .await - { - Ok(result) => { - if result == 0 { - info!("No events found in contract... skipping sweep"); - return Ok(()); - } - - contract_last_block = result; - } - Err(e) => { - return Err(e.into()); - } - } - // set upper block to contract last saved block - // set last processed block to upper block - match self - .public_directory_service - .data_interface - .get_public_directory_from_database(&db) - .await - { - Ok(v) => match v { - Some(m) => { - // verify whether insert is needed - if contract_last_block > 0 - && contract_last_block == m.upper_block as u64 - && contract_last_block == m.last_block_saved as u64 - { - info!("There are no changes in the contract .. skipping sweep"); - return Ok(()); - } - let mut s: PublicDirectoryActiveModel = m.into(); - s.upper_block = Set(contract_last_block as i64); - s.last_processed_block = Set(0); - match s.update(db).await { - Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, - Err(err) => { - return Err(err.into()); - } - } - } - None => { - info!("Initializing metadata for contract in database"); - let db_registry = PublicDirectoryActiveModel { - id: Set(Uuid::new_v4()), - contract_address: Set(self - .public_directory_service - .params - .contract_address - .to_string()), - upper_block: Set(contract_last_block as i64), - last_processed_block: Set(0), - last_block_saved: Set(0), - chain_id: Set(self - .public_directory_service - .params - .chain_id - .clone()), - }; - match db_registry.insert(db).await { - Ok(_) => self.exec_or_resume_scheduled_sweep(db).await, - Err(e) => { - return Err(e.into()); - } - } - } - }, - Err(e) => { - return Err(e.into()); - } - } - } - Err(e) => { - return Err(e); - } - } - } - - pub async fn process_events_in_block_range( - &self, - contract_block: u64, - target_block: u64, - ) -> anyhow::Result<()> { - if contract_block > target_block { - info!( - "Starting sweep; from block {}, to target block {}", - &contract_block, &target_block - ); - match self.process_events_in_block(&contract_block).await { - Ok(_prev_block) => { - // TODO: update last block processed in database - // TODO: Get next block (moving backward) - // if prev_block <= target_block {} - // TODO: repeat the flow - } - Err(e) => { - return Err(e.into()); - } - } - return Ok(()); - } - if contract_block == target_block { - return Ok(()); - } - panic!("Unexpected values, last block saved on database:{}, is greater than passed contract block: {}", &target_block, &contract_block); - } - - pub async fn get_did_associated_map( - &self, - block: &u64, - ) -> anyhow::Result>> { - let did_associated_logs = self - .public_directory_service - .contract_interface - .get_events_in_block_by_method("DidAssociated", &block) - .await - .unwrap(); - let mut did_associated_map: HashMap> = HashMap::new(); - let _l = did_associated_logs - .into_iter() - .map(|did_associated_log| { - let did = get_string_from_string_in_log(&did_associated_log, "did"); - let member_id = get_u64_from_log(&did_associated_log, "memberId"); - match did_associated_map.get(&member_id) { - Some(f) => { - let mut _f = f.clone(); - _f.push(did); - did_associated_map.insert(member_id, _f); - } - None => { - let mut v = Vec::new(); - v.push(did); - did_associated_map.insert(member_id, v); - } - }; - }) - .collect::>(); - Ok(did_associated_map) - } - - //// Returns previous block - pub async fn process_events_in_block(&self, block: &u64) -> anyhow::Result { - let mut did_associated_map = match self.get_did_associated_map(&block).await { - Ok(v) => v, - Err(e) => { - return Err(e); - } - }; - let mut prev_block: u64 = 0; - match self - .public_directory_service - .contract_interface - .get_events_in_block_by_method("MemberChanged", &block) - .await - { - Ok(member_changed_logs) => { - let _ = member_changed_logs - .into_iter() - .map(|member_changed_log| { - let exp = get_u64_from_log(&member_changed_log, "exp"); - let iat = get_u64_from_log(&member_changed_log, "iat"); - let member_id = get_u64_from_log(&member_changed_log, "memberId"); - let did = get_string_from_string_in_log(&member_changed_log, "did"); - prev_block = get_u64_from_log(&member_changed_log, "prevBlock"); - let transaction_timestamp = - get_u64_from_log(&member_changed_log, "currentTimestap"); - if transaction_timestamp == iat { - info!("new member was added/updated {} {}", did, member_id); - // 1. remove existing did in did associated mapping - match did_associated_map.get_mut(&member_id) { - Some(v) => { - let pos = - v.into_iter().rposition(|e| e.to_string() == did).unwrap(); - v.remove(pos); - } - None => panic!( - "Expected value in didAssociated event but was not found {}", - did - ), - }; - // TODO: 2. save to database -> if there exist a registry in which the block_number is greater then skip otherwise update - // let pd_member = - // "SAVE" to PdMember table - // "SAVE" to Did table - // "SAVE" to pd_did_member table - } else if transaction_timestamp == exp { - // MemberChanged with currentTimestamp==exp -> remove the entity did and all its dids from the database - info!("a member was removed"); - } else { - panic!( - "Unexpected values for iat: {}, exp: {}, transaction timestamp: {}", - iat, exp, transaction_timestamp - ); - } - }) - .collect::>(); - } - Err(e) => { - return Err(e); - } - } - // DidAssociated && !Memberchanged -> just new Did associated to an existing member - let _ = did_associated_map - .into_iter() - .map(|_el| { - // TODO: find that member in database - // TODO: associate the new did with the db found member - }) - .collect::>(); - - // DidDisassociated -> remove just that did from database that did - match self - .public_directory_service - .contract_interface - .get_events_in_block_by_method("DidDisassociated", &block) - .await - { - Ok(_did_disassociated_logs) => { - // TODO: remove these dids from database - } - Err(e) => { - return Err(e); - } - } - Ok(prev_block) - } -} diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs index e38bc66..dc9e72b 100644 --- a/src/services/trusted_registry/trusted_registry.rs +++ b/src/services/trusted_registry/trusted_registry.rs @@ -7,7 +7,7 @@ use crate::{ config::env_config::Config, services::{ public_directory::index::PublicDirectoryService, - trusted_registry::core_worker::CoreWorkerService, + public_directory::public_directory_worker_service::PublicDirectoryWorkerService, }, }; @@ -34,17 +34,17 @@ impl TrustedRegistry { ); match Database::connect(Config::get_config().databases.dbconnection.url).await { Ok(c) => { - info!("Successfully connected a database connection"); - let core_worker_service: CoreWorkerService; + info!("Established a database connection"); + let public_directory_worker_service: PublicDirectoryWorkerService; match PublicDirectoryService::new(self.public_directory.clone()).await { Ok(result) => { - core_worker_service = CoreWorkerService::new(result); + public_directory_worker_service = PublicDirectoryWorkerService::new(result); } Err(e) => { return Err(e); } } - match core_worker_service.sweep(&c).await { + match public_directory_worker_service.sweep(&c).await { Ok(_) => { // sweep chain of trust // read did registry changes diff --git a/src/services/web3/event.rs b/src/services/web3/event.rs index beabce4..1d4746b 100644 --- a/src/services/web3/event.rs +++ b/src/services/web3/event.rs @@ -10,6 +10,7 @@ use web3::{ Web3, }; +#[derive(Debug, Clone)] pub struct EventManager { abi: String, web3: Web3, From 1df3f28a06f6d86ac69339186554648a37f3a831 Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 23 Jun 2023 21:06:43 -0500 Subject: [PATCH 21/25] chore: add scafolding to sweep over dids --- src/entities.rs | 1 + src/entities/did/select.rs | 42 +++++++++++++++++ src/entities/entities.rs | 1 + src/entities/models.rs | 3 ++ src/entities/pd_did_member/select.rs | 31 +++++++++++- src/entities/public_key.rs | 2 + src/entities/public_key/model.rs | 19 ++++++++ src/entities/public_key/select.rs | 3 ++ src/migration.rs | 1 + src/migration/index.rs | 3 +- src/migration/m20230623_215702_public_key.rs | 47 +++++++++++++++++++ src/services/did.rs | 1 + src/services/did/data_interface.rs | 11 +++++ .../did/did_registry_worker_service.rs | 14 ++++++ src/services/pd_did_member/data_interface.rs | 11 +++++ .../trusted_registry/trusted_registry.rs | 35 +++++++++++--- 16 files changed, 216 insertions(+), 9 deletions(-) create mode 100644 src/entities/public_key.rs create mode 100644 src/entities/public_key/model.rs create mode 100644 src/entities/public_key/select.rs create mode 100644 src/migration/m20230623_215702_public_key.rs create mode 100644 src/services/did/did_registry_worker_service.rs diff --git a/src/entities.rs b/src/entities.rs index 72a4751..df4eb24 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -4,3 +4,4 @@ pub mod models; pub mod pd_did_member; pub mod pd_member; pub mod public_directory; +pub mod public_key; diff --git a/src/entities/did/select.rs b/src/entities/did/select.rs index b260b5c..451b9c0 100644 --- a/src/entities/did/select.rs +++ b/src/entities/did/select.rs @@ -1,9 +1,51 @@ use super::*; use crate::entities::entities::DidEntity; +use crate::entities::entities::PdDidMemberEntity; +use crate::entities::entities::PdMemberEntity; +use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::public_directory::model::Column as Pd; +use sea_orm::sea_query::Expr; +use sea_orm::sea_query::IntoCondition; +use sea_orm::sea_query::Query; use sea_orm::{entity::*, query::*}; impl DidEntity { pub fn find_by_did(did: &str) -> Select { Self::find().filter(model::Column::Did.contains(did)) } + + pub fn find_all(public_directory_contract_address: &str, chain_id: &str) -> Select { + let public_directory_contract_address = public_directory_contract_address.to_owned(); + let chain_id = chain_id.to_owned(); + Self::find().filter( + Condition::any().add( + model::Column::Id.in_subquery( + Query::select() + .column(crate::entities::pd_did_member::model::Column::DidId) + .from(PdDidMemberEntity) + .join( + JoinType::InnerJoin, + PdMemberEntity, + Expr::col(( + PdDidMemberEntity, + crate::entities::pd_did_member::model::Column::PdMemberId, + )) + .equals(( + PdMemberEntity, + crate::entities::pd_member::model::Column::Id, + )), + ) + .join( + JoinType::InnerJoin, + PublicDirectoryEntity, + Expr::col((PublicDirectoryEntity, Pd::ContractAddress)) + .eq(public_directory_contract_address.clone()) + .and(Pd::ChainId.contains(&chain_id)) + .into_condition(), + ) + .to_owned(), + ), + ), + ) + } } diff --git a/src/entities/entities.rs b/src/entities/entities.rs index f0efcd1..2ff891f 100644 --- a/src/entities/entities.rs +++ b/src/entities/entities.rs @@ -2,3 +2,4 @@ pub use crate::entities::did::model::Entity as DidEntity; pub use crate::entities::pd_did_member::model::Entity as PdDidMemberEntity; pub use crate::entities::pd_member::model::Entity as PdMemberEntity; pub use crate::entities::public_directory::model::Entity as PublicDirectoryEntity; +pub use crate::entities::public_key::model::Entity as PublicKeyEntity; diff --git a/src/entities/models.rs b/src/entities/models.rs index 4fcb73a..3aaeadb 100644 --- a/src/entities/models.rs +++ b/src/entities/models.rs @@ -9,3 +9,6 @@ pub use crate::entities::pd_member::model::Model as PdMemberModel; pub use crate::entities::pd_did_member::model::ActiveModel as PdDidMemberActiveModel; pub use crate::entities::pd_did_member::model::Model as PdDidMemberModel; + +pub use crate::entities::public_key::model::ActiveModel as PublicKeyActiveModel; +pub use crate::entities::public_key::model::Model as PublicKeyModel; diff --git a/src/entities/pd_did_member/select.rs b/src/entities/pd_did_member/select.rs index da05989..81670bb 100644 --- a/src/entities/pd_did_member/select.rs +++ b/src/entities/pd_did_member/select.rs @@ -1,5 +1,8 @@ use super::*; -use crate::entities::entities::PdDidMemberEntity; +use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::entities::{PdDidMemberEntity, PdMemberEntity}; +use crate::entities::public_directory::model::Column as Pd; +use sea_orm::sea_query::{Expr, IntoCondition}; use sea_orm::{entity::*, query::*}; use uuid::Uuid; @@ -15,4 +18,30 @@ impl PdDidMemberEntity { pub fn find_by_pd_did_member_id(pd_did_member_id: &Uuid) -> Select { Self::find().filter(model::Column::Id.eq(*pd_did_member_id)) } + + pub fn find_all(public_directory_contract_address: &str, chain_id: &str) -> Select { + let public_directory_contract_address = public_directory_contract_address.to_owned(); + let chain_id = chain_id.to_owned(); + Self::find() + .join( + JoinType::InnerJoin, + PdDidMemberEntity::belongs_to(PdMemberEntity) + .from(crate::entities::pd_did_member::model::Column::PdMemberId) + .to(crate::entities::pd_member::model::Column::Id) + .into(), + ) + .join( + JoinType::InnerJoin, + PdMemberEntity::belongs_to(PublicDirectoryEntity) + .from(crate::entities::pd_member::model::Column::PublicDirectoryId) + .to(Pd::Id) + .on_condition(move |_left, right| { + Expr::col((right, Pd::ContractAddress)) + .eq(public_directory_contract_address.clone()) + .and(Pd::ChainId.contains(&chain_id)) + .into_condition() + }) + .into(), + ) + } } diff --git a/src/entities/public_key.rs b/src/entities/public_key.rs new file mode 100644 index 0000000..46698dd --- /dev/null +++ b/src/entities/public_key.rs @@ -0,0 +1,2 @@ +pub mod model; +pub mod select; diff --git a/src/entities/public_key/model.rs b/src/entities/public_key/model.rs new file mode 100644 index 0000000..acd98b0 --- /dev/null +++ b/src/entities/public_key/model.rs @@ -0,0 +1,19 @@ +use rocket::serde::{Deserialize, Serialize}; +use sea_orm::entity::prelude::*; +use uuid::Uuid; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] +#[serde(crate = "rocket::serde")] +#[sea_orm(table_name = "public_key")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + pub did_id: Uuid, + pub block_number: i64, + pub pem_key: Vec, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entities/public_key/select.rs b/src/entities/public_key/select.rs new file mode 100644 index 0000000..c0044b6 --- /dev/null +++ b/src/entities/public_key/select.rs @@ -0,0 +1,3 @@ +use crate::entities::entities::PublicKeyEntity; + +impl PublicKeyEntity {} diff --git a/src/migration.rs b/src/migration.rs index 15f32c3..d418628 100644 --- a/src/migration.rs +++ b/src/migration.rs @@ -3,3 +3,4 @@ pub mod m20230617_195505_public_directory; pub mod m20230622_011005_did; pub mod m20230622_035815_pd_member; pub mod m20230622_044839_pd_did_member; +pub mod m20230623_215702_public_key; diff --git a/src/migration/index.rs b/src/migration/index.rs index c66a151..896f759 100644 --- a/src/migration/index.rs +++ b/src/migration/index.rs @@ -6,7 +6,7 @@ use crate::{ databases::pool::Db, migration::{ m20230617_195505_public_directory, m20230622_011005_did, m20230622_035815_pd_member, - m20230622_044839_pd_did_member, + m20230622_044839_pd_did_member, m20230623_215702_public_key, }, }; pub struct Migrator; @@ -19,6 +19,7 @@ impl MigratorTrait for Migrator { Box::new(m20230622_011005_did::Migration), Box::new(m20230622_035815_pd_member::Migration), Box::new(m20230622_044839_pd_did_member::Migration), + Box::new(m20230623_215702_public_key::Migration), ] } } diff --git a/src/migration/m20230623_215702_public_key.rs b/src/migration/m20230623_215702_public_key.rs new file mode 100644 index 0000000..78cb807 --- /dev/null +++ b/src/migration/m20230623_215702_public_key.rs @@ -0,0 +1,47 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(PublicKey::Table) + .if_not_exists() + .col( + ColumnDef::new(PublicKey::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(PublicKey::DidId).uuid().not_null()) + .col( + ColumnDef::new(PublicKey::BlockNumber) + .big_integer() + .not_null(), + ) + .col(ColumnDef::new(PublicKey::PemKey).binary().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(PublicKey::Table).to_owned()) + .await + } +} + +/// Learn more at https://docs.rs/sea-query#iden +#[derive(Iden)] +enum PublicKey { + Table, + Id, + DidId, + BlockNumber, + PemKey, +} diff --git a/src/services/did.rs b/src/services/did.rs index 5948491..5bebdd4 100644 --- a/src/services/did.rs +++ b/src/services/did.rs @@ -1,2 +1,3 @@ pub mod data_interface; +pub mod did_registry_worker_service; pub mod did_service; diff --git a/src/services/did/data_interface.rs b/src/services/did/data_interface.rs index 6909ca0..16d4177 100644 --- a/src/services/did/data_interface.rs +++ b/src/services/did/data_interface.rs @@ -36,4 +36,15 @@ impl DidDataInterfaceService { } } } + + pub async fn find_all( + &self, + db: &DatabaseConnection, + public_directory_contract_address: &str, + chain_id: &str, + ) -> Result, sea_orm::DbErr> { + DidEntity::find_all(public_directory_contract_address, chain_id) + .all(db) + .await + } } diff --git a/src/services/did/did_registry_worker_service.rs b/src/services/did/did_registry_worker_service.rs new file mode 100644 index 0000000..26259d2 --- /dev/null +++ b/src/services/did/did_registry_worker_service.rs @@ -0,0 +1,14 @@ +use sea_orm::DatabaseConnection; +use uuid::Uuid; + +pub struct DidRegistryWorkerService {} + +impl DidRegistryWorkerService { + pub fn new() -> Self { + Self {} + } + pub async fn sweep(&self, _db: &DatabaseConnection, _did_id: &Uuid) -> anyhow::Result<()> { + info!("DidRegistryWorkerService sweep"); + Ok(()) + } +} diff --git a/src/services/pd_did_member/data_interface.rs b/src/services/pd_did_member/data_interface.rs index 10fd608..bbccccf 100644 --- a/src/services/pd_did_member/data_interface.rs +++ b/src/services/pd_did_member/data_interface.rs @@ -26,6 +26,17 @@ impl PdDidMemberDataInterfaceService { } } + pub async fn find_all( + &self, + db: &DatabaseConnection, + public_directory_contract_address: &str, + chain_id: &str, + ) -> Result, sea_orm::DbErr> { + PdDidMemberEntity::find_all(public_directory_contract_address, chain_id) + .all(db) + .await + } + pub async fn get_pd_did_member( &self, db: &DatabaseConnection, diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs index dc9e72b..e052b2c 100644 --- a/src/services/trusted_registry/trusted_registry.rs +++ b/src/services/trusted_registry/trusted_registry.rs @@ -6,6 +6,7 @@ use web3::types::H160; use crate::{ config::env_config::Config, services::{ + did::did_registry_worker_service::DidRegistryWorkerService, did::did_service::DidService, public_directory::index::PublicDirectoryService, public_directory::public_directory_worker_service::PublicDirectoryWorkerService, }, @@ -33,7 +34,7 @@ impl TrustedRegistry { self.public_directory, self.chain_of_trust ); match Database::connect(Config::get_config().databases.dbconnection.url).await { - Ok(c) => { + Ok(db) => { info!("Established a database connection"); let public_directory_worker_service: PublicDirectoryWorkerService; match PublicDirectoryService::new(self.public_directory.clone()).await { @@ -44,17 +45,37 @@ impl TrustedRegistry { return Err(e); } } - match public_directory_worker_service.sweep(&c).await { - Ok(_) => { - // sweep chain of trust - // read did registry changes - } + match public_directory_worker_service.sweep(&db).await { + Ok(_) => {} Err(e) => { error!("There was an error while trying to retrieve public directory last block saved ---> {:?}", e); return Err(e.into()); } } - // sweep to get members in the public directory and for each save it to the database + // seep cot + // sweep dids that matches with pulbic directory + // TODO: match them with Chain Of Trust also + let did_service = DidService::new(); + let did_registry_worker_service = DidRegistryWorkerService::new(); + match did_service + .did_data_interface_service + .find_all( + &db, + &self.public_directory.contract_address.to_string(), + &self.public_directory.chain_id, + ) + .await + { + Ok(dids) => { + for did in dids { + match did_registry_worker_service.sweep(&db, &did.id).await { + Ok(_) => {} + Err(e) => panic!("{}", e), + } + } + } + Err(e) => return Err(e.into()), + } Ok(()) } Err(e) => { From d40929a3fcb8fc8881c829d0d41b6365a8c3e40d Mon Sep 17 00:00:00 2001 From: eum602 Date: Sun, 25 Jun 2023 14:27:21 -0500 Subject: [PATCH 22/25] feat: add component to sweep dids according to a configured Public Key directory (smart contract) --- Cargo.lock | 101 ++- Cargo.toml | 2 + src/entities/did/model.rs | 3 + src/entities/public_key/model.rs | 4 + src/entities/public_key/select.rs | 22 +- src/jobs/trusted_registries.rs | 4 +- src/logger_config.rs | 18 +- src/migration/m20230622_011005_did.rs | 10 + src/migration/m20230623_215702_public_key.rs | 18 +- src/services.rs | 1 + src/services/did.rs | 3 +- src/services/did/abi.json | 779 ++++++++++++++++++ src/services/did/contract_interface.rs | 135 +++ src/services/did/data_interface.rs | 79 +- .../did/did_registry_worker_service.rs | 393 ++++++++- src/services/did/did_service.rs | 13 - src/services/did/index.rs | 113 +++ src/services/pd_did_member/data_interface.rs | 16 +- .../public_directory_worker_service.rs | 31 +- src/services/public_key.rs | 1 + src/services/public_key/data_interface.rs | 105 +++ .../trusted_registry/trusted_registry.rs | 35 +- src/services/web3/utils.rs | 32 +- src/utils/utils.rs | 20 + 24 files changed, 1841 insertions(+), 97 deletions(-) create mode 100644 src/services/did/abi.json create mode 100644 src/services/did/contract_interface.rs delete mode 100644 src/services/did/did_service.rs create mode 100644 src/services/did/index.rs create mode 100644 src/services/public_key.rs create mode 100644 src/services/public_key/data_interface.rs diff --git a/Cargo.lock b/Cargo.lock index 80ff0f4..9cd9a17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -291,6 +291,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -774,7 +783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -809,6 +818,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "1.1.0" @@ -927,6 +942,12 @@ dependencies = [ "slab", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "generator" version = "0.7.4" @@ -1379,6 +1400,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "bs58", "chrono", "clap", "env_logger", @@ -1389,6 +1411,7 @@ dependencies = [ "rocket", "rocket_cors", "rocket_okapi", + "rust-crypto", "sea-orm", "sea-orm-migration", "sea-orm-rocket", @@ -1989,6 +2012,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.8.5" @@ -1997,7 +2043,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -2007,9 +2053,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", ] +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.6.4" @@ -2019,6 +2080,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -2223,7 +2293,7 @@ dependencies = [ "num_cpus", "parking_lot 0.12.1", "pin-project-lite", - "rand", + "rand 0.8.5", "ref-cast", "rocket_codegen", "rocket_http", @@ -2325,6 +2395,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "time 0.1.45", +] + [[package]] name = "rust_decimal" version = "1.30.0" @@ -2337,7 +2420,7 @@ dependencies = [ "byteorder", "bytes", "num-traits", - "rand", + "rand 0.8.5", "rkyv", "serde", "serde_json", @@ -2349,6 +2432,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + [[package]] name = "rustc_version" version = "0.4.0" @@ -2915,7 +3004,7 @@ dependencies = [ "once_cell", "paste", "percent-encoding", - "rand", + "rand 0.8.5", "rust_decimal", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 54ef67c..4e10587 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,8 @@ serde_json = "1.0.39" sha3 = "0.10" sea-orm = { version = "0.11.3", features = ["runtime-tokio-native-tls", "sqlx-postgres"]} hex = "0.4" +bs58 = "0.5.0" +rust-crypto = "0.2" [dependencies.sea-orm-rocket] version = "0.5.2" diff --git a/src/entities/did/model.rs b/src/entities/did/model.rs index 55e126e..07369bb 100644 --- a/src/entities/did/model.rs +++ b/src/entities/did/model.rs @@ -10,6 +10,9 @@ pub struct Model { pub id: Uuid, #[sea_orm(column_type = "Text")] pub did: String, + pub upper_block: i64, + pub last_processed_block: i64, + pub last_block_saved: i64, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/entities/public_key/model.rs b/src/entities/public_key/model.rs index acd98b0..06b0542 100644 --- a/src/entities/public_key/model.rs +++ b/src/entities/public_key/model.rs @@ -11,6 +11,10 @@ pub struct Model { pub did_id: Uuid, pub block_number: i64, pub pem_key: Vec, + #[sea_orm(column_type = "Text")] + pub content_hash: String, + pub exp: i64, + pub is_compromised: bool, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/entities/public_key/select.rs b/src/entities/public_key/select.rs index c0044b6..0b3df77 100644 --- a/src/entities/public_key/select.rs +++ b/src/entities/public_key/select.rs @@ -1,3 +1,23 @@ +use sea_orm::ColumnTrait; +use sea_orm::EntityTrait; +use sea_orm::QueryFilter; +use sea_orm::Select; +use uuid::Uuid; + use crate::entities::entities::PublicKeyEntity; -impl PublicKeyEntity {} +use super::model; + +impl PublicKeyEntity { + pub fn find_by_hash_and_did_id(content_hash: &str, did_id: &Uuid) -> Select { + Self::find().filter( + model::Column::ContentHash + .contains(content_hash) + .and(model::Column::DidId.eq(*did_id)), + ) + } + + pub fn find_by_id(id: &Uuid) -> Select { + Self::find().filter(model::Column::Id.eq(*id)) + } +} diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs index 14797d3..f62d623 100644 --- a/src/jobs/trusted_registries.rs +++ b/src/jobs/trusted_registries.rs @@ -29,7 +29,7 @@ impl TrustedRegistries { fn set_trusted_registries(&mut self) -> () { let _raw_trusted_registries = self.get_trusted_registries(); - let pd_str = "BD74DE9059CD63AC60c3AaC25c92a798be8D18b9"; // "e647e8e076cffA10425c0C49aAaC1036a3b2ddB5"; // TODO: factor better error + let pd_str = "609e1d1364d607b027E577e10AD97c571b9518c1"; //"BD74DE9059CD63AC60c3AaC25c92a798be8D18b9"; // "e647e8e076cffA10425c0C49aAaC1036a3b2ddB5"; // TODO: factor better error let public_directory_address = <[u8; 20]>::from_hex(pd_str).expect("Invalid public directory contract address"); let cot_str = "EBB6854aa875867f684dd1d2338eC20908039c67"; @@ -60,7 +60,7 @@ impl TrustedRegistries { .map(|i| { self.registries[i].start_up = (i as u64) * 100; self.registries[i].period_seconds = 2000; - self.registries[i].retry_period = 30; + self.registries[i].retry_period = 10; }) .collect::>(); } diff --git a/src/logger_config.rs b/src/logger_config.rs index 5eec09c..5dbcde4 100644 --- a/src/logger_config.rs +++ b/src/logger_config.rs @@ -4,10 +4,11 @@ use std::thread; use chrono::prelude::*; use env_logger::fmt::Formatter; use env_logger::Builder; -use log::{LevelFilter, Record}; +use env_logger::Env; +use log::Record; pub fn setup_logger(log_thread: bool, rust_log: Option<&str>) { - let output_format = move |formatter: &mut Formatter, record: &Record| { + let _output_format = move |formatter: &mut Formatter, record: &Record| { let thread_name = if log_thread { format!("(t: {}) ", thread::current().name().unwrap_or("unknown")) } else { @@ -27,17 +28,8 @@ pub fn setup_logger(log_thread: bool, rust_log: Option<&str>) { ) }; - let mut builder = Builder::new(); - builder - .format(output_format) - .filter(None, LevelFilter::Info); - + let mut builder = Builder::from_env(Env::default().default_filter_or("info")); + // builder.format(output_format); // avoiding custom formatting rust_log.map(|conf| builder.parse_filters(conf)); - builder.init(); } - -#[allow(dead_code)] -fn main() { - println!("This is not an example"); -} diff --git a/src/migration/m20230622_011005_did.rs b/src/migration/m20230622_011005_did.rs index 88e9139..f5201b2 100644 --- a/src/migration/m20230622_011005_did.rs +++ b/src/migration/m20230622_011005_did.rs @@ -13,6 +13,13 @@ impl MigrationTrait for Migration { .if_not_exists() .col(ColumnDef::new(Did::Id).uuid().not_null().primary_key()) .col(ColumnDef::new(Did::Did).string().not_null().unique_key()) + .col(ColumnDef::new(Did::UpperBlock).big_integer().not_null()) + .col( + ColumnDef::new(Did::LastProcessedBlock) + .big_integer() + .not_null(), + ) + .col(ColumnDef::new(Did::LastBlockSaved).big_integer().not_null()) .to_owned(), ) .await @@ -30,4 +37,7 @@ pub(crate) enum Did { Table, Id, Did, + UpperBlock, + LastProcessedBlock, + LastBlockSaved, } diff --git a/src/migration/m20230623_215702_public_key.rs b/src/migration/m20230623_215702_public_key.rs index 78cb807..5132574 100644 --- a/src/migration/m20230623_215702_public_key.rs +++ b/src/migration/m20230623_215702_public_key.rs @@ -24,6 +24,20 @@ impl MigrationTrait for Migration { .not_null(), ) .col(ColumnDef::new(PublicKey::PemKey).binary().not_null()) + .col(ColumnDef::new(PublicKey::ContentHash).string().not_null()) + .col(ColumnDef::new(PublicKey::Exp).big_integer().not_null()) + .col( + ColumnDef::new(PublicKey::IsCompromised) + .boolean() + .default(false), + ) + .index( + Index::create() + .name("content_hash_did_id") + .col(PublicKey::ContentHash) + .col(PublicKey::DidId) + .unique(), + ) .to_owned(), ) .await @@ -36,7 +50,6 @@ impl MigrationTrait for Migration { } } -/// Learn more at https://docs.rs/sea-query#iden #[derive(Iden)] enum PublicKey { Table, @@ -44,4 +57,7 @@ enum PublicKey { DidId, BlockNumber, PemKey, + ContentHash, + Exp, + IsCompromised, } diff --git a/src/services.rs b/src/services.rs index b1fbe7c..cce9d27 100644 --- a/src/services.rs +++ b/src/services.rs @@ -3,5 +3,6 @@ pub mod did; pub mod pd_did_member; pub mod pd_member; pub mod public_directory; +pub mod public_key; pub mod trusted_registry; pub mod web3; diff --git a/src/services/did.rs b/src/services/did.rs index 5bebdd4..b29f613 100644 --- a/src/services/did.rs +++ b/src/services/did.rs @@ -1,3 +1,4 @@ +pub mod contract_interface; pub mod data_interface; pub mod did_registry_worker_service; -pub mod did_service; +pub mod index; diff --git a/src/services/did/abi.json b/src/services/did/abi.json new file mode 100644 index 0000000..761aacf --- /dev/null +++ b/src/services/did/abi.json @@ -0,0 +1,779 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minKeyRotationTime", + "type": "uint256" + }, + { + "internalType": "address", + "name": "trustedForwarderAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validTo", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "changeTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousChange", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "compromised", + "type": "bool" + } + ], + "name": "DIDAttributeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousChange", + "type": "uint256" + } + ], + "name": "DIDControllerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "delegateType", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validTo", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "changeTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousChange", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "reason", + "type": "bool" + } + ], + "name": "DIDDelegateChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "addController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "delegateType", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "validity", + "type": "uint256" + } + ], + "name": "addDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "delegateType", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "validity", + "type": "uint256" + } + ], + "name": "addDelegateSigned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "attributes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "address", + "name": "newController", + "type": "address" + } + ], + "name": "changeController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "newController", + "type": "address" + } + ], + "name": "changeControllerSigned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "changed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "controllers", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + } + ], + "name": "disableKeyRotation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "uint256", + "name": "keyRotationTime", + "type": "uint256" + } + ], + "name": "enableKeyRotation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "attributeNameHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "attributeValueHash", + "type": "bytes32" + } + ], + "name": "expirationAttribute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "getControllers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + } + ], + "name": "identityController", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "removeController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "revokeDeltaTime", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "compromised", + "type": "bool" + } + ], + "name": "revokeAttribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "revokeDeltaTime", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "compromised", + "type": "bool" + } + ], + "name": "revokeAttributeSigned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "delegateType", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "revokeDeltaTime", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "compromised", + "type": "bool" + } + ], + "name": "revokeDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "delegateType", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "revokeDeltaTime", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "compromised", + "type": "bool" + } + ], + "name": "revokeDelegateSigned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validity", + "type": "uint256" + } + ], + "name": "setAttribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validity", + "type": "uint256" + } + ], + "name": "setAttributeSigned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "identity", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "delegateType", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + } + ], + "name": "validDelegate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/services/did/contract_interface.rs b/src/services/did/contract_interface.rs new file mode 100644 index 0000000..a83392b --- /dev/null +++ b/src/services/did/contract_interface.rs @@ -0,0 +1,135 @@ +use web3::{ + contract::{Contract, Options}, + ethabi::Log, + transports::Http, + types::{H160, U256}, +}; + +use crate::{ + config::env_config::Config, + services::{ + trusted_registry::trusted_registry::Contract as C, + web3::{event::EventManager, utils::get_u64_from_log}, + }, +}; + +use std::str; + +#[derive(Debug, Clone)] +pub struct ContractInterface { + contract_instance: Contract, + event_manager: EventManager, +} + +impl ContractInterface { + /// param {chain_id} -> the chain id that corresponds to the network where the Did Registry lives + /// param { contract_address } -> Did Registry address + pub async fn new(params: C) -> anyhow::Result { + let rpc_url = Config::get_provider(params.chain_id.clone()); + let http = web3::transports::Http::new(&rpc_url)?; + let web3 = web3::Web3::new(http); + let abi = include_bytes!("./abi.json"); + let contract_instance = + Contract::from_json(web3.eth(), params.contract_address.clone(), abi)?; + let str_abi = match str::from_utf8(abi) { + Ok(s) => s, + Err(e) => { + return Err(e.into()); + } + }; + let event_manager = EventManager::new(str_abi.to_owned(), params)?; + Ok(ContractInterface { + contract_instance, + event_manager, + }) + } + pub async fn get_last_block(&self, identity_address: H160) -> anyhow::Result { + let result = self.contract_instance.query( + "changed", + identity_address, + None, + Options::default(), + None, + ); + let identity_last_block: U256 = result.await?; + Ok(identity_last_block.as_u64()) + } + + /// Returns block previous prior to the last block saved param on the smart contract + pub async fn find_previous_block(&self, block: &u64) -> anyhow::Result> { + // TODO: fix name + match self + .find_previous_block_by_event_name("MemberChanged", block) + .await + { + Ok(v) => { + if let Some(s) = v { + return Ok(Some(s)); + } + } + Err(e) => { + return Err(e.into()); + } + }; + match self + .find_previous_block_by_event_name("DidAssociated", block) + .await + { + Ok(v) => { + if let Some(s) = v { + return Ok(Some(s)); + } + } + Err(e) => { + return Err(e.into()); + } + }; + match self + .find_previous_block_by_event_name("DidDisassociated", block) + .await + { + Ok(v) => { + if let Some(s) = v { + return Ok(Some(s)); + } + } + Err(e) => { + return Err(e.into()); + } + }; + Ok(None) + } + + pub async fn find_previous_block_by_event_name( + &self, + name_or_signature: &str, + block: &u64, + ) -> anyhow::Result> { + match self + .get_events_in_block_by_method(name_or_signature, block) + .await + { + Ok(logs) => { + if logs.len() == 0 { + return Ok(None); + } + Ok(Some(get_u64_from_log(&logs[0], "prevBlock"))) + } + Err(e) => { + return Err(e); + } + } + } + + pub async fn get_events_in_block_by_method( + &self, + name_or_signature: &str, + block: &u64, + ) -> anyhow::Result> { + let member_changed = self + .event_manager + .sweep(block, block, name_or_signature) + .await?; + Ok(member_changed) + } +} diff --git a/src/services/did/data_interface.rs b/src/services/did/data_interface.rs index 16d4177..142a3c8 100644 --- a/src/services/did/data_interface.rs +++ b/src/services/did/data_interface.rs @@ -13,7 +13,6 @@ impl DidDataInterfaceService { DidDataInterfaceService {} } pub async fn get_did_from_database( - &self, db: &DatabaseConnection, did: &str, ) -> Result, sea_orm::DbErr> { @@ -21,13 +20,42 @@ impl DidDataInterfaceService { } pub async fn insert_did_to_database( - &self, db: &DatabaseConnection, did: &str, + upper_block: Option, + last_processed_block: Option, + last_block_saved: Option, ) -> anyhow::Result { + let mut ub = 0_i64; + match upper_block { + Some(v) => { + ub = v as i64; + } + None => {} + } + + let mut lpb = 0_i64; + match last_processed_block { + Some(v) => { + lpb = v as i64; + } + None => {} + } + + let mut lbs = 0_i64; + match last_block_saved { + Some(v) => { + lbs = v as i64; + } + None => {} + } + let db_registry = DidActiveModel { id: Set(Uuid::new_v4()), did: Set(did.to_owned()), + upper_block: Set(ub), + last_processed_block: Set(lpb), + last_block_saved: Set(lbs), }; match db_registry.insert(db).await { Ok(res) => return Ok(res), @@ -38,7 +66,6 @@ impl DidDataInterfaceService { } pub async fn find_all( - &self, db: &DatabaseConnection, public_directory_contract_address: &str, chain_id: &str, @@ -47,4 +74,50 @@ impl DidDataInterfaceService { .all(db) .await } + + pub async fn update( + db: &DatabaseConnection, + upper_block: Option, + last_processed_block: Option, + last_block_saved: Option, + did: &str, + ) -> anyhow::Result { + match DidDataInterfaceService::get_did_from_database(&db, did).await { + Ok(v) => match v { + Some(m) => { + let mut s: DidActiveModel = m.into(); + match upper_block { + Some(v) => { + s.upper_block = Set(v as i64); + } + _ => {} + } + + match last_processed_block { + Some(v) => { + s.last_processed_block = Set(v as i64); + } + _ => {} + } + + match last_block_saved { + Some(v) => { + s.last_block_saved = Set(v as i64); + } + _ => {} + } + match s.update(db).await { + Ok(v) => Ok(v), + Err(err) => { + return Err(err.into()); + } + } + } + None => panic!("Error, registry doesn't exist"), + }, + Err(e) => { + return Err(e.into()); + } + } + } } diff --git a/src/services/did/did_registry_worker_service.rs b/src/services/did/did_registry_worker_service.rs index 26259d2..9e7ae1e 100644 --- a/src/services/did/did_registry_worker_service.rs +++ b/src/services/did/did_registry_worker_service.rs @@ -1,14 +1,393 @@ +use crate::{ + entities::models::DidModel, + services::{ + did::data_interface::DidDataInterfaceService, + public_key::data_interface::PublicKeyService, + trusted_registry::trusted_registry::Contract, + web3::utils::{ + get_address_from_log, get_bool_from_log, get_bytes_from_log, get_u64_from_log, + }, + }, +}; +use crypto::{digest::Digest, sha3::Sha3}; +use log::{debug, info}; use sea_orm::DatabaseConnection; -use uuid::Uuid; +use web3::ethabi::Log; -pub struct DidRegistryWorkerService {} +use super::index::{DidLac1, DidService}; + +pub struct DidRegistryWorkerService { + did_service: DidService, + public_key_service: PublicKeyService, + did: DidModel, + did_params: DidLac1, +} impl DidRegistryWorkerService { - pub fn new() -> Self { - Self {} + pub async fn new(did: DidModel) -> anyhow::Result { + match DidService::decode_did(&did.did) { + Ok(did_params) => { + let params = Contract { + chain_id: did_params.chain_id.to_string(), + contract_address: did_params.did_registry_address, + }; + match DidService::new(params).await { + Ok(did_service) => Ok(Self { + did_service, + public_key_service: PublicKeyService::new(), + did, + did_params, + }), + Err(e) => return Err(e.into()), + } + } + Err(e) => return Err(e.into()), + } + } + + pub async fn exec_or_resume_scheduled_sweep( + &mut self, + db: &DatabaseConnection, + ) -> anyhow::Result<()> { + info!("excuting scheduled worker thread"); + if self.did.upper_block == self.did.last_block_saved { + info!("All up to date in this scheduled task"); + return Ok(()); + } + + if self.did.upper_block >= self.did.last_processed_block + && self.did.last_processed_block > self.did.last_block_saved + { + info!("Found not finished job, resuming"); + match self + .did_service + .contract_interface_service + .find_previous_block(&(self.did.last_processed_block as u64)) + .await + { + Ok(u) => { + if let Some(prev_to_last_processed_block) = u { + return self + .process_events_in_block_range( + db, + prev_to_last_processed_block, + self.did.last_block_saved as u64, + ) + .await; + } + } + Err(e) => { + return Err(e); + } + } + } + info!("Starting scheduled job"); + return self + .process_events_in_block_range( + db, + self.did.upper_block as u64, + self.did.last_block_saved as u64, + ) + .await; + } + + pub async fn process_events_in_block_range( + &mut self, + db: &DatabaseConnection, + contract_block: u64, + target_block: u64, + ) -> anyhow::Result<()> { + let mut block_to_process = contract_block; + while block_to_process > target_block { + info!( + "Starting sweep; from block {}, to target block {}", + &block_to_process, &target_block + ); + match self.process_events_in_block(db, &block_to_process).await { + Ok(prev_block) => { + match DidDataInterfaceService::update( + db, + None, + Some(block_to_process), + None, + &self.did.did, + ) + .await + { + Ok(v) => { + self.did = v; + } + Err(e) => { + return Err(e.into()); + } + } + block_to_process = prev_block; + } + Err(e) => { + return Err(e.into()); + } + } + } + if block_to_process == target_block { + match DidDataInterfaceService::update( + db, + None, + Some(0), + Some(contract_block), + &self.did.did, + ) + .await + { + Ok(v) => { + self.did = v; + info!("Reached target block {}", block_to_process); + Ok(()) + } + Err(e) => { + return Err(e.into()); + } + } + } else { + panic!("Unexpected values, last block saved on database:{}, is greater than passed contract block: {}", &target_block, &block_to_process); + } + } + + //// Process event in the block whose number is passed as an argument. + /// Returns previous block + pub async fn process_events_in_block( + &self, + db: &DatabaseConnection, + block: &u64, + ) -> anyhow::Result { + let prev_block: u64; + + // TODO: make static + match self + .did_service + .contract_interface_service + .get_events_in_block_by_method("DIDAttributeChanged", &block) + .await + { + Ok(did_attribute_changed_logs) => { + match self + .process_did_attribute_changed_event(db, did_attribute_changed_logs, block) + .await + { + Err(e) => return Err(e.into()), + Ok(v) => { + prev_block = v; + } + } + } + Err(e) => { + return Err(e); + } + } + Ok(prev_block) + } + + pub async fn process_did_attribute_changed_event( + &self, + db: &DatabaseConnection, + did_attribute_changed_logs: Vec, + block: &u64, + ) -> anyhow::Result { + let mut prev_block: u64 = 0; + for did_attribute_changed_log in did_attribute_changed_logs { + let identity = get_address_from_log(&did_attribute_changed_log, "identity"); + if identity != self.did_params.address { + info!( + "Skipping log. Identities doesn't match, found identity {}; required {}", + identity, self.did_params.address + ); + continue; + } + let name = get_bytes_from_log(&did_attribute_changed_log, "name"); + match String::from_utf8(name) { + Ok(v) => { + info!("found new candidate public key for did {}", self.did.did); + let error_message = format!( + "Found public key for did {}, but params are unsupported", + self.did.did + ); + if let [asse, _, algorithm, encoding_method] = + v.split('/').collect::>().as_slice() + { + let is_candidate = + asse == &"asse" && algorithm == &"jwk" && encoding_method == &"cbor"; + if !is_candidate { + info!("{}", error_message); + continue; + } + } else { + info!("{}", error_message); + continue; + } + } + Err(e) => { + info!( + "Unable to process public key related did {:?}. Error is: {:?}... skipping this registry", + self.did.did, + e + ); + continue; + } + } + let pem_key = get_bytes_from_log(&did_attribute_changed_log, "value"); + let valid_to = get_u64_from_log(&did_attribute_changed_log, "validTo"); + // let change_time = get_u64_from_log(&did_attribute_changed_log, "changeTime"); // Not needed for this logic + prev_block = get_u64_from_log(&did_attribute_changed_log, "previousChange"); + let is_compromised = get_bool_from_log(&did_attribute_changed_log, "compromised"); // TODO: analyze how to serve this + + let mut h = Sha3::keccak256(); + h.input(&pem_key); + let content_hash = h.result_str(); + + match self + .public_key_service + .find_public_key_by_content_hash(db, &content_hash, &self.did.id) + .await + { + Ok(wrapped) => match wrapped { + Some(found_public_key) => { + if (found_public_key.block_number as u64) < *block { + match self + .public_key_service + .update_public_key( + db, + &found_public_key.id, + Some(*block), + Some(valid_to), + Some(is_compromised), + ) + .await + { + Ok(_) => { + info!( + "Updated public key with id: {:} for did: {}", + found_public_key.id, self.did.did + ); + } + Err(e) => return Err(e.into()), + } + } + } + None => { + match self + .public_key_service + .insert_public_key( + db, + &self.did.id, + &block, + pem_key, + &content_hash, + &valid_to, + is_compromised, + ) + .await + { + Ok(_) => { + info!("Inserted new public key for did: {}", self.did.did); + } + Err(e) => return Err(e.into()), + } + } + }, + Err(e) => return Err(e.into()), + } + } + Ok(prev_block) } - pub async fn sweep(&self, _db: &DatabaseConnection, _did_id: &Uuid) -> anyhow::Result<()> { - info!("DidRegistryWorkerService sweep"); - Ok(()) + + pub async fn sweep(&mut self, db: &DatabaseConnection) -> anyhow::Result<()> { + info!("Starting DidRegistryWorkerService sweep"); + debug!("Scanned did {} {}", self.did.did, self.did.id); + match self.exec_or_resume_scheduled_sweep(db).await { + Ok(_) => { + let contract_last_block: u64; + match self + .did_service + .contract_interface_service + .get_last_block(self.did_params.address) + .await + { + Ok(result) => { + if result == 0 { + info!( + "No events found for did: {:?}... skipping sweep", + self.did.did + ); + return Ok(()); + } + + contract_last_block = result; + } + Err(e) => { + return Err(e.into()); + } + } + // set upper block to contract last saved block + // set last processed block to zero value + match DidDataInterfaceService::get_did_from_database(db, &self.did.did).await { + Ok(v) => { + match v { + Some(m) => { + // verify whether insert is needed + if contract_last_block > 0 + && contract_last_block == m.upper_block as u64 + && contract_last_block == m.last_block_saved as u64 + { + info!("There are no changes in the contract. Last block saved is {}", contract_last_block); + return Ok(()); + } + match DidDataInterfaceService::update( + db, + Some(contract_last_block), + Some(0), + None, + &self.did.did, + ) + .await + { + Ok(v) => { + self.did = v.clone(); + self.exec_or_resume_scheduled_sweep(db).await + } + Err(err) => { + return Err(err.into()); + } + } + } + None => { + info!("Initializing metadata for contract in database"); + match DidDataInterfaceService::insert_did_to_database( + db, + &self.did.did, + Some(contract_last_block), + Some(0), + Some(0), + ) + .await + { + Ok(v) => { + self.did = v; + self.exec_or_resume_scheduled_sweep(db).await + } + Err(e) => { + return Err(e.into()); + } + } + } + } + } + Err(e) => { + return Err(e.into()); + } + } + } + Err(e) => { + return Err(e.into()); + } + } } } diff --git a/src/services/did/did_service.rs b/src/services/did/did_service.rs deleted file mode 100644 index f0ce86f..0000000 --- a/src/services/did/did_service.rs +++ /dev/null @@ -1,13 +0,0 @@ -use super::data_interface::DidDataInterfaceService; - -pub struct DidService { - pub did_data_interface_service: DidDataInterfaceService, -} - -impl DidService { - pub fn new() -> DidService { - DidService { - did_data_interface_service: DidDataInterfaceService {}, - } - } -} diff --git a/src/services/did/index.rs b/src/services/did/index.rs new file mode 100644 index 0000000..57a005a --- /dev/null +++ b/src/services/did/index.rs @@ -0,0 +1,113 @@ +use crate::{services::trusted_registry::trusted_registry::Contract, utils::utils::Utils}; +use crypto::{digest::Digest, sha3::Sha3}; +use web3::types::H160; + +use super::{contract_interface::ContractInterface, data_interface::DidDataInterfaceService}; + +pub struct DidLac1 { + pub address: H160, + pub did_registry_address: H160, + pub chain_id: i64, +} + +pub struct DidService { + pub did_data_interface_service: DidDataInterfaceService, + pub contract_interface_service: ContractInterface, +} + +impl DidService { + pub async fn new(params: Contract) -> anyhow::Result { + let contract_interface: ContractInterface; + match ContractInterface::new(params.clone()).await { + Ok(v) => { + contract_interface = v; + } + Err(e) => { + return Err(e); + } + } + Ok(DidService { + did_data_interface_service: DidDataInterfaceService {}, + contract_interface_service: contract_interface, + }) + } + + /// did_type_ lac1, version 1. + pub fn decode_did(did: &str) -> anyhow::Result { + let did = did.trim(); + let core = did.replace("did:lac1:", ""); + match bs58::decode(core).into_vec() { + Ok(decoded) => { + let size = decoded.len(); + let (encoded_payload, checksum) = decoded.split_at(size - 4); + // checksum + let mut h = Sha3::keccak256(); + h.input(encoded_payload); + let mut out: [u8; 32] = [0; 32]; + h.result(&mut out); + let (computed_checksum, _) = out.split_at(4); + if computed_checksum != checksum.to_vec().as_slice() { + return Err(anyhow::anyhow!("checksum error")); + } + let (_version, right) = encoded_payload.split_at(2); + let (_did_type, right) = right.split_at(2); + // TODO: verify did version and type + let (address, right) = right.split_at(20); + let (did_registry_address, chain_id) = right.split_at(20); + // let address = Utils::vec_u8_to_hex_string(address.to_vec()).unwrap(); + let address = H160::from_slice(address); + // let did_registry_address = + // Utils::vec_u8_to_hex_string(did_registry_address.to_vec()).unwrap(); + let did_registry_address = H160::from_slice(did_registry_address); + let chain_id = Utils::vec_u8_to_hex_string(chain_id.to_vec()).unwrap(); + let chain_id_int; + match i64::from_str_radix(chain_id.trim_start_matches("0x"), 16) { + Ok(v) => chain_id_int = v, + Err(_) => panic!("Invalid chain id: {}", chain_id), + } + Ok(DidLac1 { + address, + did_registry_address, + chain_id: chain_id_int, + }) + } + Err(e) => Err(e.into()), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + // use std::println; + #[test] + fn decode_did_sucess_test() { + let did = + "did:lac1:1iT5D8E51oULzpTrFePKe9KibQh4sEnqLCRDdFSLRNPfmf89seFJvjcfgKrtZ5YdGBX1".trim(); + let decoded = DidService::decode_did(did).unwrap(); + assert_eq!( + decoded.address.to_string().to_lowercase(), + "0x560ff31E783570097c18bd342e524Ef4c36fE7AE" + .to_owned() + .to_lowercase() + ); + + assert_eq!( + decoded.did_registry_address.to_string().to_lowercase(), + "0x54358D929CCf45C7cCEE8Ca60FCD0C0402489F54" + .to_owned() + .to_lowercase(), + ); + + assert_eq!(decoded.chain_id, 648540) + } + + #[test] + fn decode_did_failure_test() { + let did = "some value"; + match DidService::decode_did(did) { + Ok(_) => assert!(false), + Err(_) => assert!(true), + } + } +} diff --git a/src/services/pd_did_member/data_interface.rs b/src/services/pd_did_member/data_interface.rs index bbccccf..6c0dd70 100644 --- a/src/services/pd_did_member/data_interface.rs +++ b/src/services/pd_did_member/data_interface.rs @@ -3,7 +3,7 @@ use sea_orm::DatabaseConnection; use sea_orm::Set; use uuid::Uuid; -use crate::services::did::did_service::DidService; +use crate::services::did::data_interface::DidDataInterfaceService; use crate::services::pd_member::data_interface::PdMemberDataInterfaceService; use crate::entities::entities::PdDidMemberEntity; @@ -12,17 +12,12 @@ use crate::entities::models::PdDidMemberModel; pub struct PdDidMemberDataInterfaceService { pub pd_member_data_service: PdMemberDataInterfaceService, - pub did_service: DidService, } impl PdDidMemberDataInterfaceService { - pub fn new( - pd_member_data_service: PdMemberDataInterfaceService, - did_service: DidService, - ) -> Self { + pub fn new(pd_member_data_service: PdMemberDataInterfaceService) -> Self { Self { pd_member_data_service, - did_service, } } @@ -43,12 +38,7 @@ impl PdDidMemberDataInterfaceService { did: &str, member_id: &i64, ) -> Result, sea_orm::DbErr> { - match self - .did_service - .did_data_interface_service - .get_did_from_database(db, did) - .await - { + match DidDataInterfaceService::get_did_from_database(db, did).await { Ok(u) => match u { Some(found_did) => match self .pd_member_data_service diff --git a/src/services/public_directory/public_directory_worker_service.rs b/src/services/public_directory/public_directory_worker_service.rs index be1a92a..fb04652 100644 --- a/src/services/public_directory/public_directory_worker_service.rs +++ b/src/services/public_directory/public_directory_worker_service.rs @@ -6,7 +6,7 @@ use uuid::Uuid; use web3::ethabi::Log; use crate::services::{ - did::did_service::DidService, + did::data_interface::DidDataInterfaceService, pd_did_member::data_interface::PdDidMemberDataInterfaceService, pd_member::data_interface::PdMemberDataInterfaceService, public_directory::index::PublicDirectoryService, @@ -23,7 +23,6 @@ impl PublicDirectoryWorkerService { PublicDirectoryWorkerService { pd_did_member_data_interface_service: PdDidMemberDataInterfaceService::new( pd_member_data_service, - DidService::new(), ), } } @@ -196,10 +195,7 @@ impl PublicDirectoryWorkerService { "Starting sweep; from block {}, to target block {}", &block_to_process, &target_block ); - match self - .public_directory_process_events_in_block(db, &block_to_process) - .await - { + match self.process_events_in_block(db, &block_to_process).await { Ok(prev_block) => { match self .pd_did_member_data_interface_service @@ -278,8 +274,9 @@ impl PublicDirectoryWorkerService { Ok(did_associated_map) } - //// Returns previous block - pub async fn public_directory_process_events_in_block( + //// Process event in the block whose number is passed as an argument. + /// Returns previous block + pub async fn process_events_in_block( &self, db: &DatabaseConnection, block: &u64, @@ -410,24 +407,16 @@ impl PublicDirectoryWorkerService { // "SAVE" to Did table let did_id: Uuid; - match self - .pd_did_member_data_interface_service - .did_service - .did_data_interface_service - .get_did_from_database(db, &did) - .await - { + match DidDataInterfaceService::get_did_from_database(db, &did).await { Ok(v) => match v { Some(existing_did) => { did_id = existing_did.id; } None => { - match self - .pd_did_member_data_interface_service - .did_service - .did_data_interface_service - .insert_did_to_database(db, &did) - .await + match DidDataInterfaceService::insert_did_to_database( + db, &did, None, None, None, + ) + .await { Ok(v) => did_id = v.id, Err(e) => return Err(e.into()), diff --git a/src/services/public_key.rs b/src/services/public_key.rs new file mode 100644 index 0000000..aa85626 --- /dev/null +++ b/src/services/public_key.rs @@ -0,0 +1 @@ +pub mod data_interface; diff --git a/src/services/public_key/data_interface.rs b/src/services/public_key/data_interface.rs new file mode 100644 index 0000000..ca0b24e --- /dev/null +++ b/src/services/public_key/data_interface.rs @@ -0,0 +1,105 @@ +use crate::entities::entities::PublicKeyEntity; +use crate::entities::models::{PublicKeyActiveModel, PublicKeyModel}; +use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; +use uuid::Uuid; +pub struct PublicKeyService {} + +impl PublicKeyService { + pub fn new() -> PublicKeyService { + PublicKeyService {} + } + + pub async fn find_public_key_by_content_hash( + &self, + db: &DatabaseConnection, + content_hash: &str, + did_id: &Uuid, + ) -> Result, sea_orm::DbErr> { + PublicKeyEntity::find_by_hash_and_did_id(content_hash, did_id) + .one(db) + .await + } + + pub async fn find_by_id( + &self, + db: &DatabaseConnection, + id: &Uuid, + ) -> Result, sea_orm::DbErr> { + PublicKeyEntity::find_by_id(id).one(db).await + } + + pub async fn insert_public_key( + &self, + db: &DatabaseConnection, + did_id: &Uuid, + block_number: &u64, + pem_key: Vec, + content_hash: &str, + exp: &u64, + is_compromised: bool, + ) -> anyhow::Result { + let db_registry = PublicKeyActiveModel { + id: Set(Uuid::new_v4()), + did_id: Set(*did_id), + block_number: Set(*block_number as i64), + pem_key: Set(pem_key), + content_hash: Set(content_hash.to_owned()), + exp: Set(*exp as i64), + is_compromised: Set(is_compromised), + }; + match db_registry.insert(db).await { + Ok(res) => return Ok(res), + Err(e) => { + return Err(e.into()); + } + } + } + + pub async fn update_public_key( + &self, + db: &DatabaseConnection, + public_key_id: &Uuid, + block_number: Option, + exp: Option, + is_compromised: Option, + ) -> anyhow::Result { + match self.find_by_id(db, public_key_id).await { + Ok(v) => match v { + Some(v) => { + let mut s: PublicKeyActiveModel = v.into(); + match block_number { + Some(v) => { + s.block_number = Set(v as i64); + } + None => {} + } + match exp { + Some(v) => { + s.exp = Set(v as i64); + } + None => {} + } + match is_compromised { + Some(v) => { + s.is_compromised = Set(v); + } + None => {} + } + match s.update(db).await { + Ok(res) => return Ok(res), + Err(err) => { + return Err(err.into()); + } + } + } + None => { + return Err(anyhow::anyhow!(format!( + "Pd Did member with id {:?} does not exist", + public_key_id + ))) + } + }, + Err(e) => return Err(e.into()), + } + } +} diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs index e052b2c..9906e60 100644 --- a/src/services/trusted_registry/trusted_registry.rs +++ b/src/services/trusted_registry/trusted_registry.rs @@ -6,7 +6,8 @@ use web3::types::H160; use crate::{ config::env_config::Config, services::{ - did::did_registry_worker_service::DidRegistryWorkerService, did::did_service::DidService, + did::data_interface::DidDataInterfaceService, + did::did_registry_worker_service::DidRegistryWorkerService, public_directory::index::PublicDirectoryService, public_directory::public_directory_worker_service::PublicDirectoryWorkerService, }, @@ -28,6 +29,7 @@ pub struct TrustedRegistry { } impl TrustedRegistry { + // TODO: ensure an invalid event doesn't make fail this sweep function pub async fn sweep(&self) -> anyhow::Result<()> { info!( "Sweeping trusted registry ... {:?} {:?}", @@ -55,23 +57,26 @@ impl TrustedRegistry { // seep cot // sweep dids that matches with pulbic directory // TODO: match them with Chain Of Trust also - let did_service = DidService::new(); - let did_registry_worker_service = DidRegistryWorkerService::new(); - match did_service - .did_data_interface_service - .find_all( - &db, - &self.public_directory.contract_address.to_string(), - &self.public_directory.chain_id, - ) - .await + match DidDataInterfaceService::find_all( + &db, + &self.public_directory.contract_address.to_string(), + &self.public_directory.chain_id, + ) + .await { Ok(dids) => { for did in dids { - match did_registry_worker_service.sweep(&db, &did.id).await { - Ok(_) => {} - Err(e) => panic!("{}", e), - } + match DidRegistryWorkerService::new(did.clone()).await { + Ok(mut on_flight_did_registry_worker_service) => { + match on_flight_did_registry_worker_service.sweep(&db).await { + Ok(_) => {} + Err(e) => panic!("{}", e), + } + } + Err(e) => { + error!("There was an error while trying to pick public keys from did {:?}; error is: {:?}", did.did ,e); + } + }; } } Err(e) => return Err(e.into()), diff --git a/src/services/web3/utils.rs b/src/services/web3/utils.rs index 4ff5d37..6eacdfa 100644 --- a/src/services/web3/utils.rs +++ b/src/services/web3/utils.rs @@ -1,4 +1,4 @@ -use web3::ethabi::Log; +use web3::{ethabi::Log, types::H160}; pub fn get_u64_from_log(log: &Log, param_name: &str) -> u64 { match log.params.iter().find(|¶m| param.name == param_name) { @@ -19,3 +19,33 @@ pub fn get_string_from_string_in_log(log: &Log, param_name: &str) -> String { None => panic!("No value found for param {}", param_name), } } + +pub fn get_address_from_log(log: &Log, param_name: &str) -> H160 { + match log.params.iter().find(|¶m| param.name == param_name) { + Some(param) => match param.value.clone() { + web3::ethabi::Token::Address(v) => v, + _ => panic!("Error extracting address from log"), + }, + None => panic!("No value found for param {}", param_name), + } +} + +pub fn get_bytes_from_log(log: &Log, param_name: &str) -> Vec { + match log.params.iter().find(|¶m| param.name == param_name) { + Some(param) => match param.value.clone() { + web3::ethabi::Token::Bytes(v) => v, + _ => panic!("Passed value are not bytes"), + }, + None => panic!("No value found for param {}", param_name), + } +} + +pub fn get_bool_from_log(log: &Log, param_name: &str) -> bool { + match log.params.iter().find(|¶m| param.name == param_name) { + Some(param) => match param.value.clone() { + web3::ethabi::Token::Bool(v) => v, + _ => panic!("Passed value is not a bool"), + }, + None => panic!("No value found for param {}", param_name), + } +} diff --git a/src/utils/utils.rs b/src/utils/utils.rs index a40c86b..87aac84 100644 --- a/src/utils/utils.rs +++ b/src/utils/utils.rs @@ -31,4 +31,24 @@ impl Utils { let dot_pos = value.find(".").unwrap_or(value.len()); value[..dot_pos].parse() } + + pub fn vec_u8_to_hex_string(value: Vec) -> Option { + let value = value + .into_iter() + .map(|el| format!("{:02x?}", el)) + .collect::>() + .concat(); + Some(format!("0x{}", value)) + } + + pub fn vec_u8_to_u64(value: Vec) -> Option { + match (0..value.len()) + .into_iter() + .map(|i| 16_u64.pow((i as u64).try_into().unwrap()) * value[i] as u64) + .reduce(|acc, e| acc + e) + { + Some(i) => Some(i), + None => None, + } + } } From 706ef1094b2fe97099a9928ffd5caa32209a3b0a Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 26 Jun 2023 13:29:04 -0500 Subject: [PATCH 23/25] refactor: store certs as json web keys --- src/entities/public_key/model.rs | 2 +- src/migration/m20230623_215702_public_key.rs | 4 ++-- .../did/did_registry_worker_service.rs | 24 ++++++++++++------- src/services/public_key/data_interface.rs | 4 ++-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/entities/public_key/model.rs b/src/entities/public_key/model.rs index 06b0542..016787e 100644 --- a/src/entities/public_key/model.rs +++ b/src/entities/public_key/model.rs @@ -10,7 +10,7 @@ pub struct Model { pub id: Uuid, pub did_id: Uuid, pub block_number: i64, - pub pem_key: Vec, + pub jwk: Vec, #[sea_orm(column_type = "Text")] pub content_hash: String, pub exp: i64, diff --git a/src/migration/m20230623_215702_public_key.rs b/src/migration/m20230623_215702_public_key.rs index 5132574..e8909aa 100644 --- a/src/migration/m20230623_215702_public_key.rs +++ b/src/migration/m20230623_215702_public_key.rs @@ -23,7 +23,7 @@ impl MigrationTrait for Migration { .big_integer() .not_null(), ) - .col(ColumnDef::new(PublicKey::PemKey).binary().not_null()) + .col(ColumnDef::new(PublicKey::Jwk).binary().not_null()) .col(ColumnDef::new(PublicKey::ContentHash).string().not_null()) .col(ColumnDef::new(PublicKey::Exp).big_integer().not_null()) .col( @@ -56,7 +56,7 @@ enum PublicKey { Id, DidId, BlockNumber, - PemKey, + Jwk, ContentHash, Exp, IsCompromised, diff --git a/src/services/did/did_registry_worker_service.rs b/src/services/did/did_registry_worker_service.rs index 9e7ae1e..efb2401 100644 --- a/src/services/did/did_registry_worker_service.rs +++ b/src/services/did/did_registry_worker_service.rs @@ -210,11 +210,9 @@ impl DidRegistryWorkerService { "Found public key for did {}, but params are unsupported", self.did.did ); - if let [asse, _, algorithm, encoding_method] = - v.split('/').collect::>().as_slice() - { - let is_candidate = - asse == &"asse" && algorithm == &"jwk" && encoding_method == &"cbor"; + if let [asse, _, algorithm, _] = v.split('/').collect::>().as_slice() { + // omiting encoding method + let is_candidate = asse == &"asse" && algorithm == &"jwk"; if !is_candidate { info!("{}", error_message); continue; @@ -233,14 +231,24 @@ impl DidRegistryWorkerService { continue; } } - let pem_key = get_bytes_from_log(&did_attribute_changed_log, "value"); + let jwk_bytes = get_bytes_from_log(&did_attribute_changed_log, "value"); + match String::from_utf8(jwk_bytes.clone()) { + Ok(v) => v, + Err(err) => { + info!( + "Error decoding certificate ... skipping this registry: {:?}", + err + ); + continue; + } + }; let valid_to = get_u64_from_log(&did_attribute_changed_log, "validTo"); // let change_time = get_u64_from_log(&did_attribute_changed_log, "changeTime"); // Not needed for this logic prev_block = get_u64_from_log(&did_attribute_changed_log, "previousChange"); let is_compromised = get_bool_from_log(&did_attribute_changed_log, "compromised"); // TODO: analyze how to serve this let mut h = Sha3::keccak256(); - h.input(&pem_key); + h.input(&jwk_bytes); let content_hash = h.result_str(); match self @@ -279,7 +287,7 @@ impl DidRegistryWorkerService { db, &self.did.id, &block, - pem_key, + jwk_bytes, &content_hash, &valid_to, is_compromised, diff --git a/src/services/public_key/data_interface.rs b/src/services/public_key/data_interface.rs index ca0b24e..7afe25d 100644 --- a/src/services/public_key/data_interface.rs +++ b/src/services/public_key/data_interface.rs @@ -33,7 +33,7 @@ impl PublicKeyService { db: &DatabaseConnection, did_id: &Uuid, block_number: &u64, - pem_key: Vec, + jwk: Vec, content_hash: &str, exp: &u64, is_compromised: bool, @@ -42,7 +42,7 @@ impl PublicKeyService { id: Set(Uuid::new_v4()), did_id: Set(*did_id), block_number: Set(*block_number as i64), - pem_key: Set(pem_key), + jwk: Set(jwk), content_hash: Set(content_hash.to_owned()), exp: Set(*exp as i64), is_compromised: Set(is_compromised), From e01fec44fd2b7edde1db89c2cd01f778ca395c37 Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 30 Jun 2023 19:20:10 -0500 Subject: [PATCH 24/25] feat: expose public keys through an endpoint --- .example.env | 5 +- .example.env.dev | 5 +- .example.env.dev.sh | 3 +- Cargo.lock | 1 + Cargo.toml | 1 + docker-compose-dev.yml | 1 + docker-compose.yml | 1 + docs/tech/configuration.md | 2 +- src/controllers.rs | 1 + src/controllers/index.rs | 9 +- src/controllers/public_key_controller.rs | 60 ++++++++++++ src/dto.rs | 1 + src/dto/response.rs | 1 + src/dto/response/public_key_response_dto.rs | 38 ++++++++ src/entities/did/select.rs | 15 ++- src/entities/public_key/select.rs | 52 +++++++++++ src/jobs/trusted_registries.rs | 65 ++++++++----- .../public_directory/data_interface.rs | 8 +- .../public_directory_worker_service.rs | 2 +- src/services/public_key/data_interface.rs | 91 ++++++++++++++++++- .../trusted_registry/trusted_registry.rs | 8 +- src/utils/utils.rs | 8 ++ 22 files changed, 337 insertions(+), 41 deletions(-) create mode 100644 src/controllers/public_key_controller.rs create mode 100644 src/dto/response.rs create mode 100644 src/dto/response/public_key_response_dto.rs diff --git a/.example.env b/.example.env index a24d2aa..d3c7f83 100644 --- a/.example.env +++ b/.example.env @@ -35,5 +35,6 @@ RATE_LIMIT_WINDOW = 5 RATE_LIMIT_MAX_REQUESTS = 100 # custom variables -export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" -export RPC_CONNECTION_648540="http://35.185.112.219" \ No newline at end of file +TRUSTED_REGISTRIES="1,0x609e1d1364d607b027e577e10ad97c571b9518c1,648540,0x86Faa7372AB68852c89fee37cCAc4b4c11a8471D,0x9e55c" # format: "INDEX_1,PD1,PD1_CID,COT1,COT1_CID--2,INDEX_2,PD2,PD2_CID-COT2,COT2_CID" +TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE="1" +RPC_CONNECTION_648540="http://35.185.112.219" \ No newline at end of file diff --git a/.example.env.dev b/.example.env.dev index 25505dd..896a1f6 100644 --- a/.example.env.dev +++ b/.example.env.dev @@ -34,5 +34,6 @@ RATE_LIMIT_WINDOW = 5 RATE_LIMIT_MAX_REQUESTS = 100 # custom variables -export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,0x9e55c-0xEBB6854aa875867f684dd1d2338eC20908039c67,0x9e55c" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" -export RPC_CONNECTION_648540="http://35.185.112.219" \ No newline at end of file +TRUSTED_REGISTRIES="1,0x609e1d1364d607b027e577e10ad97c571b9518c1,648540,0x86Faa7372AB68852c89fee37cCAc4b4c11a8471D,0x9e55c" # format: "INDEX_1,PD1,PD1_CID,COT1,COT1_CID--2,INDEX_2,PD2,PD2_CID-COT2,COT2_CID" +TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE="1" +RPC_CONNECTION_648540="http://35.185.112.219" \ No newline at end of file diff --git a/.example.env.dev.sh b/.example.env.dev.sh index aea1804..0e2c44b 100755 --- a/.example.env.dev.sh +++ b/.example.env.dev.sh @@ -34,6 +34,7 @@ export RATE_LIMIT_WINDOW=5 export RATE_LIMIT_MAX_REQUESTS=100 # custom variables -export TRUSTED_REGISTRIES="0xA4C2dAFD7eaE7CBe86EB6bf9f3b842C3df2607C0,648540-0xEBB6854aa875867f684dd1d2338eC20908039c67,648540" # format: "PD1,PD1_CID-COT1,COT2_CID--PD2,PD2_CID-COT2,COT2_CID" +export TRUSTED_REGISTRIES="1,0x609e1d1364d607b027e577e10ad97c571b9518c1,648540,0x86Faa7372AB68852c89fee37cCAc4b4c11a8471D,0x9e55c" # format: "INDEX_1,PD1,PD1_CID,COT1,COT1_CID--2,INDEX_2,PD2,PD2_CID-COT2,COT2_CID" +export TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE="1" export DATABASE_URL="postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${EXPOSED_CONTAINER_TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection export RPC_CONNECTION_648540="http://35.185.112.219" diff --git a/Cargo.lock b/Cargo.lock index 9cd9a17..fd275de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2641,6 +2641,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30f30b2cf45d317def42af8542635e341fa4ae12fb0697a713346750ff426aa2" dependencies = [ "rocket", + "rocket_okapi", "sea-orm-rocket-codegen", ] diff --git a/Cargo.toml b/Cargo.toml index 4e10587..4f0ee93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ rust-crypto = "0.2" [dependencies.sea-orm-rocket] version = "0.5.2" +features = ["rocket_okapi"] [dependencies.sea-orm-migration] version = "0.11.3" diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index c5501cc..3675dd3 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -37,6 +37,7 @@ services: RATE_LIMIT_WINDOW: "${RATE_LIMIT_WINDOW}" RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" + TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE: "${TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE}" RPC_CONNECTION_648540: "${RPC_CONNECTION_648540}" DATABASE_URL: "postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection ports: diff --git a/docker-compose.yml b/docker-compose.yml index 7424da5..621e9af 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,6 +43,7 @@ services: RATE_LIMIT_MAX_REQUESTS: "${RATE_LIMIT_MAX_REQUESTS}" TRUSTED_REGISTRIES: "${TRUSTED_REGISTRIES}" RPC_CONNECTION_648540: "${RPC_CONNECTION_648540}" + TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE: "${TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE}" DATABASE_URL: "postgres://${TYPEORM_USERNAME}:${TYPEORM_PASSWORD}@${TYPEORM_HOST}:${TYPEORM_PORT}/${TYPEORM_DATABASE}" #default connection ports: - "${EXPOSED_CONTAINER_SERVER_PORT}:${PORT}" diff --git a/docs/tech/configuration.md b/docs/tech/configuration.md index 544c084..07579d5 100644 --- a/docs/tech/configuration.md +++ b/docs/tech/configuration.md @@ -32,7 +32,7 @@ docker-compose -f docker-compose-dbs.yml --env-file .env.dev up cp .example.env.dev.sh .env.dev.sh chmod +x .env.dev.sh . ./.env.dev.sh -RUST_LOG="debug,tower_http=trace" cargo run # RUST_LOG="debug,tower_http=trace" cargo watch -x run (if you have "watch" installed) +RUST_LOG="info" cargo run # RUST_LOG="info" cargo watch -x run (if you have "watch" installed) ``` ### Development with Docker diff --git a/src/controllers.rs b/src/controllers.rs index 9bd2c76..0e4b2c0 100644 --- a/src/controllers.rs +++ b/src/controllers.rs @@ -1,2 +1,3 @@ pub mod certificate_controller; pub mod index; +pub mod public_key_controller; diff --git a/src/controllers/index.rs b/src/controllers/index.rs index 38850bf..4f03493 100644 --- a/src/controllers/index.rs +++ b/src/controllers/index.rs @@ -47,7 +47,8 @@ pub fn stage() -> AdHoc { // let custom_route_spec = (vec![], custom_openapi_spec()); mount_endpoints_and_merged_docs! { building_rocket, "/api/v1".to_owned(), openapi_settings, - "/certificates" => get_routes_and_docs(&openapi_settings) + "/certificates" => get_routes_and_docs(&openapi_settings), + "/public-key" => get_routes_and_docs_for_public_key(&openapi_settings), }; building_rocket }) @@ -59,6 +60,12 @@ pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec, O ] } +pub fn get_routes_and_docs_for_public_key( + settings: &OpenApiSettings, +) -> (Vec, OpenApi) { + openapi_get_routes_spec![settings: crate::controllers::public_key_controller::get_all] +} + fn cors() -> Cors { let allowed_origins = AllowedOrigins::All; diff --git a/src/controllers/public_key_controller.rs b/src/controllers/public_key_controller.rs new file mode 100644 index 0000000..637be1a --- /dev/null +++ b/src/controllers/public_key_controller.rs @@ -0,0 +1,60 @@ +use crate::databases::pool::Db; +use crate::dto::response::public_key_response_dto::PublicKeyResponseDto; +use crate::jobs::trusted_registries::TrustedRegistries; +use crate::responses::error_message::ErrorMessage; +use crate::responses::generic_response::Responses; +use crate::responses::success_messages::SuccessMessage; +use crate::services::public_key::data_interface::PublicKeyService; +use crate::services::trusted_registry::trusted_registry::TrustedRegistry; +use crate::utils::utils::Utils; +use log::error; +use rocket::get; +use rocket::serde::json::Json; +use rocket_okapi::openapi; +use sea_orm_rocket::Connection; + +fn get_trusted_registry_by_index() -> TrustedRegistry { + let trusted_registries = TrustedRegistries::process_env_trusted_registries(); + let index: String; + match Utils::get_env_or_err("TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE") { + Ok(s) => index = s, + Err(e) => { + error!("{}", e); + panic!( + "Please set TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE environment variable" + ); + } + } + let tr = trusted_registries + .into_iter() + .filter(|e| e.index == index) + .collect::>(); + if tr.len() != 1 { + let message = format!("TRUSTED_REGISTRIES_INDEX_PUBLIC_KEYS_TO_EXPOSE '{:?}' was (not found/or more than one) with the pointed index was found in TRUSTED_REGISTRIES", index); + panic!("{}", message); + }; + tr[0].clone() +} + +/// # Return public keys +#[openapi(tag = "Public keys")] +#[get("/get-all?&")] +pub async fn get_all( + connection: Connection<'_, Db>, + page: Option, + results_per_page: Option, +) -> Responses>, Json>> { + let tr = get_trusted_registry_by_index(); + let public_directory_contract_address = + Utils::vec_u8_to_hex_string(tr.public_directory.contract_address.as_bytes().to_vec()) + .unwrap(); + let public_directory_chain_id = tr.public_directory.chain_id; + PublicKeyService::get_all( + connection, + page, + results_per_page, + &public_directory_contract_address, + &public_directory_chain_id, + ) + .await +} diff --git a/src/dto.rs b/src/dto.rs index 037be31..0f8b7d1 100644 --- a/src/dto.rs +++ b/src/dto.rs @@ -1,2 +1,3 @@ pub mod raw; +pub mod response; pub mod utils; diff --git a/src/dto/response.rs b/src/dto/response.rs new file mode 100644 index 0000000..230fe9c --- /dev/null +++ b/src/dto/response.rs @@ -0,0 +1 @@ +pub mod public_key_response_dto; diff --git a/src/dto/response/public_key_response_dto.rs b/src/dto/response/public_key_response_dto.rs new file mode 100644 index 0000000..ba0e590 --- /dev/null +++ b/src/dto/response/public_key_response_dto.rs @@ -0,0 +1,38 @@ +use rocket::serde::{Deserialize, Serialize}; +use rocket_okapi::okapi::schemars::{self, JsonSchema}; + +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[serde(crate = "rocket::serde")] +pub struct PublicKeyResponseDto { + pub page: u64, + pub results_per_page: u64, + pub num_pages: u64, + pub keys: Vec, +} + +#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct Jwk { + #[serde(skip_serializing_if = "Option::is_none")] + pub alg: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#use: Option, + pub kty: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub kid: Option, + pub x5c: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub x5t: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub n: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub e: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub x: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub y: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub crv: Option, +} diff --git a/src/entities/did/select.rs b/src/entities/did/select.rs index 451b9c0..3993a27 100644 --- a/src/entities/did/select.rs +++ b/src/entities/did/select.rs @@ -5,7 +5,6 @@ use crate::entities::entities::PdMemberEntity; use crate::entities::entities::PublicDirectoryEntity; use crate::entities::public_directory::model::Column as Pd; use sea_orm::sea_query::Expr; -use sea_orm::sea_query::IntoCondition; use sea_orm::sea_query::Query; use sea_orm::{entity::*, query::*}; @@ -38,10 +37,16 @@ impl DidEntity { .join( JoinType::InnerJoin, PublicDirectoryEntity, - Expr::col((PublicDirectoryEntity, Pd::ContractAddress)) - .eq(public_directory_contract_address.clone()) - .and(Pd::ChainId.contains(&chain_id)) - .into_condition(), + Expr::col(( + PdMemberEntity, + crate::entities::pd_member::model::Column::PublicDirectoryId, + )) + .equals((PublicDirectoryEntity, Pd::Id)) + .and( + Expr::col((PublicDirectoryEntity, Pd::ContractAddress)) + .eq(public_directory_contract_address.clone()) + .and(Pd::ChainId.contains(&chain_id)), + ), ) .to_owned(), ), diff --git a/src/entities/public_key/select.rs b/src/entities/public_key/select.rs index 0b3df77..23aa2d5 100644 --- a/src/entities/public_key/select.rs +++ b/src/entities/public_key/select.rs @@ -1,11 +1,20 @@ +use sea_orm::sea_query::Expr; +use sea_orm::sea_query::Query; use sea_orm::ColumnTrait; +use sea_orm::Condition; use sea_orm::EntityTrait; +use sea_orm::JoinType; use sea_orm::QueryFilter; use sea_orm::Select; use uuid::Uuid; +use crate::entities::entities::PdDidMemberEntity; use crate::entities::entities::PublicKeyEntity; +use crate::entities::entities::PdMemberEntity; +use crate::entities::entities::PublicDirectoryEntity; +use crate::entities::public_directory::model::Column as Pd; + use super::model; impl PublicKeyEntity { @@ -20,4 +29,47 @@ impl PublicKeyEntity { pub fn find_by_id(id: &Uuid) -> Select { Self::find().filter(model::Column::Id.eq(*id)) } + pub fn find_by_public_directory( + public_directory_contract_address: &str, + chain_id: &str, + ) -> Select { + let public_directory_contract_address = public_directory_contract_address.to_owned(); + let chain_id = chain_id.to_owned(); + Self::find().filter( + Condition::any().add( + model::Column::DidId.in_subquery( + Query::select() + .column(crate::entities::pd_did_member::model::Column::DidId) + .from(PdDidMemberEntity) + .join( + JoinType::InnerJoin, + PdMemberEntity, + Expr::col(( + PdDidMemberEntity, + crate::entities::pd_did_member::model::Column::PdMemberId, + )) + .equals(( + PdMemberEntity, + crate::entities::pd_member::model::Column::Id, + )), + ) + .join( + JoinType::InnerJoin, + PublicDirectoryEntity, + Expr::col(( + PdMemberEntity, + crate::entities::pd_member::model::Column::PublicDirectoryId, + )) + .equals((PublicDirectoryEntity, Pd::Id)) + .and( + Expr::col((PublicDirectoryEntity, Pd::ContractAddress)) + .eq(public_directory_contract_address.clone()) + .and(Pd::ChainId.contains(&chain_id)), + ), + ) + .to_owned(), + ), + ), + ) + } } diff --git a/src/jobs/trusted_registries.rs b/src/jobs/trusted_registries.rs index f62d623..7da046e 100644 --- a/src/jobs/trusted_registries.rs +++ b/src/jobs/trusted_registries.rs @@ -20,37 +20,54 @@ impl TrustedRegistries { s.set_start_up_and_period(); s } - fn get_trusted_registries(&self) -> String { + fn get_trusted_registries() -> String { match Utils::get_env_or_err("TRUSTED_REGISTRIES") { Ok(s) => s, Err(_) => panic!("Please set TRUSTED_REGISTRIES environment variable"), } } + pub fn process_env_trusted_registries() -> Vec { + let binding = TrustedRegistries::get_trusted_registries(); + let raw_trusted_registries = binding + .split("--") + .collect::>() + .into_iter() + .map(|tr_str| { + if let [index, pd, pd_cid, cot, cot_cid] = + tr_str.split(",").collect::>().as_slice() + { + let pd = Utils::trim_0x_from_hex_string(pd); + let cot = Utils::trim_0x_from_hex_string(cot); + let public_directory_address = <[u8; 20]>::from_hex(pd) + .expect("Invalid public directory contract address"); + let cot_address = + <[u8; 20]>::from_hex(cot).expect("Invalid chain of trust contract address"); + let t1 = TrustedRegistry { + index: index.to_string(), + period_seconds: 400, + start_up: 5, + public_directory: Contract { + chain_id: pd_cid.to_string(), + contract_address: H160(public_directory_address), + }, + chain_of_trust: Contract { + chain_id: cot_cid.to_string(), + contract_address: H160(cot_address), + }, + retry_period: 0, + }; + t1 + } else { + panic!("Error decoding trusted registry params from environment variables"); + } + }) + .collect::>(); + raw_trusted_registries + } + fn set_trusted_registries(&mut self) -> () { - let _raw_trusted_registries = self.get_trusted_registries(); - let pd_str = "609e1d1364d607b027E577e10AD97c571b9518c1"; //"BD74DE9059CD63AC60c3AaC25c92a798be8D18b9"; // "e647e8e076cffA10425c0C49aAaC1036a3b2ddB5"; // TODO: factor better error - let public_directory_address = - <[u8; 20]>::from_hex(pd_str).expect("Invalid public directory contract address"); - let cot_str = "EBB6854aa875867f684dd1d2338eC20908039c67"; - let cot_address = - <[u8; 20]>::from_hex(cot_str).expect("Invalid chain of trust contract address"); - let t1 = TrustedRegistry { - period_seconds: 400, - start_up: 5, - public_directory: Contract { - chain_id: "648540".to_owned(), - contract_address: H160(public_directory_address), - }, - chain_of_trust: Contract { - chain_id: "648540".to_owned(), - contract_address: H160(cot_address), - }, - retry_period: 0, - }; - let mut trs: Vec = Vec::new(); - trs.push(t1); - self.registries = trs; + self.registries = TrustedRegistries::process_env_trusted_registries(); } fn set_start_up_and_period(&mut self) -> () { diff --git a/src/services/public_directory/data_interface.rs b/src/services/public_directory/data_interface.rs index 3f4ae9e..c8fab04 100644 --- a/src/services/public_directory/data_interface.rs +++ b/src/services/public_directory/data_interface.rs @@ -2,6 +2,7 @@ use crate::entities::entities::PublicDirectoryEntity; use crate::entities::models::PublicDirectoryActiveModel; use crate::entities::models::PublicDirectoryModel; use crate::services::trusted_registry::trusted_registry::Contract; +use crate::utils::utils::Utils; use sea_orm::ActiveModelTrait; use sea_orm::DatabaseConnection; use sea_orm::Set; @@ -21,7 +22,7 @@ impl DataInterfaceService { db: &DatabaseConnection, ) -> Result, sea_orm::DbErr> { PublicDirectoryEntity::find_by_contract_address( - &self.params.contract_address.to_string(), + &Utils::vec_u8_to_hex_string(self.params.contract_address.as_bytes().to_vec()).unwrap(), &self.params.chain_id, ) .one(db) @@ -109,7 +110,10 @@ impl DataInterfaceService { None => { let db_registry = PublicDirectoryActiveModel { id: Set(Uuid::new_v4()), - contract_address: Set(self.params.contract_address.to_string()), + contract_address: Set(Utils::vec_u8_to_hex_string( + self.params.contract_address.as_bytes().to_vec(), + ) + .unwrap()), upper_block: Set(*contract_last_block as i64), last_processed_block: Set(0), last_block_saved: Set(0), diff --git a/src/services/public_directory/public_directory_worker_service.rs b/src/services/public_directory/public_directory_worker_service.rs index fb04652..0512c16 100644 --- a/src/services/public_directory/public_directory_worker_service.rs +++ b/src/services/public_directory/public_directory_worker_service.rs @@ -462,7 +462,7 @@ impl PublicDirectoryWorkerService { } else if transaction_timestamp == exp { // revocation case scenario // TODO: MemberChanged with currentTimestamp==exp -> remove the entity did and all its dids from the database - info!("a member was removed"); + // info!("a member was removed"); } } Ok(prev_block) diff --git a/src/services/public_key/data_interface.rs b/src/services/public_key/data_interface.rs index 7afe25d..4670608 100644 --- a/src/services/public_key/data_interface.rs +++ b/src/services/public_key/data_interface.rs @@ -1,9 +1,18 @@ +use crate::databases::pool::Db; +use crate::dto::response::public_key_response_dto::PublicKeyResponseDto; use crate::entities::entities::PublicKeyEntity; use crate::entities::models::{PublicKeyActiveModel, PublicKeyModel}; -use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; +use crate::responses::error_message::ErrorMessage; +use crate::responses::generic_response::Responses; +use crate::responses::success_messages::SuccessMessage; +use rocket::serde::json::Json; +use sea_orm::{ActiveModelTrait, DatabaseConnection, PaginatorTrait, Set}; +use sea_orm_rocket::Connection; use uuid::Uuid; pub struct PublicKeyService {} +const DEFAULT_RESULTS_PER_PAGE: u64 = 10; + impl PublicKeyService { pub fn new() -> PublicKeyService { PublicKeyService {} @@ -102,4 +111,84 @@ impl PublicKeyService { Err(e) => return Err(e.into()), } } + + pub async fn get_all( + connection: Connection<'_, Db>, + page: Option, + page_size: Option, + public_directory_contract_address: &str, + chain_id: &str, + ) -> Responses>, Json>> { + let db = connection.into_inner(); + let page = page.unwrap_or(1); + let page_size = page_size.unwrap_or(DEFAULT_RESULTS_PER_PAGE); + let trace_id: Uuid = Uuid::new_v4(); + match page { + 0 => { + let message = "'page' param cannot be zero"; + error!("TRACE_ID: {}, DESCRIPTION: {}", trace_id, message); + return Responses::BadRequest(Json::from(ErrorMessage { + message, + trace_id: trace_id.to_string(), + })); + } + _ => {} + } + let paginator = + PublicKeyEntity::find_by_public_directory(public_directory_contract_address, chain_id) + .paginate(db, page_size.try_into().unwrap()); + let num_pages; + match paginator.num_pages().await { + Ok(r) => { + num_pages = r; + } + Err(e) => { + let message = "Internal error when retrieving public keys"; + error!("TRACE_ID: {}, DESCRIPTION: {}", trace_id, &e); + return Responses::BadRequest(Json::from(ErrorMessage { + message, + trace_id: trace_id.to_string(), + })); + } + } + + let result = paginator + .fetch_page((page - 1).try_into().unwrap()) + .await + .map(|r| { + r.into_iter() + .map(|el| String::from_utf8(el.jwk)) + .filter_map(|el| match el { + Ok(key) => Some(key), + _ => None, + }) + .map(|jwk_str| serde_json::from_str(&jwk_str)) + .filter_map(|el| match el { + Ok(jwk) => Some(jwk), + _ => None, + }) + .collect::>() + }); + + match result { + Ok(v) => { + return Responses::Sucess(Json::from(SuccessMessage { + data: PublicKeyResponseDto { + page, + results_per_page: page_size, + num_pages, + keys: v, + }, + trace_id: trace_id.to_string(), + })); + } + Err(e) => { + error!("TRACE_ID: {}, DESCRIPTION: {}", trace_id, &e); + return Responses::BadRequest(Json::from(ErrorMessage { + message: "Internal error when retrieving public keys", + trace_id: trace_id.to_string(), + })); + } + }; + } } diff --git a/src/services/trusted_registry/trusted_registry.rs b/src/services/trusted_registry/trusted_registry.rs index 9906e60..2907b8c 100644 --- a/src/services/trusted_registry/trusted_registry.rs +++ b/src/services/trusted_registry/trusted_registry.rs @@ -11,6 +11,7 @@ use crate::{ public_directory::index::PublicDirectoryService, public_directory::public_directory_worker_service::PublicDirectoryWorkerService, }, + utils::utils::Utils, }; #[derive(Deserialize, Serialize, Debug, Clone)] @@ -21,6 +22,7 @@ pub struct Contract { #[derive(Deserialize, Serialize, Debug, Clone)] pub struct TrustedRegistry { + pub index: String, pub public_directory: Contract, pub chain_of_trust: Contract, pub period_seconds: u64, @@ -59,12 +61,16 @@ impl TrustedRegistry { // TODO: match them with Chain Of Trust also match DidDataInterfaceService::find_all( &db, - &self.public_directory.contract_address.to_string(), + &Utils::vec_u8_to_hex_string( + self.public_directory.contract_address.as_bytes().to_vec(), + ) + .unwrap(), &self.public_directory.chain_id, ) .await { Ok(dids) => { + debug!("Dids to sweep {:?}", dids); for did in dids { match DidRegistryWorkerService::new(did.clone()).await { Ok(mut on_flight_did_registry_worker_service) => { diff --git a/src/utils/utils.rs b/src/utils/utils.rs index 87aac84..73eaaaf 100644 --- a/src/utils/utils.rs +++ b/src/utils/utils.rs @@ -51,4 +51,12 @@ impl Utils { None => None, } } + + pub fn trim_0x_from_hex_string(value: &str) -> String { + if value.starts_with("0x") { + value[2..].to_string() + } else { + value.to_owned() + } + } } From 09278bd0a609ccd5782e7924a578073e7802c5ee Mon Sep 17 00:00:00 2001 From: eum602 Date: Fri, 30 Jun 2023 21:22:34 -0500 Subject: [PATCH 25/25] fix: omit adding expired members in public directory --- .../public_directory_worker_service.rs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/services/public_directory/public_directory_worker_service.rs b/src/services/public_directory/public_directory_worker_service.rs index 0512c16..90d84cf 100644 --- a/src/services/public_directory/public_directory_worker_service.rs +++ b/src/services/public_directory/public_directory_worker_service.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, time::SystemTime}; use log::{debug, info}; use sea_orm::DatabaseConnection; @@ -354,7 +354,23 @@ impl PublicDirectoryWorkerService { let did = get_string_from_string_in_log(&member_changed_log, "did"); prev_block = get_u64_from_log(&member_changed_log, "prevBlock"); let transaction_timestamp = get_u64_from_log(&member_changed_log, "currentTimestap"); - if transaction_timestamp == iat { + let current_time; + match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { + Ok(d) => { + current_time = d.as_secs(); + } + Err(e) => { + return Err(e.into()); + } + } + if transaction_timestamp == iat && exp <= current_time { + info!( + "Skipping expired member: {} in Public Directory exp {:?}, current time {}", + did, exp, current_time + ); + continue; + } + if transaction_timestamp == iat && exp > current_time { // issuance case scenario info!("new member was added/updated {} {}", did, member_id); let pd_member_id: Uuid;