From 51b87ff79123ae339bb36d287b1cbc6353ddb116 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 01:21:48 -0400 Subject: [PATCH 01/45] updated existing tables, added new tables for recoveries, deletions --- schemas/database/001_deletions.sql | 3 +++ schemas/database/001_recoveries.sql | 4 ++++ schemas/database/002.init.down.sql | 8 ++++++++ schemas/database/002_init.up.sql | 14 ++++++++++++++ schemas/database/004_unprocessed_identities..sql | 8 ++++++++ 5 files changed, 37 insertions(+) create mode 100644 schemas/database/001_deletions.sql create mode 100644 schemas/database/001_recoveries.sql create mode 100644 schemas/database/002.init.down.sql create mode 100644 schemas/database/002_init.up.sql create mode 100644 schemas/database/004_unprocessed_identities..sql diff --git a/schemas/database/001_deletions.sql b/schemas/database/001_deletions.sql new file mode 100644 index 00000000..1b354d75 --- /dev/null +++ b/schemas/database/001_deletions.sql @@ -0,0 +1,3 @@ +CREATE TABLE deletions ( + leaf_index BIGINT, NOT NULL PRIMARY KEY, +) \ No newline at end of file diff --git a/schemas/database/001_recoveries.sql b/schemas/database/001_recoveries.sql new file mode 100644 index 00000000..2631b5fe --- /dev/null +++ b/schemas/database/001_recoveries.sql @@ -0,0 +1,4 @@ +CREATE TABLE recoveries ( + existing_commitment BYTEA NOT NULL UNIQUE, + new_commitment BYTEA NOT NULL UNIQUE, +) diff --git a/schemas/database/002.init.down.sql b/schemas/database/002.init.down.sql new file mode 100644 index 00000000..9a6dc981 --- /dev/null +++ b/schemas/database/002.init.down.sql @@ -0,0 +1,8 @@ +-- Drop the new primary key constraint +ALTER TABLE identities DROP CONSTRAINT identities_pkey; + +-- Restore the old primary key +ALTER TABLE identities ADD PRIMARY KEY (leaf_index); + +-- Drop the new 'id' column +ALTER TABLE identities DROP COLUMN id; diff --git a/schemas/database/002_init.up.sql b/schemas/database/002_init.up.sql new file mode 100644 index 00000000..b0e627cb --- /dev/null +++ b/schemas/database/002_init.up.sql @@ -0,0 +1,14 @@ +-- Add the new 'id' column +ALTER TABLE identities ADD COLUMN id BIGINT; + +-- Populate the new 'id' column (assuming leaf_index can be used) +UPDATE identities SET id = leaf_index; + +-- Set the new 'id' column as NOT NULL +ALTER TABLE identities ALTER COLUMN id SET NOT NULL; + +-- Drop the existing primary key +ALTER TABLE identities DROP CONSTRAINT identities_pkey; + +-- Set the new 'id' column as the primary key +ALTER TABLE identities ADD PRIMARY KEY (id); \ No newline at end of file diff --git a/schemas/database/004_unprocessed_identities..sql b/schemas/database/004_unprocessed_identities..sql new file mode 100644 index 00000000..355e9812 --- /dev/null +++ b/schemas/database/004_unprocessed_identities..sql @@ -0,0 +1,8 @@ +CREATE TABLE unprocessed_identities ( + commitment BYTEA NOT NULL UNIQUE, + status VARCHAR(50) NOT NULL, + created_at TIMESTAMPTZ NOT NULL, + processed_at TIMESTAMPTZ, + error_message TEXT + eligibility_timestamp TIMESTAMPTZ +) \ No newline at end of file From f97fc89ba3ceee315ba2b7820080526e07cac2c1 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 13:25:07 -0400 Subject: [PATCH 02/45] updated schemas --- schemas/database/002.init.down.sql | 8 -------- schemas/database/{002_init.up.sql => 004_init.up.sql} | 0 ...sed_identities..sql => 005_unprocessed_identities.sql} | 0 schemas/database/{001_deletions.sql => 006_deletions.sql} | 0 .../database/{001_recoveries.sql => 007_recoveries.sql} | 0 src/database/mod.rs | 8 +++++++- 6 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 schemas/database/002.init.down.sql rename schemas/database/{002_init.up.sql => 004_init.up.sql} (100%) rename schemas/database/{004_unprocessed_identities..sql => 005_unprocessed_identities.sql} (100%) rename schemas/database/{001_deletions.sql => 006_deletions.sql} (100%) rename schemas/database/{001_recoveries.sql => 007_recoveries.sql} (100%) diff --git a/schemas/database/002.init.down.sql b/schemas/database/002.init.down.sql deleted file mode 100644 index 9a6dc981..00000000 --- a/schemas/database/002.init.down.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Drop the new primary key constraint -ALTER TABLE identities DROP CONSTRAINT identities_pkey; - --- Restore the old primary key -ALTER TABLE identities ADD PRIMARY KEY (leaf_index); - --- Drop the new 'id' column -ALTER TABLE identities DROP COLUMN id; diff --git a/schemas/database/002_init.up.sql b/schemas/database/004_init.up.sql similarity index 100% rename from schemas/database/002_init.up.sql rename to schemas/database/004_init.up.sql diff --git a/schemas/database/004_unprocessed_identities..sql b/schemas/database/005_unprocessed_identities.sql similarity index 100% rename from schemas/database/004_unprocessed_identities..sql rename to schemas/database/005_unprocessed_identities.sql diff --git a/schemas/database/001_deletions.sql b/schemas/database/006_deletions.sql similarity index 100% rename from schemas/database/001_deletions.sql rename to schemas/database/006_deletions.sql diff --git a/schemas/database/001_recoveries.sql b/schemas/database/007_recoveries.sql similarity index 100% rename from schemas/database/001_recoveries.sql rename to schemas/database/007_recoveries.sql diff --git a/src/database/mod.rs b/src/database/mod.rs index 4ada308c..c591906d 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -614,6 +614,8 @@ mod test { use ethers::types::U256; use postgres_docker_utils::DockerContainerGuard; use semaphore::Field; + use sqlx::types::chrono::DateTime; + use sqlx::{PgPool, Row}; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; @@ -640,9 +642,13 @@ mod test { } async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { + dbg!("here"); + let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); + dbg!(&port); + let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { @@ -1062,7 +1068,7 @@ mod test { } #[tokio::test] - async fn check_identity_existance() -> anyhow::Result<()> { + async fn check_identity_existence() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let identities = mock_identities(2); From e437aa8b7c691cf72b75f34110dc608b71465648 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 13:50:41 -0400 Subject: [PATCH 03/45] updated schemas --- .../{004_init.up.sql => 004_identities.up.sql} | 0 ...entities.sql => 005_add_elligibility_timestamp.sql} | 2 +- src/database/mod.rs | 10 +++------- 3 files changed, 4 insertions(+), 8 deletions(-) rename schemas/database/{004_init.up.sql => 004_identities.up.sql} (100%) rename schemas/database/{005_unprocessed_identities.sql => 005_add_elligibility_timestamp.sql} (90%) diff --git a/schemas/database/004_init.up.sql b/schemas/database/004_identities.up.sql similarity index 100% rename from schemas/database/004_init.up.sql rename to schemas/database/004_identities.up.sql diff --git a/schemas/database/005_unprocessed_identities.sql b/schemas/database/005_add_elligibility_timestamp.sql similarity index 90% rename from schemas/database/005_unprocessed_identities.sql rename to schemas/database/005_add_elligibility_timestamp.sql index 355e9812..3a0505af 100644 --- a/schemas/database/005_unprocessed_identities.sql +++ b/schemas/database/005_add_elligibility_timestamp.sql @@ -3,6 +3,6 @@ CREATE TABLE unprocessed_identities ( status VARCHAR(50) NOT NULL, created_at TIMESTAMPTZ NOT NULL, processed_at TIMESTAMPTZ, - error_message TEXT + error_message TEXT, eligibility_timestamp TIMESTAMPTZ ) \ No newline at end of file diff --git a/src/database/mod.rs b/src/database/mod.rs index c591906d..e98d9eaa 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -329,7 +329,7 @@ impl Database { .into_iter() .map(|row| TreeUpdate { leaf_index: row.get::(0) as usize, - element: row.get::(1), + element: row.get::(1), }) .collect::>()) } @@ -642,18 +642,14 @@ mod test { } async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { - dbg!("here"); - let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); - dbg!(&port); - let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { - database: SecretUrl::from_str(&url)?, - database_migrate: true, + database: SecretUrl::from_str(&url)?, + database_migrate: true, database_max_connections: 1, }) .await?; From f00b8b3599e93dedf3984f68aec0d9bf93eedcd4 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 16:12:18 -0400 Subject: [PATCH 04/45] updated tables, added db functions to insert deletions and recoveries --- schemas/database/004_identities.up.sql | 8 +- .../005_add_elligibility_timestamp.sql | 9 +- schemas/database/006_deletions.sql | 2 +- schemas/database/007_recoveries.sql | 2 +- src/database/mod.rs | 102 ++++++++++++++++++ src/database/types.rs | 13 ++- 6 files changed, 118 insertions(+), 18 deletions(-) diff --git a/schemas/database/004_identities.up.sql b/schemas/database/004_identities.up.sql index b0e627cb..3c824bcf 100644 --- a/schemas/database/004_identities.up.sql +++ b/schemas/database/004_identities.up.sql @@ -1,12 +1,12 @@ -- Add the new 'id' column -ALTER TABLE identities ADD COLUMN id BIGINT; - --- Populate the new 'id' column (assuming leaf_index can be used) -UPDATE identities SET id = leaf_index; +ALTER TABLE identities ADD COLUMN id BIGSERIAL; -- Set the new 'id' column as NOT NULL ALTER TABLE identities ALTER COLUMN id SET NOT NULL; +-- Set the id to be unique +ALTER TABLE identities ADD CONSTRAINT id_unique UNIQUE(id); + -- Drop the existing primary key ALTER TABLE identities DROP CONSTRAINT identities_pkey; diff --git a/schemas/database/005_add_elligibility_timestamp.sql b/schemas/database/005_add_elligibility_timestamp.sql index 3a0505af..7473fe86 100644 --- a/schemas/database/005_add_elligibility_timestamp.sql +++ b/schemas/database/005_add_elligibility_timestamp.sql @@ -1,8 +1 @@ -CREATE TABLE unprocessed_identities ( - commitment BYTEA NOT NULL UNIQUE, - status VARCHAR(50) NOT NULL, - created_at TIMESTAMPTZ NOT NULL, - processed_at TIMESTAMPTZ, - error_message TEXT, - eligibility_timestamp TIMESTAMPTZ -) \ No newline at end of file +ALTER TABLE unprocessed_identities ADD COLUMN eligibility TIMESTAMPTZ; diff --git a/schemas/database/006_deletions.sql b/schemas/database/006_deletions.sql index 1b354d75..7166fb18 100644 --- a/schemas/database/006_deletions.sql +++ b/schemas/database/006_deletions.sql @@ -1,3 +1,3 @@ CREATE TABLE deletions ( - leaf_index BIGINT, NOT NULL PRIMARY KEY, + leaf_index BIGINT NOT NULL PRIMARY KEY ) \ No newline at end of file diff --git a/schemas/database/007_recoveries.sql b/schemas/database/007_recoveries.sql index 2631b5fe..bc731507 100644 --- a/schemas/database/007_recoveries.sql +++ b/schemas/database/007_recoveries.sql @@ -1,4 +1,4 @@ CREATE TABLE recoveries ( existing_commitment BYTEA NOT NULL UNIQUE, - new_commitment BYTEA NOT NULL UNIQUE, + new_commitment BYTEA NOT NULL UNIQUE ) diff --git a/src/database/mod.rs b/src/database/mod.rs index e98d9eaa..fe0eef21 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -15,6 +15,7 @@ use thiserror::Error; use tracing::{error, info, instrument, warn}; use self::prover::ProverConfiguration; +use self::types::RecoveryCommitments; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod prover; @@ -492,6 +493,73 @@ impl Database { Ok(identity) } + pub async fn insert_new_recovery( + &self, + existing_commitment: Hash, + new_commitment: Hash, + ) -> Result<(), Error> { + let query = sqlx::query( + r#" + INSERT INTO recoveries (existing_commitment, new_commitment) + VALUES ($1, $2) + "#, + ) + .bind(existing_commitment) + .bind(new_commitment); + self.pool.execute(query).await?; + Ok(()) + } + + //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + pub async fn get_recoveries(&self) -> Result, Error> { + let query = sqlx::query( + r#" + SELECT * + FROM recoveries + "#, + ); + + let result = self.pool.fetch_all(query).await?; + + Ok(result + .into_iter() + .map(|row| RecoveryCommitments { + existing_commitment: row.get::(0), + new_commitment: row.get::(1), + }) + .collect::>()) + } + + pub async fn insert_new_deletion(&self, leaf_index: i64) -> Result<(), Error> { + let query = sqlx::query( + r#" + INSERT INTO deletions (leaf_index) + VALUES ($1) + "#, + ) + .bind(leaf_index); + + self.pool.execute(query).await?; + Ok(()) + } + + //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + pub async fn get_deletions(&self) -> Result, Error> { + let query = sqlx::query( + r#" + SELECT * + FROM deletions + "#, + ); + + let result = self.pool.fetch_all(query).await?; + + Ok(result + .into_iter() + .map(|row| row.get::(0)) + .collect::>()) + } + pub async fn get_unprocessed_commitments( &self, status: Status, @@ -644,6 +712,7 @@ mod test { async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); + dbg!(&db_container.port()); let url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -707,6 +776,39 @@ mod test { Ok(()) } + #[tokio::test] + async fn insert_deletion() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + db.insert_new_deletion(0).await?; + db.insert_new_deletion(1).await?; + db.insert_new_deletion(2).await?; + db.insert_new_deletion(3).await?; + + let deletions = db.get_deletions().await?; + + assert_eq!(deletions.len(), 4); + + Ok(()) + } + + #[tokio::test] + async fn insert_recovery() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let old_identities = mock_identities(3); + let new_identities = mock_identities(3); + + for (old, new) in old_identities.into_iter().zip(new_identities) { + db.insert_new_recovery(old, new).await?; + } + + let recoveries = db.get_recoveries().await?; + assert_eq!(recoveries.len(), 3); + + Ok(()) + } + #[tokio::test] async fn get_last_leaf_index() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; diff --git a/src/database/types.rs b/src/database/types.rs index c59c2e79..54be0307 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -3,9 +3,14 @@ use chrono::{DateTime, Utc}; use crate::identity_tree::{Hash, Status}; pub struct UnprocessedCommitment { - pub commitment: Hash, - pub status: Status, - pub created_at: DateTime, - pub processed_at: Option>, + pub commitment: Hash, + pub status: Status, + pub created_at: DateTime, + pub processed_at: Option>, pub error_message: Option, } + +pub struct RecoveryCommitments { + pub existing_commitment: Hash, + pub new_commitment: Hash, +} From 386eb4a0fd6a48a3a325f477db9529ea75c4dcf6 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 16:43:15 -0400 Subject: [PATCH 05/45] added eligibility_timestamp to UnprocessedCommitment, added method to update eligibility_timestamp --- src/database/mod.rs | 54 ++++++++++++++++++++++++++++++++++++++++++- src/database/types.rs | 1 + 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index fe0eef21..b0958575 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,6 +7,7 @@ use std::collections::HashSet; use anyhow::{anyhow, Context, Error as ErrReport}; +use chrono::Utc; use clap::Parser; use sqlx::migrate::{Migrate, MigrateDatabase, Migrator}; use sqlx::pool::PoolOptions; @@ -584,6 +585,8 @@ impl Database { created_at: row.get::<_, _>(2), processed_at: row.get::<_, _>(3), error_message: row.get::<_, _>(4), + + eligibility_timestamp: row.get::<_, _>(5), }) .collect::>()) } @@ -643,6 +646,25 @@ impl Database { Ok(()) } + pub async fn update_eligibility_timestamp( + &self, + commitment: Hash, + eligibility_timestamp: sqlx::types::chrono::DateTime, + ) -> Result<(), Error> { + let query = sqlx::query( + r#" + UPDATE unprocessed_identities SET eligibility = $1 + WHERE commitment = $3 + "#, + ) + .bind(eligibility_timestamp) + .bind(commitment); + + self.pool.execute(query).await?; + + Ok(()) + } + pub async fn identity_exists(&self, commitment: Hash) -> Result { let query_unprocessed_identity = sqlx::query( r#"SELECT exists(SELECT 1 from unprocessed_identities where commitment = $1)"#, @@ -678,7 +700,7 @@ mod test { use std::time::Duration; use anyhow::Context; - use chrono::Utc; + use chrono::{Days, Utc}; use ethers::types::U256; use postgres_docker_utils::DockerContainerGuard; use semaphore::Field; @@ -776,6 +798,36 @@ mod test { Ok(()) } + #[tokio::test] + async fn test_update_eligibility_timestamp() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let dec = "1234500000000000000"; + let commit_hash: Hash = U256::from_dec_str(dec) + .expect("cant convert to u256") + .into(); + + db.insert_new_identity(commit_hash).await?; + + let eligibility_timestamp = DateTime::from(Utc::now()) + .checked_add_days(Days::new(7)) + .expect("Could not create eligibility timestamp"); + + db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) + .await?; + + let commitments = db.get_unprocessed_commitments(Status::Pending).await?; + assert_eq!(commitments.len(), 1); + + assert_eq!( + commitments[0] + .eligibility_timestamp + .expect("Could not get eligibility_timestamp from commitment"), + eligibility_timestamp + ); + + Ok(()) + } + #[tokio::test] async fn insert_deletion() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; diff --git a/src/database/types.rs b/src/database/types.rs index 54be0307..40cc6de5 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -8,6 +8,7 @@ pub struct UnprocessedCommitment { pub created_at: DateTime, pub processed_at: Option>, pub error_message: Option, + pub eligibility_timestamp: Option>, } pub struct RecoveryCommitments { From ddfd9ffcde97c199fb9ec1f6d7979770ef9514f2 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 16:43:34 -0400 Subject: [PATCH 06/45] chore: remove dbg --- src/database/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index b0958575..58df2e9c 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -734,8 +734,6 @@ mod test { async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); - dbg!(&db_container.port()); - let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { From 6b563a3a2d6b40ca4780715ff17e9307d19cc182 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 17:32:16 -0400 Subject: [PATCH 07/45] updated deletions table, added type to represent deletion and recovery entries --- schemas/database/006_deletions.sql | 3 ++- src/database/mod.rs | 35 +++++++++++++++++------------- src/database/types.rs | 7 +++++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/schemas/database/006_deletions.sql b/schemas/database/006_deletions.sql index 7166fb18..9aa00e06 100644 --- a/schemas/database/006_deletions.sql +++ b/schemas/database/006_deletions.sql @@ -1,3 +1,4 @@ CREATE TABLE deletions ( - leaf_index BIGINT NOT NULL PRIMARY KEY + leaf_index BIGINT NOT NULL PRIMARY KEY + commitment BYTEA NOT NULL UNIQUE, ) \ No newline at end of file diff --git a/src/database/mod.rs b/src/database/mod.rs index 58df2e9c..88a92d19 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -16,7 +16,7 @@ use thiserror::Error; use tracing::{error, info, instrument, warn}; use self::prover::ProverConfiguration; -use self::types::RecoveryCommitments; +use self::types::{DeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod prover; @@ -512,7 +512,7 @@ impl Database { } //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 - pub async fn get_recoveries(&self) -> Result, Error> { + pub async fn get_recoveries(&self) -> Result, Error> { let query = sqlx::query( r#" SELECT * @@ -524,28 +524,29 @@ impl Database { Ok(result .into_iter() - .map(|row| RecoveryCommitments { + .map(|row| RecoveryEntry { existing_commitment: row.get::(0), new_commitment: row.get::(1), }) - .collect::>()) + .collect::>()) } - pub async fn insert_new_deletion(&self, leaf_index: i64) -> Result<(), Error> { + pub async fn insert_new_deletion(&self, leaf_index: i64, identity: &Hash) -> Result<(), Error> { let query = sqlx::query( r#" - INSERT INTO deletions (leaf_index) - VALUES ($1) + INSERT INTO deletions (leaf_index, commitment) + VALUES ($1, $2) "#, ) - .bind(leaf_index); + .bind(leaf_index) + .bind(identity); self.pool.execute(query).await?; Ok(()) } //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 - pub async fn get_deletions(&self) -> Result, Error> { + pub async fn get_deletions(&self) -> Result, Error> { let query = sqlx::query( r#" SELECT * @@ -557,8 +558,11 @@ impl Database { Ok(result .into_iter() - .map(|row| row.get::(0)) - .collect::>()) + .map(|row| DeletionEntry { + leaf_index: row.get::(0), + commitment: row.get::(1), + }) + .collect::>()) } pub async fn get_unprocessed_commitments( @@ -829,11 +833,12 @@ mod test { #[tokio::test] async fn insert_deletion() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; + let identities = mock_identities(3); - db.insert_new_deletion(0).await?; - db.insert_new_deletion(1).await?; - db.insert_new_deletion(2).await?; - db.insert_new_deletion(3).await?; + db.insert_new_deletion(0, &identities[0]).await?; + db.insert_new_deletion(1, &identities[1]).await?; + db.insert_new_deletion(2, &identities[2]).await?; + db.insert_new_deletion(3, &identities[3]).await?; let deletions = db.get_deletions().await?; diff --git a/src/database/types.rs b/src/database/types.rs index 40cc6de5..6ba69505 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -11,7 +11,12 @@ pub struct UnprocessedCommitment { pub eligibility_timestamp: Option>, } -pub struct RecoveryCommitments { +pub struct RecoveryEntry { pub existing_commitment: Hash, pub new_commitment: Hash, } + +pub struct DeletionEntry { + pub leaf_index: i64, //TODO: consider using a larger type for leaf indices + pub commitment: Hash, +} From b8e4d5d04a95abd7b064aca5a84a91ba027da016 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 17:59:27 -0400 Subject: [PATCH 08/45] updated deletion table, updated insert deletion test --- ...y_timestamp.sql => 005_add_eligibility_timestamp.sql} | 0 schemas/database/006_deletions.sql | 4 ++-- src/database/mod.rs | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) rename schemas/database/{005_add_elligibility_timestamp.sql => 005_add_eligibility_timestamp.sql} (100%) diff --git a/schemas/database/005_add_elligibility_timestamp.sql b/schemas/database/005_add_eligibility_timestamp.sql similarity index 100% rename from schemas/database/005_add_elligibility_timestamp.sql rename to schemas/database/005_add_eligibility_timestamp.sql diff --git a/schemas/database/006_deletions.sql b/schemas/database/006_deletions.sql index 9aa00e06..c5ec8ef6 100644 --- a/schemas/database/006_deletions.sql +++ b/schemas/database/006_deletions.sql @@ -1,4 +1,4 @@ CREATE TABLE deletions ( - leaf_index BIGINT NOT NULL PRIMARY KEY - commitment BYTEA NOT NULL UNIQUE, + leaf_index BIGINT NOT NULL PRIMARY KEY, + commitment BYTEA NOT NULL UNIQUE ) \ No newline at end of file diff --git a/src/database/mod.rs b/src/database/mod.rs index 88a92d19..84b50ad1 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -658,7 +658,7 @@ impl Database { let query = sqlx::query( r#" UPDATE unprocessed_identities SET eligibility = $1 - WHERE commitment = $3 + WHERE commitment = $2 "#, ) .bind(eligibility_timestamp) @@ -831,24 +831,23 @@ mod test { } #[tokio::test] - async fn insert_deletion() -> anyhow::Result<()> { + async fn test_insert_deletion() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let identities = mock_identities(3); db.insert_new_deletion(0, &identities[0]).await?; db.insert_new_deletion(1, &identities[1]).await?; db.insert_new_deletion(2, &identities[2]).await?; - db.insert_new_deletion(3, &identities[3]).await?; let deletions = db.get_deletions().await?; - assert_eq!(deletions.len(), 4); + assert_eq!(deletions.len(), 3); Ok(()) } #[tokio::test] - async fn insert_recovery() -> anyhow::Result<()> { + async fn test_insert_recovery() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let old_identities = mock_identities(3); From 080c24adfe62540c172a1d301747942918162d2a Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 18:02:57 -0400 Subject: [PATCH 09/45] updated get_unprocessed_commitments to only get entries that are eligible --- src/database/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 84b50ad1..05878455 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -572,7 +572,7 @@ impl Database { let query = sqlx::query( r#" SELECT * FROM unprocessed_identities - WHERE status = $1 + WHERE status = $1 AND CURRENT_TIMESTAMP > eligibility LIMIT $2 "#, ) From 9324bc0df89ab1480d96a34e9aa5575db4b295e7 Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:58:07 -0400 Subject: [PATCH 10/45] Feat: Deletion/Recovery API Updates (#586) * added deletion and recovery endpoints, added app functions for deletion * added deletion prover map * added prover_type to separate deletion and insertion provers * added prover_type during batch size removal * moved custom middleware * updated prover table migration * patching tests, added get_eligible_unprocessed_commitments * patched test_update_eligibility_timestamp * patched dynamic_batch_sizes * chore: cargo fmt * updated delete_identity to check if id has already been deleted or queued for deletion * updated recover_identity to delete existing commitment, and insert data in to recoveries table * removed unused function * added new tests for new database/identity manager logic * added new tests * fix: imported IdentityManager into test mod * updated IdentityManager tests * updated database tests * patched test_remove_prover * separated generate_proof into generate_insertion_proof and generate_deletion_proof * patched test_insert_provers * updated provers db schema, updated insert_prover_configuration test * removed commented out tests, will reimplement * removed todo --- schemas/database/008_prover_type.sql | 28 + src/app.rs | 156 ++++- src/contracts/mod.rs | 60 +- src/database/mod.rs | 367 ++++++++-- src/database/prover.rs | 25 - src/database/types.rs | 16 +- src/identity_tree.rs | 12 + src/prover/batch_insertion/mod.rs | 588 ---------------- src/prover/{batch_insertion => }/identity.rs | 0 src/prover/map.rs | 50 +- src/prover/mod.rs | 634 +++++++++++++++++- .../mod.rs} | 0 src/server/error.rs | 6 + src/server/mod.rs | 57 +- src/task_monitor/tasks/process_identities.rs | 4 +- tests/common/mod.rs | 13 +- tests/common/prover_mock.rs | 42 +- tests/dynamic_batch_sizes.rs | 34 +- 18 files changed, 1338 insertions(+), 754 deletions(-) create mode 100644 schemas/database/008_prover_type.sql delete mode 100644 src/database/prover.rs delete mode 100644 src/prover/batch_insertion/mod.rs rename src/prover/{batch_insertion => }/identity.rs (100%) rename src/server/{custom_middleware.rs => custom_middleware/mod.rs} (100%) diff --git a/schemas/database/008_prover_type.sql b/schemas/database/008_prover_type.sql new file mode 100644 index 00000000..651c9ce0 --- /dev/null +++ b/schemas/database/008_prover_type.sql @@ -0,0 +1,28 @@ +-- Create ENUM for prover type +CREATE TYPE prover_enum AS ENUM('Insertion', 'Deletion'); + +-- Add new column with the enum +ALTER TABLE provers ADD COLUMN prover_type prover_enum; + +-- Update the new column, setting all existing provers as insertions +UPDATE provers SET prover_type = 'Insertion' WHERE prover_type IS NULL; + +-- Make the column NOT NULL +ALTER TABLE provers ALTER COLUMN prover_type SET NOT NULL; + +-- Drop batch size as the primary key +ALTER TABLE provers DROP CONSTRAINT provers_pkey; + +-- Drop the url uniqueness constraint +ALTER TABLE provers DROP CONSTRAINT IF EXISTS provers_url_key; + + + + + + + + + + + diff --git a/src/app.rs b/src/app.rs index 2e605a77..764577fc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,23 +3,23 @@ use std::sync::Arc; use std::time::Instant; use anyhow::Result as AnyhowResult; +use chrono::{DateTime, Utc}; use clap::Parser; use hyper::StatusCode; +use ruint::Uint; use semaphore::poseidon_tree::LazyPoseidonTree; use semaphore::protocol::verify_proof; use serde::Serialize; use tracing::{info, instrument, warn}; use crate::contracts::{IdentityManager, SharedIdentityManager}; -use crate::database::prover::{ProverConfiguration as DbProverConf, Provers}; use crate::database::{self, Database}; use crate::ethereum::{self, Ethereum}; use crate::identity_tree::{ - CanonicalTreeBuilder, Hash, InclusionProof, RootItem, Status, TreeState, + CanonicalTreeBuilder, Hash, InclusionProof, RootItem, Status, TreeState, TreeVersionReadOps, }; -use crate::prover::batch_insertion::ProverConfiguration; -use crate::prover::map::make_insertion_map; -use crate::prover::{self, batch_insertion}; +use crate::prover::map::initialize_prover_maps; +use crate::prover::{self, ProverConfiguration, ProverType, Provers}; use crate::server::error::Error as ServerError; use crate::server::{ToResponseCode, VerifySemaphoreProofRequest}; use crate::task_monitor::TaskMonitor; @@ -110,7 +110,7 @@ pub struct Options { pub database: database::Options, #[clap(flatten)] - pub batch_provers: prover::batch_insertion::Options, + pub batch_provers: prover::Options, #[clap(flatten)] pub committer: task_monitor::Options, @@ -153,14 +153,22 @@ impl App { let (ethereum, db) = tokio::try_join!(ethereum, db)?; let database = Arc::new(db); - let mut provers = database.get_provers().await?; + let mut provers: HashSet = database.get_provers().await?; + + // TODO: need to update this let non_inserted_provers = Self::merge_env_provers(options.batch_provers, &mut provers); database.insert_provers(non_inserted_provers).await?; - let insertion_prover_map = make_insertion_map(provers)?; - let identity_manager = - IdentityManager::new(options.contracts, ethereum.clone(), insertion_prover_map).await?; + let (insertion_prover_map, deletion_prover_map) = initialize_prover_maps(provers)?; + + let identity_manager = IdentityManager::new( + options.contracts, + ethereum.clone(), + insertion_prover_map, + deletion_prover_map, + ) + .await?; let identity_manager = Arc::new(identity_manager); @@ -296,10 +304,11 @@ impl App { return Err(ServerError::InvalidCommitment); } - if !self.identity_manager.has_provers().await { + if !self.identity_manager.has_insertion_provers().await { warn!( ?commitment, - "Identity Manager has no provers. Add provers with /addBatchSize request." + "Identity Manager has no insertion provers. Add provers with /addBatchSize \ + request." ); return Err(ServerError::NoProversOnIdInsert); } @@ -317,23 +326,109 @@ impl App { return Err(ServerError::DuplicateCommitment); } - self.database.insert_new_identity(commitment).await?; + self.database + .insert_new_identity(commitment, DateTime::from(Utc::now())) + .await?; Ok(()) } - fn merge_env_provers( - options: batch_insertion::Options, - existing_provers: &mut Provers, - ) -> Provers { - let options_set: HashSet = options + /// Queues a deletion from the merkle tree. + /// + /// # Errors + /// + /// Will return `Err` if identity is already queued, not in the tree, or the + /// queue malfunctions. + #[instrument(level = "debug", skip(self))] + pub async fn delete_identity(&self, commitment: &Hash) -> Result<(), ServerError> { + // Ensure that deletion provers exist + if !self.identity_manager.has_deletion_provers().await { + warn!( + ?commitment, + "Identity Manager has no deletion provers. Add provers with /addBatchSize request." + ); + return Err(ServerError::NoProversOnIdDeletion); + } + + // Get the leaf index for the id commitment + let leaf_index = self + .database + .get_identity_leaf_index(&commitment) + .await? + .ok_or(ServerError::IdentityCommitmentNotFound)? + .leaf_index; + + // Check if the id has already been deleted + if self.tree_state.get_latest_tree().get_leaf(leaf_index) == Uint::ZERO { + return Err(ServerError::IdentityAlreadyDeleted); + } + + // Check if the id is already queued for deletion + if self + .database + .identity_is_queued_for_deletion(commitment) + .await? + { + return Err(ServerError::IdentityQueuedForDeletion); + } + + // If the id has not been deleted, insert into the deletions table + self.database + .insert_new_deletion(leaf_index, &commitment) + .await?; + + Ok(()) + } + + /// Queues a deletion from the merkle tree. + /// + /// # Errors + /// + /// Will return `Err` if identity is already queued, not in the tree, or the + /// queue malfunctions. + #[instrument(level = "debug", skip(self))] + pub async fn recover_identity( + &self, + existing_commitment: &Hash, + new_commitment: &Hash, + ) -> Result<(), ServerError> { + // Ensure that insertion provers exist + if !self.identity_manager.has_insertion_provers().await { + warn!( + ?new_commitment, + "Identity Manager has no provers. Add provers with /addBatchSize request." + ); + return Err(ServerError::NoProversOnIdInsert); + } + + // Ensure that deletion provers exist + if !self.identity_manager.has_deletion_provers().await { + warn!( + ?new_commitment, + "Identity Manager has no deletion provers. Add provers with /addBatchSize request." + ); + return Err(ServerError::NoProversOnIdDeletion); + } + + // Delete the existing id and insert the commitments into the recovery table + self.delete_identity(&existing_commitment).await?; + self.database + .insert_new_recovery(&existing_commitment, &new_commitment) + .await?; + + Ok(()) + } + + fn merge_env_provers(options: prover::Options, existing_provers: &mut Provers) -> Provers { + let options_set: HashSet = options .prover_urls .0 .into_iter() - .map(|opt| DbProverConf { - url: opt.url, - batch_size: opt.batch_size, - timeout_s: opt.timeout_s, + .map(|opt| ProverConfiguration { + url: opt.url, + batch_size: opt.batch_size, + timeout_s: opt.timeout_s, + prover_type: opt.prover_type, }) .collect(); @@ -360,13 +455,14 @@ impl App { url: String, batch_size: usize, timeout_seconds: u64, + prover_type: ProverType, ) -> Result<(), ServerError> { self.identity_manager - .add_batch_size(&url, batch_size, timeout_seconds) + .add_batch_size(&url, batch_size, timeout_seconds, prover_type) .await?; self.database - .insert_prover_configuration(batch_size, url, timeout_seconds) + .insert_prover_configuration(batch_size, url, timeout_seconds, prover_type) .await?; Ok(()) @@ -377,10 +473,16 @@ impl App { /// Will return `Err` if the requested batch size does not exist. /// Will return `Err` if batch size fails to be removed from database. #[instrument(level = "debug", skip(self))] - pub async fn remove_batch_size(&self, batch_size: usize) -> Result<(), ServerError> { - self.identity_manager.remove_batch_size(batch_size).await?; + pub async fn remove_batch_size( + &self, + batch_size: usize, + prover_type: ProverType, + ) -> Result<(), ServerError> { + self.identity_manager + .remove_batch_size(batch_size, prover_type) + .await?; - self.database.remove_prover(batch_size).await?; + self.database.remove_prover(batch_size, prover_type).await?; Ok(()) } diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index c5c52d3b..4686f796 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -15,9 +15,9 @@ use tracing::{error, info, instrument, warn}; use self::abi::{BridgedWorldId, WorldId}; use crate::ethereum::write::TransactionId; use crate::ethereum::{Ethereum, ReadProvider}; -use crate::prover::batch_insertion::ProverConfiguration; -use crate::prover::map::{InsertionProverMap, ReadOnlyInsertionProver}; -use crate::prover::{batch_insertion, Proof, ReadOnlyProver}; +use crate::prover::identity::Identity; +use crate::prover::map::{DeletionProverMap, InsertionProverMap, ReadOnlyInsertionProver}; +use crate::prover::{Proof, Prover, ProverConfiguration, ProverType, ReadOnlyProver}; use crate::serde_utils::JsonStrWrapper; use crate::server::error::Error as ServerError; @@ -55,12 +55,13 @@ pub struct Options { /// contract. #[derive(Debug)] pub struct IdentityManager { - ethereum: Ethereum, + ethereum: Ethereum, insertion_prover_map: InsertionProverMap, - abi: WorldId, - secondary_abis: Vec>, - initial_leaf_value: Field, - tree_depth: usize, + deletion_prover_map: DeletionProverMap, + abi: WorldId, + secondary_abis: Vec>, + initial_leaf_value: Field, + tree_depth: usize, } impl IdentityManager { @@ -69,6 +70,7 @@ impl IdentityManager { options: Options, ethereum: Ethereum, insertion_prover_map: InsertionProverMap, + deletion_prover_map: DeletionProverMap, ) -> anyhow::Result where Self: Sized, @@ -118,6 +120,7 @@ impl IdentityManager { let identity_manager = Self { ethereum, insertion_prover_map, + deletion_prover_map, abi, secondary_abis, initial_leaf_value, @@ -143,10 +146,7 @@ impl IdentityManager { /// Validates that merkle proofs are of the correct length against tree /// depth - pub fn validate_merkle_proofs( - &self, - identity_commitments: &[batch_insertion::Identity], - ) -> anyhow::Result<()> { + pub fn validate_merkle_proofs(&self, identity_commitments: &[Identity]) -> anyhow::Result<()> { for id in identity_commitments { if id.merkle_proof.len() != self.tree_depth { return Err(anyhow!(format!( @@ -163,7 +163,7 @@ impl IdentityManager { pub async fn get_suitable_prover( &self, num_identities: usize, - ) -> anyhow::Result> { + ) -> anyhow::Result> { let prover_map = self.insertion_prover_map.read().await; match RwLockReadGuard::try_map(prover_map, |map| map.get(num_identities)) { @@ -175,12 +175,12 @@ impl IdentityManager { } #[instrument(level = "debug", skip(prover, identity_commitments))] - pub async fn prepare_proof( + pub async fn prepare_insertion_proof( prover: ReadOnlyInsertionProver<'_>, start_index: usize, pre_root: U256, post_root: U256, - identity_commitments: &[batch_insertion::Identity], + identity_commitments: &[Identity], ) -> anyhow::Result { let batch_size = identity_commitments.len(); @@ -193,7 +193,7 @@ impl IdentityManager { ); let proof_data: Proof = prover - .generate_proof( + .generate_insertion_proof( actual_start_index, pre_root, post_root, @@ -210,7 +210,7 @@ impl IdentityManager { start_index: usize, pre_root: U256, post_root: U256, - identity_commitments: Vec, + identity_commitments: Vec, proof_data: Proof, ) -> anyhow::Result { let actual_start_index: u32 = start_index.try_into()?; @@ -309,16 +309,21 @@ impl IdentityManager { url: &impl ToString, batch_size: usize, timeout_seconds: u64, + prover_type: ProverType, ) -> Result<(), ServerError> { - let mut map = self.insertion_prover_map.write().await; + let mut map = match prover_type { + ProverType::Insertion => self.insertion_prover_map.write().await, + ProverType::Deletion => self.deletion_prover_map.write().await, + }; if map.batch_size_exists(batch_size) { return Err(ServerError::BatchSizeAlreadyExists); } - let prover = batch_insertion::Prover::new(&ProverConfiguration { + let prover = Prover::new(&ProverConfiguration { url: url.to_string(), batch_size, + prover_type, timeout_s: timeout_seconds, })?; @@ -331,8 +336,15 @@ impl IdentityManager { /// /// Will return `Err` if the batch size requested for removal doesn't exist /// in the prover map. - pub async fn remove_batch_size(&self, batch_size: usize) -> Result<(), ServerError> { - let mut map = self.insertion_prover_map.write().await; + pub async fn remove_batch_size( + &self, + batch_size: usize, + prover_type: ProverType, + ) -> Result<(), ServerError> { + let mut map = match prover_type { + ProverType::Insertion => self.insertion_prover_map.write().await, + ProverType::Deletion => self.deletion_prover_map.write().await, + }; if map.len() == 1 { warn!("Attempting to remove the last batch size."); @@ -353,9 +365,13 @@ impl IdentityManager { .as_configuration_vec()) } - pub async fn has_provers(&self) -> bool { + pub async fn has_insertion_provers(&self) -> bool { self.insertion_prover_map.read().await.len() > 0 } + + pub async fn has_deletion_provers(&self) -> bool { + self.deletion_prover_map.read().await.len() > 0 + } } /// A type for an identity manager object that can be sent across threads. diff --git a/src/database/mod.rs b/src/database/mod.rs index 05878455..326eec7b 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -15,12 +15,11 @@ use sqlx::{Executor, Pool, Postgres, Row}; use thiserror::Error; use tracing::{error, info, instrument, warn}; -use self::prover::ProverConfiguration; use self::types::{DeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; -pub mod prover; pub mod types; +use crate::prover::{self, ProverConfiguration, ProverType, Provers}; use crate::secret::SecretUrl; // Statically link in migration files @@ -331,7 +330,7 @@ impl Database { .into_iter() .map(|row| TreeUpdate { leaf_index: row.get::(0) as usize, - element: row.get::(1), + element: row.get::(1), }) .collect::>()) } @@ -395,10 +394,10 @@ impl Database { Ok(result.get::(0) as i32) } - pub async fn get_provers(&self) -> Result { + pub async fn get_provers(&self) -> Result { let query = sqlx::query( r#" - SELECT batch_size, url, timeout_s + SELECT batch_size, url, timeout_s, prover_type FROM provers "#, ); @@ -411,13 +410,15 @@ impl Database { let batch_size = row.get::(0) as usize; let url = row.get::(1); let timeout_s = row.get::(2) as u64; - prover::ProverConfiguration { + let prover_type = row.get::(3); + ProverConfiguration { url, batch_size, timeout_s, + prover_type, } }) - .collect::()) + .collect::()) } pub async fn insert_prover_configuration( @@ -425,20 +426,20 @@ impl Database { batch_size: usize, url: impl ToString, timeout_seconds: u64, + prover_type: ProverType, ) -> Result<(), Error> { let url = url.to_string(); let query = sqlx::query( r#" - INSERT INTO provers (batch_size, url, timeout_s) - VALUES ($1, $2, $3) - ON CONFLICT (batch_size) - DO UPDATE SET (url, timeout_s) = ($2, $3) + INSERT INTO provers (batch_size, url, timeout_s, prover_type) + VALUES ($1, $2, $3, $4) "#, ) .bind(batch_size as i64) .bind(url) - .bind(timeout_seconds as i64); + .bind(timeout_seconds as i64) + .bind(prover_type); self.pool.execute(query).await?; @@ -452,14 +453,15 @@ impl Database { let mut query_builder = sqlx::QueryBuilder::new( r#" - INSERT INTO provers (batch_size, url, timeout_s) + INSERT INTO provers (batch_size, url, timeout_s, prover_type) "#, ); query_builder.push_values(provers, |mut b, prover| { b.push_bind(prover.batch_size as i64) .push_bind(prover.url) - .push_bind(prover.timeout_s as i64); + .push_bind(prover.timeout_s as i64) + .push_bind(prover.prover_type); }); let query = query_builder.build(); @@ -468,36 +470,47 @@ impl Database { Ok(()) } - pub async fn remove_prover(&self, batch_size: usize) -> Result<(), Error> { + pub async fn remove_prover( + &self, + batch_size: usize, + prover_type: ProverType, + ) -> Result<(), Error> { let query = sqlx::query( r#" - DELETE FROM provers WHERE batch_size = $1 + DELETE FROM provers WHERE batch_size = $1 AND prover_type = $2 "#, ) - .bind(batch_size as i64); + .bind(batch_size as i64) + .bind(prover_type); self.pool.execute(query).await?; Ok(()) } - pub async fn insert_new_identity(&self, identity: Hash) -> Result { + pub async fn insert_new_identity( + &self, + identity: Hash, + eligibility_timestamp: sqlx::types::chrono::DateTime, + ) -> Result { let query = sqlx::query( r#" - INSERT INTO unprocessed_identities (commitment, status, created_at) - VALUES ($1, $2, CURRENT_TIMESTAMP) + INSERT INTO unprocessed_identities (commitment, status, created_at, eligibility) + VALUES ($1, $2, CURRENT_TIMESTAMP, $3) "#, ) .bind(identity) - .bind(<&str>::from(Status::New)); + .bind(<&str>::from(Status::New)) + .bind(eligibility_timestamp); + self.pool.execute(query).await?; Ok(identity) } pub async fn insert_new_recovery( &self, - existing_commitment: Hash, - new_commitment: Hash, + existing_commitment: &Hash, + new_commitment: &Hash, ) -> Result<(), Error> { let query = sqlx::query( r#" @@ -511,7 +524,8 @@ impl Database { Ok(()) } - //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + // TODO: consider using a larger value than i64 for leaf index, ruint should + // have postgres compatibility for u256 pub async fn get_recoveries(&self) -> Result, Error> { let query = sqlx::query( r#" @@ -526,26 +540,31 @@ impl Database { .into_iter() .map(|row| RecoveryEntry { existing_commitment: row.get::(0), - new_commitment: row.get::(1), + new_commitment: row.get::(1), }) .collect::>()) } - pub async fn insert_new_deletion(&self, leaf_index: i64, identity: &Hash) -> Result<(), Error> { + pub async fn insert_new_deletion( + &self, + leaf_index: usize, + identity: &Hash, + ) -> Result<(), Error> { let query = sqlx::query( r#" INSERT INTO deletions (leaf_index, commitment) VALUES ($1, $2) "#, ) - .bind(leaf_index) + .bind(leaf_index as i64) .bind(identity); self.pool.execute(query).await?; Ok(()) } - //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + // TODO: consider using a larger value than i64 for leaf index, ruint should + // have postgres compatibility for u256 pub async fn get_deletions(&self) -> Result, Error> { let query = sqlx::query( r#" @@ -565,7 +584,7 @@ impl Database { .collect::>()) } - pub async fn get_unprocessed_commitments( + pub async fn get_eligible_unprocessed_commitments( &self, status: Status, ) -> Result, Error> { @@ -581,6 +600,35 @@ impl Database { let result = self.pool.fetch_all(query).await?; + Ok(result + .into_iter() + .map(|row| types::UnprocessedCommitment { + commitment: row.get::(0), + status, + created_at: row.get::<_, _>(2), + processed_at: row.get::<_, _>(3), + error_message: row.get::<_, _>(4), + eligibility_timestamp: row.get::<_, _>(5), + }) + .collect::>()) + } + + pub async fn get_unprocessed_commitments( + &self, + status: Status, + ) -> Result, Error> { + let query = sqlx::query( + r#" + SELECT * FROM unprocessed_identities + WHERE status = $1 + LIMIT $2 + "#, + ) + .bind(<&str>::from(status)) + .bind(MAX_UNPROCESSED_FETCH_COUNT); + + let result = self.pool.fetch_all(query).await?; + Ok(result .into_iter() .map(|row| types::UnprocessedCommitment { @@ -650,6 +698,7 @@ impl Database { Ok(()) } + // TODO: add docs pub async fn update_eligibility_timestamp( &self, commitment: Hash, @@ -671,14 +720,14 @@ impl Database { pub async fn identity_exists(&self, commitment: Hash) -> Result { let query_unprocessed_identity = sqlx::query( - r#"SELECT exists(SELECT 1 from unprocessed_identities where commitment = $1)"#, + r#"SELECT exists(SELECT 1 FROM unprocessed_identities where commitment = $1)"#, ) .bind(commitment); let row_unprocessed = self.pool.fetch_one(query_unprocessed_identity).await?; let query_processed_identity = - sqlx::query(r#"SELECT exists(SELECT 1 from identities where commitment = $1)"#) + sqlx::query(r#"SELECT exists(SELECT 1 FROM identities where commitment = $1)"#) .bind(commitment); let row_processed = self.pool.fetch_one(query_processed_identity).await?; @@ -687,6 +736,15 @@ impl Database { Ok(exists) } + + // TODO: add docs + pub async fn identity_is_queued_for_deletion(&self, commitment: &Hash) -> Result { + let query_queued_deletion = + sqlx::query(r#"SELECT exists(SELECT 1 FROM deletions where commitment = $1)"#) + .bind(commitment); + let row_unprocessed = self.pool.fetch_one(query_queued_deletion).await?; + Ok(row_unprocessed.get::(0)) + } } #[derive(Debug, Error)] @@ -700,6 +758,7 @@ pub enum Error { #[cfg(test)] mod test { + use std::collections::HashSet; use std::str::FromStr; use std::time::Duration; @@ -707,12 +766,14 @@ mod test { use chrono::{Days, Utc}; use ethers::types::U256; use postgres_docker_utils::DockerContainerGuard; + use ruint::Uint; use semaphore::Field; use sqlx::types::chrono::DateTime; use sqlx::{PgPool, Row}; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; + use crate::prover::{ProverConfiguration, ProverType}; use crate::secret::SecretUrl; macro_rules! assert_same_time { @@ -735,14 +796,16 @@ mod test { chrono::Duration::milliseconds(x.num_milliseconds().abs()) } + // TODO: we should probably consolidate all tests that propagate errors to + // TODO: either use anyhow or eyre async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { - database: SecretUrl::from_str(&url)?, - database_migrate: true, + database: SecretUrl::from_str(&url)?, + database_migrate: true, database_max_connections: 1, }) .await?; @@ -782,7 +845,12 @@ mod test { let commit_hash: Hash = U256::from_dec_str(dec) .expect("cant convert to u256") .into(); - let hash = db.insert_new_identity(commit_hash).await?; + + let eligibility_timestamp = DateTime::from(Utc::now()); + + let hash = db + .insert_new_identity(commit_hash, eligibility_timestamp) + .await?; assert_eq!(commit_hash, hash); @@ -793,6 +861,7 @@ mod test { assert_eq!(commit.0, Status::New); let identity_count = db.get_unprocessed_commitments(Status::New).await?.len(); + assert_eq!(identity_count, 1); assert!(db.remove_unprocessed_identity(&commit_hash).await.is_ok()); @@ -800,6 +869,209 @@ mod test { Ok(()) } + fn mock_provers() -> HashSet { + let mut provers = HashSet::new(); + + provers.insert(ProverConfiguration { + batch_size: 100, + url: "http://localhost:8080".to_string(), + timeout_s: 100, + prover_type: ProverType::Insertion, + }); + + provers.insert(ProverConfiguration { + batch_size: 100, + url: "http://localhost:8080".to_string(), + timeout_s: 100, + prover_type: ProverType::Deletion, + }); + + provers + } + + #[tokio::test] + async fn test_insert_prover_configuration() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let mock_prover_configuration_0 = ProverConfiguration { + batch_size: 100, + url: "http://localhost:8080".to_string(), + timeout_s: 100, + prover_type: ProverType::Insertion, + }; + + let mock_prover_configuration_1 = ProverConfiguration { + batch_size: 100, + url: "http://localhost:8081".to_string(), + timeout_s: 100, + prover_type: ProverType::Deletion, + }; + + db.insert_prover_configuration( + mock_prover_configuration_0.batch_size, + mock_prover_configuration_0.url.clone(), + mock_prover_configuration_0.timeout_s, + mock_prover_configuration_0.prover_type, + ) + .await?; + + db.insert_prover_configuration( + mock_prover_configuration_1.batch_size, + mock_prover_configuration_1.url.clone(), + mock_prover_configuration_1.timeout_s, + mock_prover_configuration_1.prover_type, + ) + .await?; + + let provers = db.get_provers().await?; + + assert!(provers.contains(&mock_prover_configuration_0)); + assert!(provers.contains(&mock_prover_configuration_1)); + + Ok(()) + } + + #[tokio::test] + async fn test_insert_provers() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let mock_provers = mock_provers(); + + db.insert_provers(mock_provers.clone()).await?; + + let provers = db.get_provers().await?; + + assert_eq!(provers, mock_provers); + Ok(()) + } + + #[tokio::test] + async fn test_remove_prover() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let mock_provers = mock_provers(); + + db.insert_provers(mock_provers.clone()).await?; + db.remove_prover(100, ProverType::Insertion).await?; + let provers = db.get_provers().await?; + + assert_eq!(provers, HashSet::new()); + + Ok(()) + } + + #[tokio::test] + async fn test_insert_new_recovery() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let existing_commitment: Uint<256, 4> = Uint::from(1); + let new_commitment: Uint<256, 4> = Uint::from(2); + + db.insert_new_recovery(&existing_commitment, &new_commitment) + .await?; + + let recoveries = db.get_recoveries().await?; + + assert_eq!(recoveries.len(), 1); + assert_eq!(recoveries[0].existing_commitment, existing_commitment); + assert_eq!(recoveries[0].new_commitment, new_commitment); + + Ok(()) + } + + #[tokio::test] + async fn test_insert_new_deletion() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let existing_commitment: Uint<256, 4> = Uint::from(1); + + db.insert_new_deletion(0, &existing_commitment).await?; + + let deletions = db.get_deletions().await?; + assert_eq!(deletions.len(), 1); + assert_eq!(deletions[0].leaf_index, 0); + assert_eq!(deletions[0].commitment, existing_commitment); + + Ok(()) + } + + #[tokio::test] + async fn test_get_eligible_unprocessed_commitments() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let commitment_0: Uint<256, 4> = Uint::from(1); + let eligibility_timestamp_0 = DateTime::from(Utc::now()); + + db.insert_new_identity(commitment_0, eligibility_timestamp_0) + .await?; + + let commitment_1: Uint<256, 4> = Uint::from(2); + let eligibility_timestamp_1 = DateTime::from(Utc::now()) + .checked_add_days(Days::new(7)) + .expect("Could not create eligibility timestamp"); + + db.insert_new_identity(commitment_1, eligibility_timestamp_1) + .await?; + + let unprocessed_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; + + assert_eq!(unprocessed_commitments.len(), 1); + assert_eq!(unprocessed_commitments[0].commitment, commitment_0); + assert_eq!( + unprocessed_commitments[0].eligibility_timestamp, + eligibility_timestamp_0 + ); + + Ok(()) + } + + #[tokio::test] + async fn test_get_unprocessed_commitments() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let commitment_0: Uint<256, 4> = Uint::from(1); + let eligibility_timestamp_0 = DateTime::from(Utc::now()); + + db.insert_new_identity(commitment_0, eligibility_timestamp_0) + .await?; + + let commitment_1: Uint<256, 4> = Uint::from(2); + let eligibility_timestamp_1 = DateTime::from(Utc::now()) + .checked_add_days(Days::new(7)) + .expect("Could not create eligibility timestamp"); + + db.insert_new_identity(commitment_1, eligibility_timestamp_1) + .await?; + + let unprocessed_commitments = db.get_unprocessed_commitments(Status::New).await?; + + assert_eq!(unprocessed_commitments.len(), 2); + assert_eq!(unprocessed_commitments[0].commitment, commitment_0); + assert_eq!( + unprocessed_commitments[0].eligibility_timestamp, + eligibility_timestamp_0 + ); + + assert_eq!(unprocessed_commitments[1].commitment, commitment_1); + assert_eq!( + unprocessed_commitments[1].eligibility_timestamp, + eligibility_timestamp_1 + ); + + Ok(()) + } + + #[tokio::test] + async fn test_identity_is_queued_for_deletion() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let existing_commitment: Uint<256, 4> = Uint::from(1); + + db.insert_new_deletion(0, &existing_commitment).await?; + + assert!( + db.identity_is_queued_for_deletion(&existing_commitment) + .await? + ); + + Ok(()) + } + #[tokio::test] async fn test_update_eligibility_timestamp() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; @@ -808,8 +1080,18 @@ mod test { .expect("cant convert to u256") .into(); - db.insert_new_identity(commit_hash).await?; + // Set eligibility to Utc::now() day and check db entries + let eligibility_timestamp = DateTime::from(Utc::now()); + db.insert_new_identity(commit_hash, eligibility_timestamp) + .await?; + + let commitments = db.get_unprocessed_commitments(Status::New).await?; + assert_eq!(commitments.len(), 1); + + let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; + assert_eq!(eligible_commitments.len(), 1); + // Set eligibility to Utc::now() + 7 days and check db entries let eligibility_timestamp = DateTime::from(Utc::now()) .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); @@ -817,15 +1099,11 @@ mod test { db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_unprocessed_commitments(Status::Pending).await?; + let commitments = db.get_unprocessed_commitments(Status::New).await?; assert_eq!(commitments.len(), 1); - assert_eq!( - commitments[0] - .eligibility_timestamp - .expect("Could not get eligibility_timestamp from commitment"), - eligibility_timestamp - ); + let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; + assert_eq!(eligible_commitments.len(), 0); Ok(()) } @@ -854,7 +1132,7 @@ mod test { let new_identities = mock_identities(3); for (old, new) in old_identities.into_iter().zip(new_identities) { - db.insert_new_recovery(old, new).await?; + db.insert_new_recovery(&old, &new).await?; } let recoveries = db.get_recoveries().await?; @@ -1230,8 +1508,9 @@ mod test { assert!(!db.identity_exists(identities[0]).await?); // When there's only unprocessed identity + let eligibility_timestamp = DateTime::from(Utc::now()); - db.insert_new_identity(identities[0]) + db.insert_new_identity(identities[0], eligibility_timestamp) .await .context("Inserting new identity")?; assert!(db.identity_exists(identities[0]).await?); diff --git a/src/database/prover.rs b/src/database/prover.rs deleted file mode 100644 index 91125bc4..00000000 --- a/src/database/prover.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::collections::HashSet; -use std::hash::{Hash, Hasher}; - -pub type Provers = HashSet; - -#[derive(Debug, Clone)] -pub struct ProverConfiguration { - pub url: String, - pub batch_size: usize, - pub timeout_s: u64, -} - -impl Hash for ProverConfiguration { - fn hash(&self, state: &mut H) { - self.batch_size.hash(state); - } -} - -impl PartialEq for ProverConfiguration { - fn eq(&self, other: &Self) -> bool { - self.batch_size == other.batch_size - } -} - -impl Eq for ProverConfiguration {} diff --git a/src/database/types.rs b/src/database/types.rs index 6ba69505..a3891197 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -3,20 +3,20 @@ use chrono::{DateTime, Utc}; use crate::identity_tree::{Hash, Status}; pub struct UnprocessedCommitment { - pub commitment: Hash, - pub status: Status, - pub created_at: DateTime, - pub processed_at: Option>, - pub error_message: Option, - pub eligibility_timestamp: Option>, + pub commitment: Hash, + pub status: Status, + pub created_at: DateTime, + pub processed_at: Option>, + pub error_message: Option, + pub eligibility_timestamp: DateTime, } pub struct RecoveryEntry { pub existing_commitment: Hash, - pub new_commitment: Hash, + pub new_commitment: Hash, } pub struct DeletionEntry { - pub leaf_index: i64, //TODO: consider using a larger type for leaf indices + pub leaf_index: i64, // TODO: consider using a larger type for leaf indices pub commitment: Hash, } diff --git a/src/identity_tree.rs b/src/identity_tree.rs index 07712ad1..824a6f51 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -183,6 +183,11 @@ where self.tree.root() } + /// Gets the leaf value at a given index. + fn get_leaf(&self, leaf: usize) -> Hash { + self.get_leaf(leaf) + } + /// Gets the proof of the given leaf index element fn get_proof(&self, leaf: usize) -> (Hash, Proof) { let proof = self.tree.proof(leaf); @@ -397,6 +402,8 @@ pub trait TreeVersionReadOps { fn next_leaf(&self) -> usize; /// Returns the merkle proof and element at the given leaf. fn get_proof(&self, leaf: usize) -> (Hash, Proof); + /// Gets the leaf value at a given index. + fn get_leaf(&self, leaf: usize) -> Hash; } impl TreeVersionReadOps for TreeVersion @@ -415,6 +422,11 @@ where let tree = self.get_data(); tree.get_proof(leaf) } + + fn get_leaf(&self, leaf: usize) -> Hash { + let tree = self.get_data(); + tree.get_leaf(leaf) + } } impl TreeVersion { diff --git a/src/prover/batch_insertion/mod.rs b/src/prover/batch_insertion/mod.rs deleted file mode 100644 index d09a83ab..00000000 --- a/src/prover/batch_insertion/mod.rs +++ /dev/null @@ -1,588 +0,0 @@ -mod identity; - -use std::fmt::{Display, Formatter}; -use std::mem::size_of; -use std::time::Duration; - -use clap::Parser; -use ethers::types::U256; -use ethers::utils::keccak256; -use once_cell::sync::Lazy; -use prometheus::{exponential_buckets, register_histogram, Histogram}; -use serde::{Deserialize, Serialize}; -use url::Url; - -use crate::database::prover::ProverConfiguration as DbProverConfiguration; -pub use crate::prover::batch_insertion::identity::Identity; -use crate::prover::Proof; -use crate::serde_utils::JsonStrWrapper; - -/// The endpoint used for proving operations. -const MTB_PROVE_ENDPOINT: &str = "prove"; - -static TOTAL_PROVING_TIME: Lazy = Lazy::new(|| { - register_histogram!( - "total_proving_time", - "The time to generate a proof in seconds. Includes preparing the data for the prover", - exponential_buckets(0.1, 1.5, 25).unwrap() - ) - .unwrap() -}); - -static PROVER_PROVING_TIME: Lazy = Lazy::new(|| { - register_histogram!( - "prover_proving_time", - "Only the time between sending a request and receiving the proof", - exponential_buckets(0.1, 1.5, 25).unwrap() - ) - .unwrap() -}); - -#[derive(Clone, Debug, PartialEq, Eq, Parser)] -#[group(skip)] -pub struct Options { - /// The options for configuring the batch insertion prover service. - /// - /// This should be a JSON array containing objects of the following format `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30}` - #[clap( - long, - env, - default_value = r#"[{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30}]"# - )] - pub prover_urls: JsonStrWrapper>, -} - -/// Configuration options for the component responsible for interacting with the -/// prover service. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ProverConfiguration { - /// The URL at which to contact the semaphore prover service for proof - /// generation. - pub url: String, - - /// The number of seconds to wait before timing out the transaction. - pub timeout_s: u64, - - // TODO Add and query a prover `info` endpoint instead. - /// The batch size that the prover is set up to work with. This must match - /// the deployed prover. - pub batch_size: usize, -} - -/// A representation of the connection to the MTB prover service. -#[derive(Clone, Debug)] -pub struct Prover { - target_url: Url, - client: reqwest::Client, - batch_size: usize, - timeout_s: u64, -} - -impl Prover { - /// Constructs a new instance of the Merkle Tree Batcher (or Mtb). - /// - /// # Arguments - /// - `options`: The prover configuration options. - pub fn new(options: &ProverConfiguration) -> anyhow::Result { - let target_url = Url::parse(&options.url)?; - let timeout_duration = Duration::from_secs(options.timeout_s); - let timeout_s = options.timeout_s; - let batch_size = options.batch_size; - let client = reqwest::Client::builder() - .connect_timeout(timeout_duration) - .https_only(false) - .build()?; - let mtb = Self { - target_url, - client, - batch_size, - timeout_s, - }; - - Ok(mtb) - } - - /// Creates a new batch insertion prover from the prover taken from the - /// database - pub fn from_prover_conf(prover_conf: &DbProverConfiguration) -> anyhow::Result { - let target_url = Url::parse(&prover_conf.url)?; - let timeout_duration = Duration::from_secs(prover_conf.timeout_s); - let client = reqwest::Client::builder() - .connect_timeout(timeout_duration) - .https_only(false) - .build()?; - - Ok(Self { - target_url, - client, - batch_size: prover_conf.batch_size, - timeout_s: prover_conf.timeout_s, - }) - } - - pub fn batch_size(&self) -> usize { - self.batch_size - } - - pub fn timeout_s(&self) -> u64 { - self.timeout_s - } - - /// Generates a proof term for the provided identity insertions into the - /// merkle tree. - /// - /// # Arguments - /// - `start_index`: The index in the merkle tree at which the insertions - /// were started. - /// - `pre_root`: The value of the merkle tree's root before identities were - /// inserted. - /// - `post_root`: The value of the merkle tree's root after the identities - /// were inserted. - /// - `identities`: A list of identity insertions, ordered in the order the - /// identities were inserted into the merkle tree. - pub async fn generate_proof( - &self, - start_index: u32, - pre_root: U256, - post_root: U256, - identities: &[Identity], - ) -> anyhow::Result { - if identities.len() != self.batch_size { - return Err(anyhow::Error::msg( - "Provided batch does not match prover batch size.", - )); - } - - let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); - - let identity_commitments: Vec = identities.iter().map(|id| id.commitment).collect(); - let input_hash = - compute_input_hash(start_index, pre_root, post_root, &identity_commitments); - let merkle_proofs = identities - .iter() - .map(|id| id.merkle_proof.clone()) - .collect(); - - let proof_input = ProofInput { - input_hash, - start_index, - pre_root, - post_root, - identity_commitments, - merkle_proofs, - }; - - let request = self - .client - .post(self.target_url.join(MTB_PROVE_ENDPOINT)?) - .body("OH MY GOD") - .json(&proof_input) - .build()?; - - let prover_proving_time_timer = PROVER_PROVING_TIME.start_timer(); - let proof_term = self.client.execute(request).await?; - let proof_term = proof_term.error_for_status()?; - prover_proving_time_timer.observe_duration(); - - let json = proof_term.text().await?; - - let Ok(proof) = serde_json::from_str::(&json) else { - let error: ProverError = serde_json::from_str(&json)?; - return Err(anyhow::Error::msg(format!("{error}"))) - }; - - total_proving_time_timer.observe_duration(); - - Ok(proof) - } - - pub fn url(&self) -> String { - self.target_url.to_string() - } -} - -/// Computes the input hash to the prover. -/// -/// The input hash is specified as the `keccak256` hash of the inputs arranged -/// as follows: -/// -/// ```md -/// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] -/// 32 || 256 || 256 || 256 || 256 || ... || 256 bits -/// ``` -/// -/// where: -/// - `StartIndex` is `start_index`, the leaf index in the tree from which the -/// insertions started. -/// - `PreRoot` is `pre_root`, the root value of the merkle tree before the -/// insertions were made. -/// - `PostRoot` is `post_root`, the root value of the merkle tree after the -/// insertions were made. -/// - `IdComms` is `identity_commitments`, the list of identity commitments -/// provided in the order that they were inserted into the tree. -/// -/// The result is computed using the inputs in _big-endian_ byte ordering. -pub fn compute_input_hash( - start_index: u32, - pre_root: U256, - post_root: U256, - identity_commitments: &[U256], -) -> U256 { - let mut pre_root_bytes: [u8; size_of::()] = Default::default(); - pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); - let mut post_root_bytes: [u8; size_of::()] = Default::default(); - post_root.to_big_endian(post_root_bytes.as_mut_slice()); - - let mut bytes: Vec = vec![]; - bytes.extend_from_slice(&start_index.to_be_bytes()); - bytes.extend(pre_root_bytes.iter()); - bytes.extend(post_root_bytes.iter()); - - for commitment in identity_commitments.iter() { - let mut commitment_bytes: [u8; size_of::()] = Default::default(); - commitment.to_big_endian(commitment_bytes.as_mut_slice()); - bytes.extend(commitment_bytes.iter()); - } - - keccak256(bytes).into() -} - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct ProverError { - pub code: String, - pub message: String, -} - -impl Display for ProverError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "PROVER FAILURE: Code = {}, Message = {}", - self.code, self.message - ) - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct ProofInput { - input_hash: U256, - start_index: u32, - pre_root: U256, - post_root: U256, - identity_commitments: Vec, - merkle_proofs: Vec>, -} - -#[cfg(test)] -mod test { - use super::*; - - #[tokio::test] - async fn mtb_should_generate_proof_with_correct_inputs() -> anyhow::Result<()> { - let mock_url: String = "0.0.0.0:3001".into(); - let mock_service = mock::Service::new(mock_url.clone()).await?; - - let options = ProverConfiguration { - url: "http://localhost:3001".into(), - timeout_s: 30, - batch_size: 3, - }; - let mtb = Prover::new(&options).unwrap(); - let input_data = get_default_proof_input(); - let identities: Vec = extract_identities_from(&input_data); - - let expected_proof = get_default_proof_output(); - let proof = mtb - .generate_proof( - input_data.start_index, - input_data.pre_root, - input_data.post_root, - &identities, - ) - .await?; - - mock_service.stop(); - - assert_eq!(proof, expected_proof); - - Ok(()) - } - - #[tokio::test] - async fn mtb_should_respond_with_error_if_inputs_incorrect() -> anyhow::Result<()> { - let mock_url: String = "0.0.0.0:3002".into(); - let mock_service = mock::Service::new(mock_url.clone()).await?; - - let options = ProverConfiguration { - url: "http://localhost:3002".into(), - timeout_s: 30, - batch_size: 3, - }; - let mtb = Prover::new(&options).unwrap(); - let mut input_data = get_default_proof_input(); - let identities = extract_identities_from(&input_data); - input_data.post_root = U256::from(2); - - let prover_result = mtb - .generate_proof( - input_data.start_index, - input_data.pre_root, - input_data.post_root, - &identities, - ) - .await; - - mock_service.stop(); - assert!(prover_result.is_err()); - - Ok(()) - } - - #[tokio::test] - async fn prover_should_error_if_batch_size_wrong() -> anyhow::Result<()> { - let options = ProverConfiguration { - url: "http://localhost:3002".into(), - timeout_s: 30, - batch_size: 10, - }; - let mtb = Prover::new(&options).unwrap(); - let input_data = get_default_proof_input(); - let identities = extract_identities_from(&input_data); - - let prover_result = mtb - .generate_proof( - input_data.start_index, - input_data.pre_root, - input_data.post_root, - &identities, - ) - .await; - - assert!(prover_result.is_err()); - assert_eq!( - prover_result.unwrap_err().to_string(), - anyhow::Error::msg("Provided batch does not match prover batch size.").to_string() - ); - - Ok(()) - } - - #[test] - fn compute_input_hash_should_succeed() { - let input = get_default_proof_input(); - - assert_eq!( - compute_input_hash( - input.start_index, - input.pre_root, - input.post_root, - &input.identity_commitments - ), - input.input_hash - ); - } - - #[test] - fn proof_input_should_serde() { - let expected_data: ProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); - let proof_input = get_default_proof_input(); - - assert_eq!(proof_input, expected_data); - } - - fn extract_identities_from(proof_input: &ProofInput) -> Vec { - proof_input - .identity_commitments - .iter() - .zip(&proof_input.merkle_proofs) - .map(|(comm, prf)| Identity::new(*comm, prf.clone())) - .collect() - } - - pub fn get_default_proof_output() -> Proof { - Proof::from([ - "0x12bba8b5a46139c819d83544f024828ece34f4f46be933a377a07c1904e96ec4".into(), - "0x112c8d7c63b6c431cef23e9c0d9ffff39d1d660f514030d4f2787960b437a1d5".into(), - "0x2413396a2af3add6fbe8137cfe7657917e31a5cdab0b7d1d645bd5eeb47ba601".into(), - "0x1ad029539528b32ba70964ce43dbf9bba2501cdb3aaa04e4d58982e2f6c34752".into(), - "0x5bb975296032b135458bd49f92d5e9d363367804440d4692708de92e887cf17".into(), - "0x14932600f53a1ceb11d79a7bdd9688a2f8d1919176f257f132587b2b3274c41e".into(), - "0x13d7b19c7b67bf5d3adf2ac2d3885fd5d49435b6069c0656939cd1fb7bef9dc9".into(), - "0x142e14f90c49c79b4edf5f6b7acbcdb0b0f376a4311fc036f1006679bd53ca9e".into(), - ]) - } - - fn get_default_proof_input() -> ProofInput { - let start_index: u32 = 0; - let pre_root: U256 = - "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2".into(); - let post_root: U256 = - "0x7b248024e18c30f6c8a6c63dad3748d72cd13d1197bfd79a1323216d6ac6e99".into(); - let identities: Vec = vec!["0x1".into(), "0x2".into(), "0x3".into()]; - let merkle_proofs: Vec> = vec![ - vec![ - "0x0".into(), - "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864".into(), - "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), - "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), - "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), - "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), - "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), - "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), - "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), - "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), - ], - vec![ - "0x1".into(), - "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864".into(), - "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), - "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), - "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), - "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), - "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), - "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), - "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), - "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), - ], - vec![ - "0x0".into(), - "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a".into(), - "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), - "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), - "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), - "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), - "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), - "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), - "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), - "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), - ], - ]; - let input_hash: U256 = - "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8".into(); - - ProofInput { - input_hash, - start_index, - pre_root, - post_root, - identity_commitments: identities, - merkle_proofs, - } - } - - const EXPECTED_JSON: &str = r#"{ - "inputHash": "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8", - "startIndex": 0, - "preRoot": "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2", - "postRoot": "0x7b248024e18c30f6c8a6c63dad3748d72cd13d1197bfd79a1323216d6ac6e99", - "identityCommitments": [ - "0x1", - "0x2", - "0x3" - ], - "merkleProofs": [ - [ - "0x0", - "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", - "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", - "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", - "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", - "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", - "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", - "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", - "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", - "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" - ], - [ - "0x1", - "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", - "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", - "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", - "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", - "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", - "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", - "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", - "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", - "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" - ], - [ - "0x0", - "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a", - "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", - "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", - "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", - "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", - "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", - "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", - "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", - "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" - ] - ] -} -"#; -} - -#[cfg(test)] -pub mod mock { - use std::net::SocketAddr; - - use axum::routing::post; - use axum::{Json, Router}; - use axum_server::Handle; - - use super::*; - - pub struct Service { - server: Handle, - } - - #[derive(Serialize, Deserialize)] - #[serde(untagged)] - #[allow(clippy::large_enum_variant)] - enum ProveResponse { - ProofSuccess(Proof), - ProofFailure(ProverError), - } - - impl Service { - pub async fn new(url: String) -> anyhow::Result { - let prove = |Json(payload): Json| async move { - match payload.post_root.div_mod(U256::from(2)) { - (_, y) if y != U256::zero() => { - Json(ProveResponse::ProofSuccess(test::get_default_proof_output())) - } - _ => { - let error = ProverError { - code: "Oh no!".into(), - message: "Things went wrong.".into(), - }; - Json(ProveResponse::ProofFailure(error)) - } - } - }; - let app = Router::new().route("/prove", post(prove)); - - let addr: SocketAddr = url.parse()?; - let server = Handle::new(); - let serverside_handle = server.clone(); - let service = app.into_make_service(); - - tokio::spawn(async move { - axum_server::bind(addr) - .handle(serverside_handle) - .serve(service) - .await - .unwrap(); - }); - - let service = Self { server }; - Ok(service) - } - - pub fn stop(self) { - self.server.shutdown(); - } - } -} diff --git a/src/prover/batch_insertion/identity.rs b/src/prover/identity.rs similarity index 100% rename from src/prover/batch_insertion/identity.rs rename to src/prover/identity.rs diff --git a/src/prover/map.rs b/src/prover/map.rs index 51b6fc7d..8712b90c 100644 --- a/src/prover/map.rs +++ b/src/prover/map.rs @@ -1,10 +1,9 @@ use std::collections::BTreeMap; +use std::hash::{Hash, Hasher}; use tokio::sync::{RwLock, RwLockReadGuard}; -use crate::database::prover; -use crate::prover::batch_insertion; -use crate::prover::batch_insertion::ProverConfiguration; +use crate::prover::{Prover, ProverConfiguration, ProverType, Provers}; /// The type of a map containing a mapping from a usize to a locked item. type SharedProverMap

= RwLock>; @@ -23,6 +22,10 @@ pub struct ProverMap

{ } impl

ProverMap

{ + pub fn new(map: BTreeMap) -> Self { + Self { map } + } + /// Get the smallest prover that can handle the given batch size. pub fn get(&self, batch_size: usize) -> Option<&P> { for (size, prover) in &self.map { @@ -57,14 +60,15 @@ impl

ProverMap

{ } } -impl ProverMap { +impl ProverMap { pub fn as_configuration_vec(&self) -> Vec { self.map .iter() .map(|(k, v)| ProverConfiguration { - url: v.url(), - timeout_s: v.timeout_s(), - batch_size: *k, + url: v.url(), + timeout_s: v.timeout_s(), + batch_size: *k, + prover_type: v.prover_type(), }) .collect() } @@ -77,24 +81,36 @@ impl

From> for ProverMap

{ } /// A map of provers for batch insertion operations. -pub type InsertionProverMap = SharedProverMap; +pub type InsertionProverMap = SharedProverMap; +/// A map of provers for batch deletion operations. +pub type DeletionProverMap = SharedProverMap; /// The type of provers that can only be read from for insertion operations. -pub type ReadOnlyInsertionProver<'a> = ReadOnlyProver<'a, batch_insertion::Prover>; +pub type ReadOnlyInsertionProver<'a> = ReadOnlyProver<'a, Prover>; /// Builds an insertion prover map from the provided configuration. -pub fn make_insertion_map(db_provers: prover::Provers) -> anyhow::Result { - let mut map = BTreeMap::new(); +pub fn initialize_prover_maps( + db_provers: Provers, +) -> anyhow::Result<(InsertionProverMap, DeletionProverMap)> { + let mut insertion_map = BTreeMap::new(); + let mut deletion_map = BTreeMap::new(); for prover in db_provers { - map.insert( - prover.batch_size, - batch_insertion::Prover::from_prover_conf(&prover)?, - ); + match prover.prover_type { + ProverType::Insertion => { + insertion_map.insert(prover.batch_size, Prover::from_prover_conf(&prover)?); + } + + ProverType::Deletion => { + deletion_map.insert(prover.batch_size, Prover::from_prover_conf(&prover)?); + } + } } - let insertion_map = ProverMap::from(map); - Ok(RwLock::new(insertion_map)) + Ok(( + RwLock::new(ProverMap::new(insertion_map)), + RwLock::new(ProverMap::new(deletion_map)), + )) } #[cfg(test)] diff --git a/src/prover/mod.rs b/src/prover/mod.rs index 5672a806..62f08bbc 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -7,9 +7,641 @@ //! APIs are designed to be imported for use qualified (e.g. //! `batch_insertion::Prover`, `batch_insertion::Identity` and so on). -pub mod batch_insertion; +pub mod identity; pub mod map; pub mod proof; +use std::collections::HashSet; +use std::default; +use std::fmt::{Display, Formatter}; +use std::hash::{Hash, Hasher}; +use std::mem::size_of; +use std::time::Duration; + +use clap::Parser; +use ethers::types::U256; +use ethers::utils::keccak256; pub use map::{InsertionProverMap, ProverMap, ReadOnlyProver}; +use once_cell::sync::Lazy; +use prometheus::{exponential_buckets, register_histogram, Histogram}; pub use proof::Proof; +use serde::{Deserialize, Serialize}; +use url::Url; + +use crate::prover::identity::Identity; +use crate::serde_utils::JsonStrWrapper; + +/// The endpoint used for proving operations. +const MTB_PROVE_ENDPOINT: &str = "prove"; + +static TOTAL_PROVING_TIME: Lazy = Lazy::new(|| { + register_histogram!( + "total_proving_time", + "The time to generate a proof in seconds. Includes preparing the data for the prover", + exponential_buckets(0.1, 1.5, 25).unwrap() + ) + .unwrap() +}); + +static PROVER_PROVING_TIME: Lazy = Lazy::new(|| { + register_histogram!( + "prover_proving_time", + "Only the time between sending a request and receiving the proof", + exponential_buckets(0.1, 1.5, 25).unwrap() + ) + .unwrap() +}); + +#[derive(Clone, Debug, PartialEq, Eq, Parser)] +#[group(skip)] +pub struct Options { + /// The options for configuring the batch insertion prover service. + /// + /// This should be a JSON array containing objects of the following format `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30,"prover_type", "insertion"}` + #[clap( + long, + env, + default_value = r#"[{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30,"prover_type": "insertion"}]"# //TODO: update this and test + )] + pub prover_urls: JsonStrWrapper>, +} + +/// Configuration options for the component responsible for interacting with the +/// prover service. +#[derive(Clone, Debug, Eq, Serialize, Deserialize)] +pub struct ProverConfiguration { + /// The URL at which to contact the semaphore prover service for proof + /// generation. + pub url: String, + + /// The number of seconds to wait before timing out the transaction. + pub timeout_s: u64, + + // TODO Add and query a prover `info` endpoint instead. + /// The batch size that the prover is set up to work with. This must match + /// the deployed prover. + pub batch_size: usize, + + // TODO: add docs + pub prover_type: ProverType, +} + +#[derive(Debug, Copy, Clone, sqlx::Type, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +#[sqlx(type_name = "prover_enum", rename_all = "PascalCase")] +pub enum ProverType { + #[default] + Insertion, + Deletion, +} + +impl Hash for ProverConfiguration { + fn hash(&self, state: &mut H) { + self.batch_size.hash(state); + } +} + +impl PartialEq for ProverConfiguration { + fn eq(&self, other: &Self) -> bool { + self.batch_size == other.batch_size + } +} + +pub type Provers = HashSet; + +/// A representation of the connection to the MTB prover service. +#[derive(Clone, Debug)] +pub struct Prover { + target_url: Url, + client: reqwest::Client, + batch_size: usize, + timeout_s: u64, + prover_type: ProverType, +} + +impl Prover { + /// Constructs a new instance of the Merkle Tree Batcher (or Mtb). + /// + /// # Arguments + /// - `options`: The prover configuration options. + pub fn new(options: &ProverConfiguration) -> anyhow::Result { + let target_url = Url::parse(&options.url)?; + let timeout_duration = Duration::from_secs(options.timeout_s); + let client = reqwest::Client::builder() + .connect_timeout(timeout_duration) + .https_only(false) + .build()?; + + let mtb = Self { + target_url, + client, + batch_size: options.batch_size, + timeout_s: options.timeout_s, + prover_type: options.prover_type, + }; + + Ok(mtb) + } + + /// Creates a new batch insertion prover from the prover taken from the + /// database + pub fn from_prover_conf(prover_conf: &ProverConfiguration) -> anyhow::Result { + let target_url = Url::parse(&prover_conf.url)?; + let timeout_duration = Duration::from_secs(prover_conf.timeout_s); + let client = reqwest::Client::builder() + .connect_timeout(timeout_duration) + .https_only(false) + .build()?; + + Ok(Self { + target_url, + client, + batch_size: prover_conf.batch_size, + timeout_s: prover_conf.timeout_s, + prover_type: prover_conf.prover_type, + }) + } + + pub fn batch_size(&self) -> usize { + self.batch_size + } + + pub fn prover_type(&self) -> ProverType { + self.prover_type + } + + pub fn timeout_s(&self) -> u64 { + self.timeout_s + } + + /// Generates a proof term for the provided identity insertions into the + /// merkle tree. + /// + /// # Arguments + /// - `start_index`: The index in the merkle tree at which the insertions + /// were started. + /// - `pre_root`: The value of the merkle tree's root before identities were + /// inserted. + /// - `post_root`: The value of the merkle tree's root after the identities + /// were inserted. + /// - `identities`: A list of identity insertions, ordered in the order the + /// identities were inserted into the merkle tree. + pub async fn generate_insertion_proof( + &self, + start_index: u32, + pre_root: U256, + post_root: U256, + identities: &[Identity], + ) -> anyhow::Result { + if identities.len() != self.batch_size { + return Err(anyhow::Error::msg( + "Provided batch does not match prover batch size.", + )); + } + + let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); + + let identity_commitments: Vec = identities.iter().map(|id| id.commitment).collect(); + let input_hash = + compute_input_hash(start_index, pre_root, post_root, &identity_commitments); + let merkle_proofs = identities + .iter() + .map(|id| id.merkle_proof.clone()) + .collect(); + + let proof_input = ProofInput { + input_hash, + start_index, + pre_root, + post_root, + identity_commitments, + merkle_proofs, + }; + + let request = self + .client + .post(self.target_url.join(MTB_PROVE_ENDPOINT)?) + .body("OH MY GOD") + .json(&proof_input) + .build()?; + + let prover_proving_time_timer = PROVER_PROVING_TIME.start_timer(); + let proof_term = self.client.execute(request).await?; + let proof_term = proof_term.error_for_status()?; + prover_proving_time_timer.observe_duration(); + + let json = proof_term.text().await?; + + let Ok(proof) = serde_json::from_str::(&json) else { + let error: ProverError = serde_json::from_str(&json)?; + return Err(anyhow::Error::msg(format!("{error}"))) + }; + + total_proving_time_timer.observe_duration(); + + Ok(proof) + } + + pub async fn generate_deletion_proof( + &self, + start_index: u32, + pre_root: U256, + post_root: U256, + identities: &[Identity], + ) -> anyhow::Result { + todo!("TODO:"); + } + + pub fn url(&self) -> String { + self.target_url.to_string() + } +} + +/// Computes the input hash to the prover. +/// +/// The input hash is specified as the `keccak256` hash of the inputs arranged +/// as follows: +/// +/// ```md +/// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] +/// 32 || 256 || 256 || 256 || 256 || ... || 256 bits +/// ``` +/// +/// where: +/// - `StartIndex` is `start_index`, the leaf index in the tree from which the +/// insertions started. +/// - `PreRoot` is `pre_root`, the root value of the merkle tree before the +/// insertions were made. +/// - `PostRoot` is `post_root`, the root value of the merkle tree after the +/// insertions were made. +/// - `IdComms` is `identity_commitments`, the list of identity commitments +/// provided in the order that they were inserted into the tree. +/// +/// The result is computed using the inputs in _big-endian_ byte ordering. +pub fn compute_input_hash( + start_index: u32, + pre_root: U256, + post_root: U256, + identity_commitments: &[U256], +) -> U256 { + let mut pre_root_bytes: [u8; size_of::()] = Default::default(); + pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); + let mut post_root_bytes: [u8; size_of::()] = Default::default(); + post_root.to_big_endian(post_root_bytes.as_mut_slice()); + + let mut bytes: Vec = vec![]; + bytes.extend_from_slice(&start_index.to_be_bytes()); + bytes.extend(pre_root_bytes.iter()); + bytes.extend(post_root_bytes.iter()); + + for commitment in identity_commitments.iter() { + let mut commitment_bytes: [u8; size_of::()] = Default::default(); + commitment.to_big_endian(commitment_bytes.as_mut_slice()); + bytes.extend(commitment_bytes.iter()); + } + + keccak256(bytes).into() +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ProverError { + pub code: String, + pub message: String, +} + +impl Display for ProverError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "PROVER FAILURE: Code = {}, Message = {}", + self.code, self.message + ) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ProofInput { + input_hash: U256, + start_index: u32, + pre_root: U256, + post_root: U256, + identity_commitments: Vec, + merkle_proofs: Vec>, +} + +#[cfg(test)] +mod test { + use super::*; + + #[tokio::test] + async fn mtb_should_generate_proof_with_correct_inputs() -> anyhow::Result<()> { + let mock_url: String = "0.0.0.0:3001".into(); + let mock_service = mock::Service::new(mock_url.clone()).await?; + + let options = ProverConfiguration { + url: "http://localhost:3001".into(), + timeout_s: 30, + batch_size: 3, + prover_type: ProverType::Insertion, + }; + let mtb = Prover::new(&options).unwrap(); + let input_data = get_default_proof_input(); + let identities: Vec = extract_identities_from(&input_data); + + let expected_proof = get_default_proof_output(); + let proof = mtb + .generate_insertion_proof( + input_data.start_index, + input_data.pre_root, + input_data.post_root, + &identities, + ) + .await?; + + mock_service.stop(); + + assert_eq!(proof, expected_proof); + + Ok(()) + } + + #[tokio::test] + async fn mtb_should_respond_with_error_if_inputs_incorrect() -> anyhow::Result<()> { + let mock_url: String = "0.0.0.0:3002".into(); + let mock_service = mock::Service::new(mock_url.clone()).await?; + + let options = ProverConfiguration { + url: "http://localhost:3002".into(), + timeout_s: 30, + batch_size: 3, + prover_type: ProverType::Insertion, + }; + let mtb = Prover::new(&options).unwrap(); + let mut input_data = get_default_proof_input(); + let identities = extract_identities_from(&input_data); + input_data.post_root = U256::from(2); + + let prover_result = mtb + .generate_insertion_proof( + input_data.start_index, + input_data.pre_root, + input_data.post_root, + &identities, + ) + .await; + + mock_service.stop(); + assert!(prover_result.is_err()); + + Ok(()) + } + + #[tokio::test] + async fn prover_should_error_if_batch_size_wrong() -> anyhow::Result<()> { + let options = ProverConfiguration { + url: "http://localhost:3002".into(), + timeout_s: 30, + batch_size: 10, + prover_type: ProverType::Insertion, + }; + let mtb = Prover::new(&options).unwrap(); + let input_data = get_default_proof_input(); + let identities = extract_identities_from(&input_data); + + let prover_result = mtb + .generate_insertion_proof( + input_data.start_index, + input_data.pre_root, + input_data.post_root, + &identities, + ) + .await; + + assert!(prover_result.is_err()); + assert_eq!( + prover_result.unwrap_err().to_string(), + anyhow::Error::msg("Provided batch does not match prover batch size.").to_string() + ); + + Ok(()) + } + + #[test] + fn compute_input_hash_should_succeed() { + let input = get_default_proof_input(); + + assert_eq!( + compute_input_hash( + input.start_index, + input.pre_root, + input.post_root, + &input.identity_commitments + ), + input.input_hash + ); + } + + #[test] + fn proof_input_should_serde() { + let expected_data: ProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); + let proof_input = get_default_proof_input(); + + assert_eq!(proof_input, expected_data); + } + + fn extract_identities_from(proof_input: &ProofInput) -> Vec { + proof_input + .identity_commitments + .iter() + .zip(&proof_input.merkle_proofs) + .map(|(comm, prf)| Identity::new(*comm, prf.clone())) + .collect() + } + + pub fn get_default_proof_output() -> Proof { + Proof::from([ + "0x12bba8b5a46139c819d83544f024828ece34f4f46be933a377a07c1904e96ec4".into(), + "0x112c8d7c63b6c431cef23e9c0d9ffff39d1d660f514030d4f2787960b437a1d5".into(), + "0x2413396a2af3add6fbe8137cfe7657917e31a5cdab0b7d1d645bd5eeb47ba601".into(), + "0x1ad029539528b32ba70964ce43dbf9bba2501cdb3aaa04e4d58982e2f6c34752".into(), + "0x5bb975296032b135458bd49f92d5e9d363367804440d4692708de92e887cf17".into(), + "0x14932600f53a1ceb11d79a7bdd9688a2f8d1919176f257f132587b2b3274c41e".into(), + "0x13d7b19c7b67bf5d3adf2ac2d3885fd5d49435b6069c0656939cd1fb7bef9dc9".into(), + "0x142e14f90c49c79b4edf5f6b7acbcdb0b0f376a4311fc036f1006679bd53ca9e".into(), + ]) + } + + fn get_default_proof_input() -> ProofInput { + let start_index: u32 = 0; + let pre_root: U256 = + "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2".into(); + let post_root: U256 = + "0x7b248024e18c30f6c8a6c63dad3748d72cd13d1197bfd79a1323216d6ac6e99".into(); + let identities: Vec = vec!["0x1".into(), "0x2".into(), "0x3".into()]; + let merkle_proofs: Vec> = vec![ + vec![ + "0x0".into(), + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864".into(), + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), + ], + vec![ + "0x1".into(), + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864".into(), + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), + ], + vec![ + "0x0".into(), + "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a".into(), + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), + ], + ]; + let input_hash: U256 = + "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8".into(); + + ProofInput { + input_hash, + start_index, + pre_root, + post_root, + identity_commitments: identities, + merkle_proofs, + } + } + + const EXPECTED_JSON: &str = r#"{ + "inputHash": "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8", + "startIndex": 0, + "preRoot": "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2", + "postRoot": "0x7b248024e18c30f6c8a6c63dad3748d72cd13d1197bfd79a1323216d6ac6e99", + "identityCommitments": [ + "0x1", + "0x2", + "0x3" + ], + "merkleProofs": [ + [ + "0x0", + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" + ], + [ + "0x1", + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" + ], + [ + "0x0", + "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a", + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" + ] + ] +} +"#; +} + +#[cfg(test)] +pub mod mock { + use std::net::SocketAddr; + + use axum::routing::post; + use axum::{Json, Router}; + use axum_server::Handle; + + use super::*; + + pub struct Service { + server: Handle, + } + + #[derive(Serialize, Deserialize)] + #[serde(untagged)] + #[allow(clippy::large_enum_variant)] + enum ProveResponse { + ProofSuccess(Proof), + ProofFailure(ProverError), + } + + impl Service { + pub async fn new(url: String) -> anyhow::Result { + let prove = |Json(payload): Json| async move { + match payload.post_root.div_mod(U256::from(2)) { + (_, y) if y != U256::zero() => { + Json(ProveResponse::ProofSuccess(test::get_default_proof_output())) + } + _ => { + let error = ProverError { + code: "Oh no!".into(), + message: "Things went wrong.".into(), + }; + Json(ProveResponse::ProofFailure(error)) + } + } + }; + let app = Router::new().route("/prove", post(prove)); + + let addr: SocketAddr = url.parse()?; + let server = Handle::new(); + let serverside_handle = server.clone(); + let service = app.into_make_service(); + + tokio::spawn(async move { + axum_server::bind(addr) + .handle(serverside_handle) + .serve(service) + .await + .unwrap(); + }); + + let service = Self { server }; + Ok(service) + } + + pub fn stop(self) { + self.server.shutdown(); + } + } +} diff --git a/src/server/custom_middleware.rs b/src/server/custom_middleware/mod.rs similarity index 100% rename from src/server/custom_middleware.rs rename to src/server/custom_middleware/mod.rs diff --git a/src/server/error.rs b/src/server/error.rs index 15ed03ed..403d2908 100644 --- a/src/server/error.rs +++ b/src/server/error.rs @@ -31,6 +31,10 @@ pub enum Error { DuplicateCommitment, #[error("Root mismatch between tree and contract.")] RootMismatch, + #[error("Identity is already queued for deletion.")] + IdentityQueuedForDeletion, + #[error("Identity has already been deleted.")] + IdentityAlreadyDeleted, #[error("invalid JSON request: {0}")] InvalidSerialization(#[from] serde_json::Error), #[error(transparent)] @@ -55,6 +59,8 @@ pub enum Error { CannotRemoveLastBatchSize, #[error("Identity Manager had no provers on point of identity insertion.")] NoProversOnIdInsert, + #[error("Identity Manager had no provers on point of identity deletion.")] + NoProversOnIdDeletion, #[error(transparent)] Other(#[from] EyreError), } diff --git a/src/server/mod.rs b/src/server/mod.rs index 2dd0816c..05527903 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -22,6 +22,7 @@ use crate::app::{ App, InclusionProofResponse, ListBatchSizesResponse, VerifySemaphoreProofResponse, }; use crate::identity_tree::Hash; +use crate::prover::ProverType; mod custom_middleware; @@ -55,6 +56,8 @@ pub struct AddBatchSizeRequest { batch_size: usize, /// The timeout for communications with the prover service. timeout_seconds: u64, + // TODO: add docs + prover_type: ProverType, } #[derive(Clone, Serialize, Deserialize)] @@ -62,7 +65,9 @@ pub struct AddBatchSizeRequest { #[serde(deny_unknown_fields)] pub struct RemoveBatchSizeRequest { /// The batch size to remove from the prover map. - batch_size: usize, + batch_size: usize, + // TODO: add docs + prover_type: ProverType, } #[derive(Serialize, Deserialize)] @@ -83,6 +88,24 @@ pub struct VerifySemaphoreProofRequest { pub proof: Proof, } +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct DeletionRequest { + /// The identity commitment to delete. + identity_commitment: Hash, +} + +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct RecoveryRequest { + /// The leaf index of the identity commitment to delete. + prev_identity_commitment: Hash, + /// The new identity commitment to insert. + new_identity_commitment: Hash, +} + pub trait ToResponseCode { fn to_response_code(&self) -> StatusCode; } @@ -133,16 +156,40 @@ async fn add_batch_size( State(app): State>, Json(req): Json, ) -> Result<(), Error> { - app.add_batch_size(req.url, req.batch_size, req.timeout_seconds) - .await?; + app.add_batch_size( + req.url, + req.batch_size, + req.timeout_seconds, + req.prover_type, + ) + .await?; Ok(()) } + +async fn delete_identity( + State(app): State>, + Json(req): Json, +) -> Result<(), Error> { + app.delete_identity(&req.identity_commitment).await?; + Ok(()) +} + +async fn recover_identity( + State(app): State>, + Json(req): Json, +) -> Result<(), Error> { + app.recover_identity(&req.prev_identity_commitment, &req.new_identity_commitment) + .await?; + Ok(()) +} + async fn remove_batch_size( State(app): State>, Json(req): Json, ) -> Result<(), Error> { - app.remove_batch_size(req.batch_size).await?; + app.remove_batch_size(req.batch_size, req.prover_type) + .await?; Ok(()) } @@ -202,6 +249,8 @@ pub async fn bind_from_listener( .route("/inclusionProof", post(inclusion_proof)) .route("/insertIdentity", post(insert_identity)) .route("/addBatchSize", post(add_batch_size)) + .route("/deleteIdentity", post(delete_identity)) + .route("/recoverIdentity", post(recover_identity)) .route("/removeBatchSize", post(remove_batch_size)) .route("/listBatchSizes", get(list_batch_sizes)) .layer(middleware::from_fn( diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 244f2e61..2ec0ca96 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -15,7 +15,7 @@ use crate::database::Database; use crate::identity_tree::{ AppliedTreeUpdate, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, }; -use crate::prover::batch_insertion::Identity; +use crate::prover::identity::Identity; use crate::prover::map::ReadOnlyInsertionProver; use crate::task_monitor::{PendingBatchSubmission, TaskMonitor}; use crate::utils::async_queue::AsyncQueue; @@ -328,7 +328,7 @@ async fn commit_identities( identity_manager.validate_merkle_proofs(&identity_commitments)?; // We prepare the proof before reserving a slot in the pending identities - let proof = IdentityManager::prepare_proof( + let proof = IdentityManager::prepare_insertion_proof( insertion_prover, start_index, pre_root, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 39a579a0..370b25e3 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -63,6 +63,7 @@ use hyper::StatusCode; use self::chain_mock::{spawn_mock_chain, MockChain, SpecialisedContract}; use self::prelude::*; +use self::prover_mock::ProverType; #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] @@ -207,14 +208,17 @@ pub async fn test_add_batch_size( uri: impl Into, prover_url: impl Into, batch_size: u64, + prover_type: ProverType, client: &Client, ) -> anyhow::Result<()> { let prover_url_string: String = prover_url.into(); + let body = Body::from( json!({ "url": prover_url_string, "batchSize": batch_size, - "timeoutSeconds": 3 + "timeoutSeconds": 3, + "proverType": prover_type }) .to_string(), ); @@ -238,9 +242,11 @@ pub async fn test_remove_batch_size( uri: impl Into, batch_size: u64, client: &Client, + prover_type: ProverType, expect_failure: bool, ) -> anyhow::Result<()> { - let body = Body::from(json!({ "batchSize": batch_size }).to_string()); + let body = + Body::from(json!({ "batchSize": batch_size, "proverType": prover_type }).to_string()); let request = Request::builder() .method("POST") .uri(uri.into() + "/removeBatchSize") @@ -413,7 +419,8 @@ async fn spawn_db() -> anyhow::Result { } pub async fn spawn_mock_prover(batch_size: usize) -> anyhow::Result { - let mock_prover_service = prover_mock::ProverService::new(batch_size).await?; + let mock_prover_service = + prover_mock::ProverService::new(batch_size, prover_mock::ProverType::Insertion).await?; Ok(mock_prover_service) } diff --git a/tests/common/prover_mock.rs b/tests/common/prover_mock.rs index d0bf5c33..f7ab189e 100644 --- a/tests/common/prover_mock.rs +++ b/tests/common/prover_mock.rs @@ -91,10 +91,30 @@ impl ProveResponse { /// The mock prover service. pub struct ProverService { - server: Handle, - inner: Arc>, - address: SocketAddr, - batch_size: usize, + server: Handle, + inner: Arc>, + address: SocketAddr, + batch_size: usize, + prover_type: ProverType, +} + +// TODO: we could just import this from the sequencer +#[derive(Debug, Copy, Clone, sqlx::Type, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +#[sqlx(type_name = "prover_enum", rename_all = "PascalCase")] +pub enum ProverType { + #[default] + Insertion, + Deletion, +} + +impl std::fmt::Display for ProverType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + ProverType::Insertion => write!(f, "insertion"), + ProverType::Deletion => write!(f, "deletion"), + } + } } struct Prover { @@ -108,7 +128,7 @@ impl ProverService { /// It provides only a single endpoint for now, `/prove` in order to match /// the full service (`semaphore-mtb`). This can be extended in the future /// if needed. - pub async fn new(batch_size: usize) -> anyhow::Result { + pub async fn new(batch_size: usize, prover_type: ProverType) -> anyhow::Result { async fn prove( State(state): State>>, Json(input): Json, @@ -146,6 +166,7 @@ impl ProverService { inner, address, batch_size, + prover_type, }; Ok(service) @@ -169,6 +190,10 @@ impl ProverService { self.batch_size } + pub fn prover_type(&self) -> ProverType { + self.prover_type + } + /// Produces an arg string that's compatible with this prover - can be used /// as is in the CLI args /// @@ -180,12 +205,13 @@ impl ProverService { /// Produces an arg string that's compatible with this prover - needs to be /// wrapped in an array /// - /// e.g. `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30}` + /// e.g. `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30,"prover_type": "insertion"}` pub fn arg_string_single(&self) -> String { format!( - r#"{{"url": "{}","batch_size": {},"timeout_s": 30}}"#, + r#"{{"url": "{}","batch_size": {},"timeout_s": 30, "prover_type": "{}"}}"#, self.url(), - self.batch_size + self.batch_size, + self.prover_type ) } } diff --git a/tests/dynamic_batch_sizes.rs b/tests/dynamic_batch_sizes.rs index 77d76110..43370340 100644 --- a/tests/dynamic_batch_sizes.rs +++ b/tests/dynamic_batch_sizes.rs @@ -126,9 +126,16 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { // Add a new prover for batch sizes of two. let second_prover = spawn_mock_prover(second_batch_size).await?; - test_add_batch_size(&uri, second_prover.url(), second_batch_size as u64, &client) - .await - .expect("Failed to add batch size."); + + test_add_batch_size( + &uri, + second_prover.url(), + second_batch_size as u64, + second_prover.prover_type(), + &client, + ) + .await + .expect("Failed to add batch size."); // Query for the available provers. let batch_sizes_uri: Uri = @@ -151,11 +158,14 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { "url": second_prover.url() + "/", "timeout_s": 3, "batch_size": second_batch_size, + "prover_type": "insertion", }, { "url": prover_mock.url() + "/", "timeout_s": 30, "batch_size": batch_size, + "prover_type": "insertion", + } ]) ); @@ -193,7 +203,14 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { .await; // Now if we remove the original prover, things should still work. - test_remove_batch_size(&uri, batch_size as u64, &client, false).await?; + test_remove_batch_size( + &uri, + batch_size as u64, + &client, + prover_mock.prover_type(), + false, + ) + .await?; // We should be able to insert less than a full batch successfully. test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, 5).await; @@ -214,7 +231,14 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { .await; // We should be unable to remove _all_ of the provers, however. - test_remove_batch_size(&uri, second_batch_size as u64, &client, true).await?; + test_remove_batch_size( + &uri, + second_batch_size as u64, + &client, + second_prover.prover_type(), + true, + ) + .await?; // So we should still be able to run a batch. test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, 6).await; From e7c9abdf76b3e44371a8f0d3944e9584712e76ae Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Thu, 31 Aug 2023 15:08:29 -0400 Subject: [PATCH 11/45] chore: removing unused whitespace --- schemas/database/008_prover_type.sql | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/schemas/database/008_prover_type.sql b/schemas/database/008_prover_type.sql index 651c9ce0..eacc11df 100644 --- a/schemas/database/008_prover_type.sql +++ b/schemas/database/008_prover_type.sql @@ -14,15 +14,4 @@ ALTER TABLE provers ALTER COLUMN prover_type SET NOT NULL; ALTER TABLE provers DROP CONSTRAINT provers_pkey; -- Drop the url uniqueness constraint -ALTER TABLE provers DROP CONSTRAINT IF EXISTS provers_url_key; - - - - - - - - - - - +ALTER TABLE provers DROP CONSTRAINT IF EXISTS provers_url_key; \ No newline at end of file From 3f043a27bcbc5b84647778e7127c15d2c6efbf17 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Thu, 31 Aug 2023 15:34:04 -0400 Subject: [PATCH 12/45] removed redundant deletion prover check --- src/app.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/app.rs b/src/app.rs index 764577fc..e2c620c3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -401,17 +401,9 @@ impl App { return Err(ServerError::NoProversOnIdInsert); } - // Ensure that deletion provers exist - if !self.identity_manager.has_deletion_provers().await { - warn!( - ?new_commitment, - "Identity Manager has no deletion provers. Add provers with /addBatchSize request." - ); - return Err(ServerError::NoProversOnIdDeletion); - } - // Delete the existing id and insert the commitments into the recovery table self.delete_identity(&existing_commitment).await?; + self.database .insert_new_recovery(&existing_commitment, &new_commitment) .await?; From f5e7090d030e8cd2e400c20b45756d29d8369e42 Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:42:05 -0400 Subject: [PATCH 13/45] Deletion/recovery task monitor updates (#589) * added deletion and recovery endpoints, added app functions for deletion * added deletion prover map * added prover_type to separate deletion and insertion provers * added prover_type during batch size removal * moved custom middleware * updated prover table migration * patching tests, added get_eligible_unprocessed_commitments * patched test_update_eligibility_timestamp * patched dynamic_batch_sizes * chore: cargo fmt * updated delete_identity to check if id has already been deleted or queued for deletion * updated recover_identity to delete existing commitment, and insert data in to recoveries table * removed unused function * added new tests for new database/identity manager logic * added new tests * fix: imported IdentityManager into test mod * updated IdentityManager tests * updated database tests * patched test_remove_prover * added delete_identities task * updated DeleteIdentities methods * updated delete identities task * updated logic to remove deletions from table after inserting into identities table * updated delete task * Updated identity tree peek_next_updates to get contiguous insertion or deletion updates until max_update_count * updated processes identities * added deletion task to the task monitor startup * updated commit_identities * added helper functions for delete/insert identities, refactored commit_identities * added logic to separate insertion/deletion inputs * fix test * added logic to insert recovery commitments after deletion * added deletion indices to deletion proof input * removed identity manager from delete_identities task * removed unused imports, arguments and outdated comment * removed get_unprocessed_commitments * added peek next updates test * updated remove_deletions, added test * moved logic to process recoveries into mine identities task * added logic to get dynamic eligibility timestamp * adding logic to get time until next deletion * added logic to update latest deletion root * updated to track the latest deletion timestamp * chore: typo * removed todos, added fixme --- schemas/database/009_latest_deletion_root.sql | 6 + src/app.rs | 8 +- src/contracts/abi.rs | 2 + src/contracts/mod.rs | 82 ++++- src/database/mod.rs | 161 +++++++--- src/database/types.rs | 7 +- src/identity_tree.rs | 92 +++++- src/prover/mod.rs | 113 ++++++- src/task_monitor.rs | 88 +++++- src/task_monitor/tasks/delete_identities.rs | 110 +++++++ src/task_monitor/tasks/insert_identities.rs | 4 +- src/task_monitor/tasks/mine_identities.rs | 136 ++++++++- src/task_monitor/tasks/mod.rs | 1 + src/task_monitor/tasks/process_identities.rs | 284 ++++++++++++++++-- 14 files changed, 977 insertions(+), 117 deletions(-) create mode 100644 schemas/database/009_latest_deletion_root.sql create mode 100644 src/task_monitor/tasks/delete_identities.rs diff --git a/schemas/database/009_latest_deletion_root.sql b/schemas/database/009_latest_deletion_root.sql new file mode 100644 index 00000000..a3a1c146 --- /dev/null +++ b/schemas/database/009_latest_deletion_root.sql @@ -0,0 +1,6 @@ +CREATE TABLE latest_deletion_root ( + Lock char(1) NOT NULL DEFAULT 'X', + deletion_timestamp TIMESTAMPTZ, + constraint PK_T1 PRIMARY KEY (Lock), + constraint CK_T1_Locked CHECK (Lock='X') +) \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index e2c620c3..dcaca85c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -155,7 +155,6 @@ impl App { let database = Arc::new(db); let mut provers: HashSet = database.get_provers().await?; - // TODO: need to update this let non_inserted_provers = Self::merge_env_provers(options.batch_provers, &mut provers); database.insert_provers(non_inserted_provers).await?; @@ -372,6 +371,13 @@ impl App { return Err(ServerError::IdentityQueuedForDeletion); } + // Check if there are any deletions, if not, set the latest deletion timestamp + // to now to ensure that the new deletion is processed by the next deletion + // interval + if self.database.get_deletions().await?.is_empty() { + self.database.update_latest_deletion(Utc::now()).await?; + } + // If the id has not been deleted, insert into the deletions table self.database .insert_new_deletion(leaf_index, &commitment) diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index 752fbcf5..6e6f0255 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -7,9 +7,11 @@ abigen!( r#"[ struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, uint32[] calldata deletionIndices, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) + function getRootHistoryExpiry() external view returns (uint256) ]"#, ); diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 4686f796..1c5964c3 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -1,5 +1,5 @@ //! Functionality for interacting with smart contracts deployed on chain. -mod abi; +pub mod abi; use std::collections::HashMap; use std::sync::Arc; @@ -55,13 +55,13 @@ pub struct Options { /// contract. #[derive(Debug)] pub struct IdentityManager { - ethereum: Ethereum, + ethereum: Ethereum, insertion_prover_map: InsertionProverMap, - deletion_prover_map: DeletionProverMap, - abi: WorldId, - secondary_abis: Vec>, - initial_leaf_value: Field, - tree_depth: usize, + deletion_prover_map: DeletionProverMap, + abi: WorldId, + secondary_abis: Vec>, + initial_leaf_value: Field, + tree_depth: usize, } impl IdentityManager { @@ -160,7 +160,7 @@ impl IdentityManager { Ok(()) } - pub async fn get_suitable_prover( + pub async fn get_suitable_insertion_prover( &self, num_identities: usize, ) -> anyhow::Result> { @@ -174,13 +174,31 @@ impl IdentityManager { } } + pub async fn get_suitable_deletion_prover( + &self, + num_identities: usize, + ) -> anyhow::Result> { + let prover_map = self.deletion_prover_map.read().await; + + match RwLockReadGuard::try_map(prover_map, |map| map.get(num_identities)) { + Ok(p) => anyhow::Ok(p), + Err(_) => Err(anyhow!( + "No available prover for batch size: {num_identities}" + )), + } + } + + pub async fn root_history_expiry(&self) -> anyhow::Result { + Ok(self.abi.get_root_history_expiry().call().await?) + } + #[instrument(level = "debug", skip(prover, identity_commitments))] pub async fn prepare_insertion_proof( prover: ReadOnlyInsertionProver<'_>, start_index: usize, pre_root: U256, - post_root: U256, identity_commitments: &[Identity], + post_root: U256, ) -> anyhow::Result { let batch_size = identity_commitments.len(); @@ -204,6 +222,27 @@ impl IdentityManager { Ok(proof_data) } + #[instrument(level = "debug", skip(prover, identity_commitments))] + pub async fn prepare_deletion_proof( + prover: ReadOnlyProver<'_, Prover>, + pre_root: U256, + deletion_indices: &[u32], + identity_commitments: Vec, + post_root: U256, + ) -> anyhow::Result { + info!( + "Sending {} identities to prover of batch size {}", + identity_commitments.len(), + prover.batch_size() + ); + + let proof_data: Proof = prover + .generate_deletion_proof(pre_root, post_root, deletion_indices, identity_commitments) + .await?; + + Ok(proof_data) + } + #[instrument(level = "debug", skip(self, identity_commitments, proof_data))] pub async fn register_identities( &self, @@ -241,6 +280,31 @@ impl IdentityManager { .map_err(|tx_err| anyhow!("{}", tx_err.to_string())) } + // TODO: docs + #[instrument(level = "debug")] + pub async fn delete_identities( + &self, + deletion_proof: Proof, + pre_root: U256, + deletion_indices: Vec, + post_root: U256, + ) -> anyhow::Result { + let proof_points_array: [U256; 8] = deletion_proof.into(); + + // We want to send the transaction through our ethereum provider rather than + // directly now. To that end, we create it, and then send it later, waiting for + // it to complete. + let register_identities_transaction = self + .abi + .delete_identities(proof_points_array, pre_root, deletion_indices, post_root) + .tx; + + self.ethereum + .send_transaction(register_identities_transaction, true) + .await + .map_err(|tx_err| anyhow!("{}", tx_err.to_string())) + } + #[instrument(level = "debug", skip(self))] pub async fn mine_identities(&self, transaction_id: TransactionId) -> anyhow::Result { let result = self.ethereum.mine_transaction(transaction_id).await?; diff --git a/src/database/mod.rs b/src/database/mod.rs index 326eec7b..f1914c1d 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,7 +7,7 @@ use std::collections::HashSet; use anyhow::{anyhow, Context, Error as ErrReport}; -use chrono::Utc; +use chrono::{DateTime, Utc}; use clap::Parser; use sqlx::migrate::{Migrate, MigrateDatabase, Migrator}; use sqlx::pool::PoolOptions; @@ -15,7 +15,7 @@ use sqlx::{Executor, Pool, Postgres, Row}; use thiserror::Error; use tracing::{error, info, instrument, warn}; -use self::types::{DeletionEntry, RecoveryEntry}; +use self::types::{DeletionEntry, LatestDeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod types; @@ -524,6 +524,41 @@ impl Database { Ok(()) } + pub async fn get_latest_deletion(&self) -> Result { + let query = + sqlx::query("SELECT deletion_timestamp FROM latest_deletion_root WHERE Lock = 'X';"); + + let row = self.pool.fetch_optional(query).await?; + + if let Some(row) = row { + Ok(LatestDeletionEntry { + timestamp: row.get(0), + }) + } else { + Ok(LatestDeletionEntry { + timestamp: DateTime::from(Utc::now()), + }) + } + } + + pub async fn update_latest_deletion( + &self, + deletion_timestamp: DateTime, + ) -> Result<(), Error> { + let query = sqlx::query( + r#" + INSERT INTO latest_deletion_root (Lock, deletion_timestamp) + VALUES ('X', $1) + ON CONFLICT (Lock) + DO UPDATE SET deletion_timestamp = EXCLUDED.deletion_timestamp; + "#, + ) + .bind(&deletion_timestamp); + + self.pool.execute(query).await?; + Ok(()) + } + // TODO: consider using a larger value than i64 for leaf index, ruint should // have postgres compatibility for u256 pub async fn get_recoveries(&self) -> Result, Error> { @@ -578,49 +613,45 @@ impl Database { Ok(result .into_iter() .map(|row| DeletionEntry { - leaf_index: row.get::(0), + leaf_index: row.get::(0) as usize, commitment: row.get::(1), }) .collect::>()) } - pub async fn get_eligible_unprocessed_commitments( - &self, - status: Status, - ) -> Result, Error> { - let query = sqlx::query( - r#" - SELECT * FROM unprocessed_identities - WHERE status = $1 AND CURRENT_TIMESTAMP > eligibility - LIMIT $2 - "#, - ) - .bind(<&str>::from(status)) - .bind(MAX_UNPROCESSED_FETCH_COUNT); + /// Remove a list of entries from the deletions table + pub async fn remove_deletions(&self, commitments: Vec) -> Result<(), Error> { + let placeholders: String = commitments + .iter() + .enumerate() + .map(|(i, _)| format!("${}", i + 1)) + .collect::>() + .join(", "); + + let query = format!( + "DELETE FROM deletions WHERE commitment IN ({})", + placeholders + ); - let result = self.pool.fetch_all(query).await?; + let mut query = sqlx::query(&query); - Ok(result - .into_iter() - .map(|row| types::UnprocessedCommitment { - commitment: row.get::(0), - status, - created_at: row.get::<_, _>(2), - processed_at: row.get::<_, _>(3), - error_message: row.get::<_, _>(4), - eligibility_timestamp: row.get::<_, _>(5), - }) - .collect::>()) + for commitment in commitments.iter() { + query = query.bind(commitment); + } + + query.execute(&self.pool).await?; + + Ok(()) } - pub async fn get_unprocessed_commitments( + pub async fn get_eligible_unprocessed_commitments( &self, status: Status, ) -> Result, Error> { let query = sqlx::query( r#" SELECT * FROM unprocessed_identities - WHERE status = $1 + WHERE status = $1 AND CURRENT_TIMESTAMP > eligibility LIMIT $2 "#, ) @@ -637,7 +668,6 @@ impl Database { created_at: row.get::<_, _>(2), processed_at: row.get::<_, _>(3), error_message: row.get::<_, _>(4), - eligibility_timestamp: row.get::<_, _>(5), }) .collect::>()) @@ -860,7 +890,10 @@ mod test { .expect("expected commitment status"); assert_eq!(commit.0, Status::New); - let identity_count = db.get_unprocessed_commitments(Status::New).await?.len(); + let identity_count = db + .get_eligible_unprocessed_commitments(Status::New) + .await? + .len(); assert_eq!(identity_count, 1); @@ -1039,7 +1072,7 @@ mod test { db.insert_new_identity(commitment_1, eligibility_timestamp_1) .await?; - let unprocessed_commitments = db.get_unprocessed_commitments(Status::New).await?; + let unprocessed_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; assert_eq!(unprocessed_commitments.len(), 2); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); @@ -1085,7 +1118,7 @@ mod test { db.insert_new_identity(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_unprocessed_commitments(Status::New).await?; + let commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; assert_eq!(commitments.len(), 1); let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; @@ -1099,7 +1132,7 @@ mod test { db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_unprocessed_commitments(Status::New).await?; + let commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; assert_eq!(commitments.len(), 1); let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; @@ -1524,4 +1557,62 @@ mod test { Ok(()) } + + #[tokio::test] + async fn test_remove_deletions() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let identities = mock_identities(4); + + // Insert new identities + db.insert_new_deletion(0, &identities[0]) + .await + .context("Inserting new identity")?; + + db.insert_new_deletion(1, &identities[1]) + .await + .context("Inserting new identity")?; + + db.insert_new_deletion(2, &identities[2]) + .await + .context("Inserting new identity")?; + db.insert_new_deletion(3, &identities[3]) + .await + .context("Inserting new identity")?; + + // Remove identities 0 to 2 + db.remove_deletions(identities[0..=2].to_vec()).await?; + let deletions = db.get_deletions().await?; + + assert_eq!(deletions.len(), 1); + + Ok(()) + } + + #[tokio::test] + async fn test_latest_deletion_root() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + // Update with initial timestamp + let initial_timestamp = chrono::Utc::now(); + db.update_latest_deletion(initial_timestamp) + .await + .context("Inserting initial root")?; + + // Assert values + let initial_entry = db.get_latest_deletion().await?; + assert_eq!(initial_entry.timestamp, initial_timestamp); + + // Update with a new timestamp + let new_timestamp = chrono::Utc::now(); + db.update_latest_deletion(new_timestamp) + .await + .context("Updating with new root")?; + + // Assert values + let new_entry = db.get_latest_deletion().await?; + assert_eq!(new_entry.timestamp, new_timestamp); + + Ok(()) + } } diff --git a/src/database/types.rs b/src/database/types.rs index a3891197..e3179d3d 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -16,7 +16,12 @@ pub struct RecoveryEntry { pub new_commitment: Hash, } +pub struct LatestDeletionEntry { + pub timestamp: DateTime, +} + +#[derive(Hash, PartialEq, Eq)] pub struct DeletionEntry { - pub leaf_index: i64, // TODO: consider using a larger type for leaf indices + pub leaf_index: usize, pub commitment: Hash, } diff --git a/src/identity_tree.rs b/src/identity_tree.rs index 824a6f51..510f6a4b 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -194,15 +194,32 @@ where (self.tree.root(), proof) } - /// Returns _up to_ `maximum_update_count` updates that are to be applied to - /// the tree. + /// Returns _up to_ `maximum_update_count` contiguous deletion or insertion + /// updates that are to be applied to the tree. fn peek_next_updates(&self, maximum_update_count: usize) -> Vec { - let Some(next) = self.next.as_ref() else { return Vec::new(); }; - + let Some(next) = self.next.as_ref() else { return vec![]; }; let next = next.get_data(); + + let first_is_zero = match next.metadata.diff.first() { + Some(first) => first.update.element == Hash::ZERO, + None => return vec![], + }; + + // Gets the next contiguous of insertion or deletion updates from the diff + let should_take = |elem: &&AppliedTreeUpdate| { + if first_is_zero { + // If first is zero, we should take only consecutive zeros + elem.update.element == Hash::ZERO + } else { + // If first is not zero, we should take only non-zeros + elem.update.element != Hash::ZERO + } + }; + next.metadata .diff .iter() + .take_while(should_take) .take(maximum_update_count) .cloned() .collect() @@ -456,6 +473,23 @@ impl TreeVersion { output } + + /// Deletes many identities from the tree, returns a list with the root + /// and proof of inclusion + pub fn delete_many(&self, leaf_indices: &[usize]) -> Vec<(Hash, Proof)> { + let mut data = self.get_data(); + + let mut output = Vec::with_capacity(leaf_indices.len()); + + for leaf_index in leaf_indices { + data.update(*leaf_index, Hash::ZERO); + let (root, proof) = data.get_proof(*leaf_index); + + output.push((root, proof)); + } + + output + } } /// Public API for working with versions that have a successor. Such versions @@ -664,3 +698,53 @@ impl DerivedTreeBuilder

{ sealed } } + +#[cfg(test)] +mod tests { + use semaphore::lazy_merkle_tree::{Canonical, LazyMerkleTree}; + use semaphore::poseidon_tree::PoseidonHash; + + use super::{ + AppliedTreeUpdate, CanonicalTreeBuilder, DerivedTreeBuilder, Hash, PoseidonTree, + TreeVersion, TreeWithNextVersion, + }; + + #[test] + fn test_peek_next_updates() { + let (canonical_tree, processed_builder) = + CanonicalTreeBuilder::new(10, 10, 0, Hash::ZERO, &vec![]).seal(); + let processed_tree = processed_builder.seal(); + let insertion_updates = processed_tree.append_many(&vec![ + Hash::from(1), + Hash::from(2), + Hash::from(3), + Hash::from(4), + Hash::from(5), + Hash::from(6), + Hash::from(7), + ]); + + let _deletion_updates = processed_tree.delete_many(&vec![0, 1, 2]); + + let next_updates = canonical_tree.peek_next_updates(10); + assert_eq!(next_updates.len(), 7); + + canonical_tree.apply_updates_up_to( + insertion_updates + .last() + .expect("Could not get insertion updates") + .0, + ); + + let _ = processed_tree.append_many(&vec![ + Hash::from(5), + Hash::from(6), + Hash::from(7), + Hash::from(8), + ]); + + let next_updates = canonical_tree.peek_next_updates(10); + + assert_eq!(next_updates.len(), 3); + } +} diff --git a/src/prover/mod.rs b/src/prover/mod.rs index 62f08bbc..f1ab1b9c 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -202,14 +202,18 @@ impl Prover { let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); let identity_commitments: Vec = identities.iter().map(|id| id.commitment).collect(); - let input_hash = - compute_input_hash(start_index, pre_root, post_root, &identity_commitments); + let input_hash = compute_insertion_proof_input_hash( + start_index, + pre_root, + post_root, + &identity_commitments, + ); let merkle_proofs = identities .iter() .map(|id| id.merkle_proof.clone()) .collect(); - let proof_input = ProofInput { + let proof_input = InsertionProofInput { input_hash, start_index, pre_root, @@ -244,12 +248,58 @@ impl Prover { pub async fn generate_deletion_proof( &self, - start_index: u32, pre_root: U256, post_root: U256, - identities: &[Identity], + deletion_indices: &[u32], + identities: Vec, ) -> anyhow::Result { - todo!("TODO:"); + if identities.len() != self.batch_size { + return Err(anyhow::Error::msg( + "Provided batch does not match prover batch size.", + )); + } + + let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); + + let (identity_commitments, merkle_proofs): (Vec, Vec>) = identities + .into_iter() + .map(|id| (id.commitment, id.merkle_proof)) + .unzip(); + + let input_hash = + compute_deletion_proof_input_hash(pre_root, post_root, &identity_commitments); + + let proof_input = DeletionProofInput { + input_hash, + pre_root, + post_root, + deletion_indices: deletion_indices.to_vec(), + identity_commitments, + merkle_proofs, + }; + + let request = self + .client + .post(self.target_url.join(MTB_PROVE_ENDPOINT)?) + .body("OH MY GOD") + .json(&proof_input) + .build()?; + + let prover_proving_time_timer = PROVER_PROVING_TIME.start_timer(); + let proof_term = self.client.execute(request).await?; + let proof_term = proof_term.error_for_status()?; + prover_proving_time_timer.observe_duration(); + + let json = proof_term.text().await?; + + let Ok(proof) = serde_json::from_str::(&json) else { + let error: ProverError = serde_json::from_str(&json)?; + return Err(anyhow::Error::msg(format!("{error}"))) + }; + + total_proving_time_timer.observe_duration(); + + Ok(proof) } pub fn url(&self) -> String { @@ -278,7 +328,7 @@ impl Prover { /// provided in the order that they were inserted into the tree. /// /// The result is computed using the inputs in _big-endian_ byte ordering. -pub fn compute_input_hash( +pub fn compute_insertion_proof_input_hash( start_index: u32, pre_root: U256, post_root: U256, @@ -303,6 +353,30 @@ pub fn compute_input_hash( keccak256(bytes).into() } +// TODO: check this and update docs +pub fn compute_deletion_proof_input_hash( + pre_root: U256, + post_root: U256, + identity_commitments: &[U256], +) -> U256 { + let mut pre_root_bytes: [u8; size_of::()] = Default::default(); + pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); + let mut post_root_bytes: [u8; size_of::()] = Default::default(); + post_root.to_big_endian(post_root_bytes.as_mut_slice()); + + let mut bytes: Vec = vec![]; + bytes.extend(pre_root_bytes.iter()); + bytes.extend(post_root_bytes.iter()); + + for commitment in identity_commitments.iter() { + let mut commitment_bytes: [u8; size_of::()] = Default::default(); + commitment.to_big_endian(commitment_bytes.as_mut_slice()); + bytes.extend(commitment_bytes.iter()); + } + + keccak256(bytes).into() +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct ProverError { @@ -322,7 +396,7 @@ impl Display for ProverError { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -struct ProofInput { +struct InsertionProofInput { input_hash: U256, start_index: u32, pre_root: U256, @@ -331,6 +405,17 @@ struct ProofInput { merkle_proofs: Vec>, } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct DeletionProofInput { + input_hash: U256, + pre_root: U256, + post_root: U256, + deletion_indices: Vec, + identity_commitments: Vec, + merkle_proofs: Vec>, +} + #[cfg(test)] mod test { use super::*; @@ -433,7 +518,7 @@ mod test { let input = get_default_proof_input(); assert_eq!( - compute_input_hash( + compute_insertion_proof_input_hash( input.start_index, input.pre_root, input.post_root, @@ -445,13 +530,13 @@ mod test { #[test] fn proof_input_should_serde() { - let expected_data: ProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); + let expected_data: InsertionProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); let proof_input = get_default_proof_input(); assert_eq!(proof_input, expected_data); } - fn extract_identities_from(proof_input: &ProofInput) -> Vec { + fn extract_identities_from(proof_input: &InsertionProofInput) -> Vec { proof_input .identity_commitments .iter() @@ -473,7 +558,7 @@ mod test { ]) } - fn get_default_proof_input() -> ProofInput { + fn get_default_proof_input() -> InsertionProofInput { let start_index: u32 = 0; let pre_root: U256 = "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2".into(); @@ -521,7 +606,7 @@ mod test { let input_hash: U256 = "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8".into(); - ProofInput { + InsertionProofInput { input_hash, start_index, pre_root, @@ -607,7 +692,7 @@ pub mod mock { impl Service { pub async fn new(url: String) -> anyhow::Result { - let prove = |Json(payload): Json| async move { + let prove = |Json(payload): Json| async move { match payload.post_root.div_mod(U256::from(2)) { (_, y) if y != U256::zero() => { Json(ProveResponse::ProofSuccess(test::get_default_proof_output())) diff --git a/src/task_monitor.rs b/src/task_monitor.rs index 71fd38db..5f61e5fd 100644 --- a/src/task_monitor.rs +++ b/src/task_monitor.rs @@ -10,6 +10,7 @@ use tokio::sync::{broadcast, Notify, RwLock}; use tokio::task::JoinHandle; use tracing::{info, instrument, warn}; +use self::tasks::delete_identities::DeleteIdentities; use self::tasks::finalize_identities::FinalizeRoots; use self::tasks::insert_identities::InsertIdentities; use self::tasks::mine_identities::MineIdentities; @@ -17,7 +18,7 @@ use self::tasks::process_identities::ProcessIdentities; use crate::contracts::SharedIdentityManager; use crate::database::Database; use crate::ethereum::write::TransactionId; -use crate::identity_tree::TreeState; +use crate::identity_tree::{Hash, TreeState}; use crate::utils::async_queue::AsyncQueue; pub mod tasks; @@ -26,6 +27,7 @@ const PROCESS_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const FINALIZE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const MINE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const INSERT_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); +const DELETE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); struct RunningInstance { handles: Vec>, @@ -33,13 +35,59 @@ struct RunningInstance { } #[derive(Debug, Clone)] -pub struct PendingBatchSubmission { +pub struct PendingBatchInsertion { transaction_id: TransactionId, pre_root: U256, post_root: U256, start_index: usize, } +impl PendingBatchInsertion { + pub fn new( + transaction_id: TransactionId, + pre_root: U256, + post_root: U256, + start_index: usize, + ) -> Self { + Self { + transaction_id, + pre_root, + post_root, + start_index, + } + } +} + +#[derive(Debug, Clone)] +pub struct PendingBatchDeletion { + transaction_id: TransactionId, + pre_root: U256, + commitments: Vec, + post_root: U256, +} + +impl PendingBatchDeletion { + pub fn new( + transaction_id: TransactionId, + pre_root: U256, + commitments: Vec, + post_root: U256, + ) -> Self { + Self { + transaction_id, + pre_root, + commitments, + post_root, + } + } +} + +#[derive(Debug, Clone)] +pub enum PendingBatchSubmission { + Insertion(PendingBatchInsertion), + Deletion(PendingBatchDeletion), +} + static PENDING_IDENTITIES: Lazy = Lazy::new(|| { register_gauge!("pending_identities", "Identities not submitted on-chain").unwrap() }); @@ -89,6 +137,14 @@ pub struct Options { #[clap(long, env, default_value = "180")] pub batch_timeout_seconds: u64, + /// TODO: + #[clap(long, env, default_value = "3600")] + pub deletion_time_interval: i64, + + /// TODO: + #[clap(long, env, default_value = "100")] + pub min_batch_deletion_size: usize, + /// How many identities can be held in the API insertion queue at any given /// time Past this limit the API request will block until the queue has /// space for the insertion. @@ -128,6 +184,10 @@ pub struct TaskMonitor { batch_insert_timeout_secs: u64, pending_identities_capacity: usize, mined_roots_capacity: usize, + // TODO: docs + deletion_time_interval: i64, + // TODO: docs + min_batch_deletion_size: usize, } impl TaskMonitor { @@ -140,7 +200,6 @@ impl TaskMonitor { let batch_insert_timeout_secs = options.batch_timeout_seconds; let pending_identities_capacity = options.pending_identities_capacity; let mined_roots_capacity = options.mined_roots_capacity; - Self { instance: RwLock::new(None), database, @@ -149,6 +208,8 @@ impl TaskMonitor { batch_insert_timeout_secs, pending_identities_capacity, mined_roots_capacity, + deletion_time_interval: options.deletion_time_interval, + min_batch_deletion_size: options.min_batch_deletion_size, } } @@ -206,7 +267,7 @@ impl TaskMonitor { handles.push(mine_identities_handle); - // Prcess identities task + // Process identities task let process_identities = ProcessIdentities::new( self.database.clone(), self.identity_manager.clone(), @@ -228,7 +289,7 @@ impl TaskMonitor { let insert_identities = InsertIdentities::new( self.database.clone(), self.tree_state.get_latest_tree(), - wake_up_notify, + wake_up_notify.clone(), ); let insert_identities_handle = crate::utils::spawn_monitored_with_backoff( @@ -239,6 +300,23 @@ impl TaskMonitor { handles.push(insert_identities_handle); + // Delete identities task + let delete_identities = DeleteIdentities::new( + self.database.clone(), + self.tree_state.get_latest_tree(), + self.deletion_time_interval, + self.min_batch_deletion_size, + wake_up_notify, + ); + + let delete_identities_handle = crate::utils::spawn_monitored_with_backoff( + move || delete_identities.clone().run(), + shutdown_sender.clone(), + DELETE_IDENTITIES_BACKOFF, + ); + + handles.push(delete_identities_handle); + *instance = Some(RunningInstance { handles, shutdown_sender, diff --git a/src/task_monitor/tasks/delete_identities.rs b/src/task_monitor/tasks/delete_identities.rs new file mode 100644 index 00000000..79487cf9 --- /dev/null +++ b/src/task_monitor/tasks/delete_identities.rs @@ -0,0 +1,110 @@ +use std::collections::HashSet; +use std::sync::Arc; + +use anyhow::Result as AnyhowResult; +use chrono::{DateTime, Utc}; +use tokio::sync::Notify; +use tracing::info; + +use crate::contracts::SharedIdentityManager; +use crate::database::types::DeletionEntry; +use crate::database::Database; +use crate::identity_tree::{Hash, Latest, TreeVersion}; + +pub struct DeleteIdentities { + database: Arc, + latest_tree: TreeVersion, + deletion_time_interval: i64, + min_deletion_batch_size: usize, + wake_up_notify: Arc, +} + +impl DeleteIdentities { + pub fn new( + database: Arc, + latest_tree: TreeVersion, + deletion_time_interval: i64, + min_deletion_batch_size: usize, + wake_up_notify: Arc, + ) -> Arc { + Arc::new(Self { + database, + latest_tree, + deletion_time_interval, + min_deletion_batch_size, + wake_up_notify, + }) + } + + pub async fn run(self: Arc) -> anyhow::Result<()> { + delete_identities( + &self.database, + &self.latest_tree, + self.deletion_time_interval, + self.min_deletion_batch_size, + self.wake_up_notify.clone(), + ) + .await + } +} + +async fn delete_identities( + database: &Database, + latest_tree: &TreeVersion, + deletion_time_interval: i64, + min_deletion_batch_size: usize, + wake_up_notify: Arc, +) -> AnyhowResult<()> { + info!("Starting deletion processor."); + + let deletion_time_interval = chrono::Duration::seconds(deletion_time_interval); + + loop { + let deletions = database.get_deletions().await?; + if deletions.is_empty() { + // Sleep for one hour + tokio::time::sleep(tokio::time::Duration::from_secs(3600)).await; + continue; + } + + let last_deletion_timestamp = database.get_latest_deletion().await?.timestamp; + // If the minimum deletions batch size is reached or the deletion time interval + // has elapsed, run a batch of deletions + if deletions.len() >= min_deletion_batch_size + || Utc::now() - last_deletion_timestamp > deletion_time_interval + { + // Dedup deletion entries + let deletions = deletions + .into_iter() + .map(|f| f) + .collect::>(); + + let (leaf_indices, previous_commitments): (Vec, Vec) = deletions + .iter() + .map(|d| (d.leaf_index, d.commitment)) + .unzip(); + + // Delete the commitments at the target leaf indices in the latest tree, + // generating the proof for each update + let data = latest_tree.delete_many(&leaf_indices); + + assert_eq!( + data.len(), + leaf_indices.len(), + "Length mismatch when appending identities to tree" + ); + + // Insert the new items into pending identities + let items = data.into_iter().zip(leaf_indices.into_iter()); + for ((root, _proof), leaf_index) in items { + database + .insert_pending_identity(leaf_index, &Hash::ZERO, &root) + .await?; + } + + // Remove the previous commitments from the deletions table + database.remove_deletions(previous_commitments).await?; + wake_up_notify.notify_one(); + } + } +} diff --git a/src/task_monitor/tasks/insert_identities.rs b/src/task_monitor/tasks/insert_identities.rs index 0d990568..cd052d79 100644 --- a/src/task_monitor/tasks/insert_identities.rs +++ b/src/task_monitor/tasks/insert_identities.rs @@ -42,7 +42,9 @@ async fn insert_identities_loop( ) -> AnyhowResult<()> { loop { // get commits from database - let unprocessed = database.get_unprocessed_commitments(Status::New).await?; + let unprocessed = database + .get_eligible_unprocessed_commitments(Status::New) + .await?; if unprocessed.is_empty() { sleep(Duration::from_secs(5)).await; continue; diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs index f7e2b197..49ff3681 100644 --- a/src/task_monitor/tasks/mine_identities.rs +++ b/src/task_monitor/tasks/mine_identities.rs @@ -1,13 +1,18 @@ +use std::collections::HashMap; use std::sync::Arc; -use anyhow::Result as AnyhowResult; +use anyhow::{Context, Result as AnyhowResult}; +use chrono::{DateTime, Days, Utc}; use ethers::types::U256; use tracing::{info, instrument}; +use crate::contracts::abi::WorldId; use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; -use crate::identity_tree::{Intermediate, TreeVersion, TreeWithNextVersion}; -use crate::task_monitor::{PendingBatchSubmission, TaskMonitor}; +use crate::identity_tree::{Hash, Intermediate, TreeVersion, TreeWithNextVersion}; +use crate::task_monitor::{ + PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, +}; use crate::utils::async_queue::{AsyncPopGuard, AsyncQueue}; pub struct MineIdentities { @@ -57,33 +62,47 @@ async fn mine_identities_loop( loop { let pending_identity = pending_batch_submissions_queue.pop().await; - mine_identities( - &pending_identity, - database, - identity_manager, - mined_tree, - mined_roots_queue, - ) - .await?; + match pending_identity.read().await { + PendingBatchSubmission::Insertion(pending_identity_insertion) => { + mine_insertions( + pending_identity_insertion, + database, + identity_manager, + mined_tree, + mined_roots_queue, + ) + .await?; + } + PendingBatchSubmission::Deletion(pending_identity_deletion) => { + mine_deletions( + pending_identity_deletion, + database, + identity_manager, + mined_tree, + mined_roots_queue, + ) + .await?; + } + } pending_identity.commit().await; } } #[instrument(level = "info", skip_all)] -async fn mine_identities( - pending_identity: &AsyncPopGuard<'_, PendingBatchSubmission>, +async fn mine_insertions( + pending_identity: PendingBatchInsertion, database: &Database, identity_manager: &IdentityManager, mined_tree: &TreeVersion, mined_roots_queue: &AsyncQueue, ) -> AnyhowResult<()> { - let PendingBatchSubmission { + let PendingBatchInsertion { transaction_id, pre_root, post_root, start_index, - } = pending_identity.read().await; + } = pending_identity; info!( start_index, @@ -126,3 +145,90 @@ async fn mine_identities( Ok(()) } + +#[instrument(level = "info", skip_all)] +async fn mine_deletions( + pending_identity_deletion: PendingBatchDeletion, + database: &Database, + identity_manager: &IdentityManager, + mined_tree: &TreeVersion, + mined_roots_queue: &AsyncQueue, +) -> AnyhowResult<()> { + let PendingBatchDeletion { + transaction_id, + pre_root, + post_root, + commitments, + } = pending_identity_deletion; + + info!( + ?pre_root, + ?post_root, + ?transaction_id, + "Mining deletion batch" + ); + + if !identity_manager + .mine_identities(transaction_id.clone()) + .await? + { + panic!( + "Transaction {} failed on chain - sequencer will crash and restart", + transaction_id + ); + } + + // With this done, all that remains is to mark them as submitted to the + // blockchain in the source-of-truth database, and also update the mined tree to + // agree with the database and chain. + database.mark_root_as_processed(&post_root.into()).await?; + + // Update the latest deletion + database.update_latest_deletion(Utc::now()).await?; + + info!(?pre_root, ?post_root, "Deletion batch mined"); + + let updates_count = mined_tree.apply_updates_up_to(post_root.into()); + + mined_roots_queue.push(post_root).await; + + info!(updates_count, ?pre_root, ?post_root, "Mined tree updated"); + + // Check if any deleted commitments correspond with entries in the + // recoveries table and insert the new commitment into the unprocessed + // identities table with the proper eligibility timestamp + let recoveries = database + .get_recoveries() + .await? + .iter() + .map(|f| (f.existing_commitment, f.new_commitment)) + .collect::>(); + + // Fetch the root history expiry time on chain + let root_history_expiry = identity_manager.root_history_expiry().await?; + + // Use the root history expiry to calcuate the eligibility timestamp for the new + // insertion + let eligibility_timestamp = DateTime::from_utc( + chrono::NaiveDateTime::from_timestamp_opt( + Utc::now().timestamp() + root_history_expiry.as_u64() as i64, + 0, + ) + .context("Could not convert eligibility timestamp to NaiveDateTime")?, + Utc, + ); + + // For each deletion, if there is a corresponding recovery, insert a new + // identity with the specified eligibility timestamp + for prev_commitment in commitments { + if let Some(new_commitment) = recoveries.get(&prev_commitment.into()) { + database + .insert_new_identity(*new_commitment, eligibility_timestamp) + .await?; + } + } + + TaskMonitor::log_identities_queues(database).await?; + + Ok(()) +} diff --git a/src/task_monitor/tasks/mod.rs b/src/task_monitor/tasks/mod.rs index 8ad56242..8db72a66 100644 --- a/src/task_monitor/tasks/mod.rs +++ b/src/task_monitor/tasks/mod.rs @@ -1,3 +1,4 @@ +pub mod delete_identities; pub mod finalize_identities; pub mod insert_identities; pub mod mine_identities; diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 2ec0ca96..139b704d 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -1,7 +1,9 @@ +use std::collections::HashMap; use std::sync::Arc; use std::time::{Duration, SystemTime}; -use anyhow::Result as AnyhowResult; +use anyhow::{Context, Result as AnyhowResult}; +use chrono::{Days, Utc}; use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{register_histogram, Histogram}; @@ -13,11 +15,14 @@ use tracing::{debug, error, info, instrument, warn}; use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; use crate::identity_tree::{ - AppliedTreeUpdate, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, + AppliedTreeUpdate, Hash, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, }; use crate::prover::identity::Identity; use crate::prover::map::ReadOnlyInsertionProver; -use crate::task_monitor::{PendingBatchSubmission, TaskMonitor}; +use crate::prover::{Proof, Prover, ReadOnlyProver}; +use crate::task_monitor::{ + PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, +}; use crate::utils::async_queue::AsyncQueue; /// The number of seconds either side of the timer tick to treat as enough to @@ -119,21 +124,12 @@ async fn process_identities( continue; } - let prover = identity_manager.get_suitable_prover(updates.len()).await?; - - info!( - "Sending timed-out batch with {}/{} updates.", - updates.len(), - prover.batch_size() - ); - commit_identities( database, identity_manager, batching_tree, pending_batch_submissions_queue, &updates, - prover ).await?; last_batch_time = SystemTime::now(); @@ -179,15 +175,12 @@ async fn process_identities( continue; } - let prover = identity_manager.get_suitable_prover(updates.len()).await?; - commit_identities( database, identity_manager, batching_tree, pending_batch_submissions_queue, &updates, - prover ).await?; // We've inserted the identities, so we want to ensure that @@ -203,14 +196,73 @@ async fn process_identities( } } -#[instrument(level = "info", skip_all)] async fn commit_identities( database: &Database, identity_manager: &IdentityManager, batching_tree: &TreeVersion, pending_batch_submissions_queue: &AsyncQueue, updates: &[AppliedTreeUpdate], - insertion_prover: ReadOnlyInsertionProver<'_>, +) -> AnyhowResult<()> { + // If the update is an insertion + if updates + .first() + .context("Updates should be > 1")? + .update + .element + != Hash::ZERO + { + let prover = identity_manager + .get_suitable_insertion_prover(updates.len()) + .await?; + + info!( + "Sending timed-out insertion batch with {}/{} updates.", + updates.len(), + prover.batch_size() + ); + + insert_identities( + database, + identity_manager, + batching_tree, + pending_batch_submissions_queue, + &updates, + prover, + ) + .await?; + } else { + let prover = identity_manager + .get_suitable_deletion_prover(updates.len()) + .await?; + + info!( + "Sending timed-out deletion batch with {}/{} updates.", + updates.len(), + prover.batch_size() + ); + + delete_identities( + database, + identity_manager, + batching_tree, + pending_batch_submissions_queue, + &updates, + prover, + ) + .await?; + } + + Ok(()) +} + +#[instrument(level = "info", skip_all)] +pub async fn insert_identities( + database: &Database, + identity_manager: &IdentityManager, + batching_tree: &TreeVersion, + pending_batch_submissions_queue: &AsyncQueue, + updates: &[AppliedTreeUpdate], + prover: ReadOnlyProver<'_, Prover>, ) -> AnyhowResult<()> { TaskMonitor::log_identities_queues(database).await?; @@ -221,7 +273,6 @@ async fn commit_identities( debug!("Starting identity commit for {} identities.", updates.len()); - // Sanity check that the insertions are to consecutive leaves in the tree. let mut last_index = updates .first() .expect("Updates is non empty.") @@ -238,6 +289,7 @@ async fn commit_identities( } // Grab the initial conditions before the updates are applied to the tree. + let start_index = updates[0].update.leaf_index; let pre_root: U256 = batching_tree.get_root().into(); let mut commitments: Vec = updates @@ -273,7 +325,7 @@ async fn commit_identities( "Number of identities does not match the number of merkle proofs." ); - let batch_size = insertion_prover.batch_size(); + let batch_size = prover.batch_size(); // The verifier and prover can only work with a given batch size, so we need to // ensure that our batches match that size. We do this by padding with @@ -329,17 +381,13 @@ async fn commit_identities( // We prepare the proof before reserving a slot in the pending identities let proof = IdentityManager::prepare_insertion_proof( - insertion_prover, + prover, start_index, pre_root, - post_root, &identity_commitments, + post_root, ) - .await - .map_err(|e| { - error!(?e, "Failed to prepare proof."); - e - })?; + .await?; #[allow(clippy::cast_precision_loss)] PENDING_IDENTITIES_CHANNEL_CAPACITY.observe(pending_batch_submissions_queue.len().await as f64); @@ -349,7 +397,12 @@ async fn commit_identities( // identities to mine. let permit = pending_batch_submissions_queue.reserve().await; - info!(start_index, ?pre_root, ?post_root, "Submitting batch"); + info!( + start_index, + ?pre_root, + ?post_root, + "Submitting insertion batch" + ); // With all the data prepared we can submit the identities to the on-chain // identity manager and wait for that transaction to be mined. @@ -372,23 +425,190 @@ async fn commit_identities( ?pre_root, ?post_root, ?transaction_id, - "Batch submitted" + "Insertion batch submitted" ); // The transaction will be awaited on asynchronously permit - .send(PendingBatchSubmission { + .send(PendingBatchSubmission::Insertion( + PendingBatchInsertion::new(transaction_id, pre_root, post_root, start_index), + )) + .await; + + // Update the batching tree only after submitting the identities to the chain + batching_tree.apply_updates_up_to(post_root.into()); + + info!(start_index, ?pre_root, ?post_root, "Tree updated"); + + TaskMonitor::log_batch_size(updates.len()); + + Ok(()) +} + +pub async fn delete_identities( + database: &Database, + identity_manager: &IdentityManager, + batching_tree: &TreeVersion, + pending_batch_submissions_queue: &AsyncQueue, + updates: &[AppliedTreeUpdate], + prover: ReadOnlyProver<'_, Prover>, +) -> AnyhowResult<()> { + TaskMonitor::log_identities_queues(database).await?; + + if updates.is_empty() { + warn!("Identity commit requested with zero identities. Continuing."); + return Ok(()); + } + + debug!("Starting identity commit for {} identities.", updates.len()); + + // Grab the initial conditions before the updates are applied to the tree. + let pre_root: U256 = batching_tree.get_root().into(); + let mut commitments: Vec = updates + .iter() + .map(|update| update.update.element.into()) + .collect(); + + let latest_tree_from_updates = updates + .last() + .expect("Updates is non empty.") + .result + .clone(); + + // Next get merkle proofs for each update - note the proofs are acquired from + // intermediate versions of the tree + let mut merkle_proofs: Vec<_> = updates + .iter() + .map(|update_with_tree| { + update_with_tree + .result + .proof(update_with_tree.update.leaf_index) + }) + .collect(); + + // Grab some variables for sizes to make querying easier. + let commitment_count = updates.len(); + + // If these aren't equal then something has gone terribly wrong and is a + // programmer bug, so we abort. + assert_eq!( + commitment_count, + merkle_proofs.len(), + "Number of identities does not match the number of merkle proofs." + ); + + let batch_size = prover.batch_size(); + + // The verifier and prover can only work with a given batch size, so we need to + // ensure that our batches match that size. We do this by padding with + // subsequent zero identities and their associated merkle proofs if the batch is + // too small. + if commitment_count != batch_size { + // FIXME: I dont think this is going to work for deletions + // TODO: need to check this, but basically we are getting the most recent leaf + // and then using that as the start since deletions can happen out of sequence + + // TODO: Calling count is inefficient because it calls `next()` until the + // iterator is exhausted. Update this to be more efficient + let start_index = latest_tree_from_updates.leaves().count(); + let padding = batch_size - commitment_count; + commitments.append(&mut vec![U256::zero(); padding]); + + // TODO: need to check these indices are correct + for i in start_index..(start_index + padding) { + let proof = latest_tree_from_updates.proof(i); + merkle_proofs.push(proof); + } + } + + let deletion_indices = updates + .iter() + .map(|f| f.update.leaf_index as u32) + .collect::>(); + + assert_eq!( + commitments.len(), + batch_size, + "Mismatch between commitments and batch size." + ); + assert_eq!( + merkle_proofs.len(), + batch_size, + "Mismatch between merkle proofs and batch size." + ); + + // With the updates applied we can grab the value of the tree's new root and + // build our identities for sending to the identity manager. + let post_root: U256 = latest_tree_from_updates.root().into(); + let identity_commitments: Vec = commitments + .iter() + .zip(merkle_proofs) + .map(|(id, prf)| { + let commitment: U256 = id.into(); + let proof: Vec = prf + .0 + .iter() + .map(|branch| match branch { + Branch::Left(v) | Branch::Right(v) => U256::from(*v), + }) + .collect(); + Identity::new(commitment, proof) + }) + .collect(); + + identity_manager.validate_merkle_proofs(&identity_commitments)?; + + // We prepare the proof before reserving a slot in the pending identities + let proof = IdentityManager::prepare_deletion_proof( + prover, + pre_root, + &deletion_indices, + identity_commitments, + post_root, + ) + .await?; + + #[allow(clippy::cast_precision_loss)] + PENDING_IDENTITIES_CHANNEL_CAPACITY.observe(pending_batch_submissions_queue.len().await as f64); + + // This queue's capacity provides us with a natural back-pressure mechanism + // to ensure that we don't overwhelm the identity manager with too many + // identities to mine. + let permit = pending_batch_submissions_queue.reserve().await; + + info!(?pre_root, ?post_root, "Submitting deletion batch"); + + // With all the data prepared we can submit the identities to the on-chain + // identity manager and wait for that transaction to be mined. + let transaction_id = identity_manager + .delete_identities(proof, pre_root, deletion_indices, post_root) + .await + .map_err(|e| { + error!(?e, "Failed to insert identity to contract."); + e + })?; + + info!( + ?pre_root, + ?post_root, + ?transaction_id, + "Deletion batch submitted" + ); + + // The transaction will be awaited on asynchronously + permit + .send(PendingBatchSubmission::Deletion(PendingBatchDeletion::new( transaction_id, pre_root, + commitments, post_root, - start_index, - }) + ))) .await; // Update the batching tree only after submitting the identities to the chain batching_tree.apply_updates_up_to(post_root.into()); - info!(start_index, ?pre_root, ?post_root, "Tree updated"); + info!(?pre_root, ?post_root, "Tree updated"); TaskMonitor::log_batch_size(updates.len()); From 68125ec44acabc51777c4df8dca19c3b54ac0fbb Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Wed, 6 Sep 2023 16:14:16 -0400 Subject: [PATCH 14/45] fixed tests --- src/database/mod.rs | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index f1914c1d..61b226c8 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -728,26 +728,6 @@ impl Database { Ok(()) } - // TODO: add docs - pub async fn update_eligibility_timestamp( - &self, - commitment: Hash, - eligibility_timestamp: sqlx::types::chrono::DateTime, - ) -> Result<(), Error> { - let query = sqlx::query( - r#" - UPDATE unprocessed_identities SET eligibility = $1 - WHERE commitment = $2 - "#, - ) - .bind(eligibility_timestamp) - .bind(commitment); - - self.pool.execute(query).await?; - - Ok(()) - } - pub async fn identity_exists(&self, commitment: Hash) -> Result { let query_unprocessed_identity = sqlx::query( r#"SELECT exists(SELECT 1 FROM unprocessed_identities where commitment = $1)"#, @@ -1058,29 +1038,29 @@ mod test { async fn test_get_unprocessed_commitments() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; + // Insert new identity with a valid eligibility timestamp let commitment_0: Uint<256, 4> = Uint::from(1); let eligibility_timestamp_0 = DateTime::from(Utc::now()); - db.insert_new_identity(commitment_0, eligibility_timestamp_0) .await?; + // Insert new identity with eligibility timestamp in the future let commitment_1: Uint<256, 4> = Uint::from(2); let eligibility_timestamp_1 = DateTime::from(Utc::now()) .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); - db.insert_new_identity(commitment_1, eligibility_timestamp_1) .await?; let unprocessed_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; - assert_eq!(unprocessed_commitments.len(), 2); + // Assert unprocessed commitments against expected values + assert_eq!(unprocessed_commitments.len(), 1); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); assert_eq!( unprocessed_commitments[0].eligibility_timestamp, eligibility_timestamp_0 ); - assert_eq!(unprocessed_commitments[1].commitment, commitment_1); assert_eq!( unprocessed_commitments[1].eligibility_timestamp, @@ -1129,14 +1109,13 @@ mod test { .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); - db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) + // Insert new identity with an eligibility timestamp in the future + let commit_hash: Hash = Hash::from(1); + db.insert_new_identity(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; - assert_eq!(commitments.len(), 1); - let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; - assert_eq!(eligible_commitments.len(), 0); + assert_eq!(eligible_commitments.len(), 1); Ok(()) } From 490f7904a7a4d6d4dc75c2908e79281ab806f7dc Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:47:45 -0400 Subject: [PATCH 15/45] Deletion proof padding (#593) * updated padding for deletion proof * updated deletion padding * packed deletion indices into bytearray * removed unused import * added padding for merkle proofs and commitments * fixed import * removed deletion index packing from deletion proof, added index packing to contract function input for delete_identities * updated zeroed proof --- src/contracts/abi.rs | 2 +- src/contracts/mod.rs | 13 ++++- src/task_monitor/tasks/process_identities.rs | 54 +++++++++----------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index 6e6f0255..07e69fe7 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -7,7 +7,7 @@ abigen!( r#"[ struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual - function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, uint32[] calldata deletionIndices, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, bytes calldata deletionIndices, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 1c5964c3..504353c5 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use anyhow::anyhow; use clap::Parser; +use ethers::abi::ethabi::Bytes; use ethers::providers::Middleware; use ethers::types::{Address, U256}; use semaphore::Field; @@ -294,9 +295,19 @@ impl IdentityManager { // We want to send the transaction through our ethereum provider rather than // directly now. To that end, we create it, and then send it later, waiting for // it to complete. + let deletion_indices = deletion_indices + .iter() + .flat_map(|&idx| idx.to_be_bytes().to_vec()) + .collect::>(); + let register_identities_transaction = self .abi - .delete_identities(proof_points_array, pre_root, deletion_indices, post_root) + .delete_identities( + proof_points_array, + pre_root, + deletion_indices.into(), + post_root, + ) .tx; self.ethereum diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 139b704d..0f8fad56 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -7,7 +7,9 @@ use chrono::{Days, Utc}; use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{register_histogram, Histogram}; -use semaphore::poseidon_tree::Branch; +use ruint::Uint; +use semaphore::merkle_tree::Proof; +use semaphore::poseidon_tree::{Branch, PoseidonHash}; use tokio::sync::Notify; use tokio::{select, time}; use tracing::{debug, error, info, instrument, warn}; @@ -19,7 +21,7 @@ use crate::identity_tree::{ }; use crate::prover::identity::Identity; use crate::prover::map::ReadOnlyInsertionProver; -use crate::prover::{Proof, Prover, ReadOnlyProver}; +use crate::prover::{Prover, ReadOnlyProver}; use crate::task_monitor::{ PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, }; @@ -499,42 +501,34 @@ pub async fn delete_identities( let batch_size = prover.batch_size(); + let mut deletion_indices = updates + .iter() + .map(|f| f.update.leaf_index as u32) + .collect::>(); + // The verifier and prover can only work with a given batch size, so we need to - // ensure that our batches match that size. We do this by padding with - // subsequent zero identities and their associated merkle proofs if the batch is - // too small. - if commitment_count != batch_size { - // FIXME: I dont think this is going to work for deletions - // TODO: need to check this, but basically we are getting the most recent leaf - // and then using that as the start since deletions can happen out of sequence + // ensure that our batches match that size. We do this by padding deletion + // indices with tree.depth() ^ 2. The deletion prover will skip the proof for + // any deletion with an index greater than the max tree depth + let pad_index = latest_tree_from_updates.depth().pow(2) as u32; - // TODO: Calling count is inefficient because it calls `next()` until the - // iterator is exhausted. Update this to be more efficient - let start_index = latest_tree_from_updates.leaves().count(); + if commitment_count != batch_size { let padding = batch_size - commitment_count; - commitments.append(&mut vec![U256::zero(); padding]); + commitments.extend(vec![U256::zero(); padding]); + deletion_indices.extend(vec![pad_index; padding]); - // TODO: need to check these indices are correct - for i in start_index..(start_index + padding) { - let proof = latest_tree_from_updates.proof(i); - merkle_proofs.push(proof); - } - } + let zeroed_proof = Proof(vec![ + Branch::Left(Uint::ZERO); + latest_tree_from_updates.depth() + ]); - let deletion_indices = updates - .iter() - .map(|f| f.update.leaf_index as u32) - .collect::>(); + merkle_proofs.extend(vec![zeroed_proof; padding]); + } assert_eq!( - commitments.len(), + deletion_indices.len(), batch_size, - "Mismatch between commitments and batch size." - ); - assert_eq!( - merkle_proofs.len(), - batch_size, - "Mismatch between merkle proofs and batch size." + "Mismatch between deletion indices length and batch size." ); // With the updates applied we can grab the value of the tree's new root and From a45cafe81abe7e0532b377237376e1a575d6ee1e Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:02:33 -0400 Subject: [PATCH 16/45] Deletion / Recovery Tests (#596) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added deletion test * added deleltion prover setup to spawn_deps * patched test_get_unprocessed_commitments * updated test setup, updated delete identities test, patched get_leaf fucntion for TreeVersionData * updated deletion test * updated identities table to drop unique commitment constraint * added recovery test * added a note that we need a mock deletion proof * updated deletion test * updated mock prover to handle deletion input * patched prove function * updated prove_deletion for mock prover * Add V2 chain mocks (#594) * updated compute_deletion_proof_input_hash * patched mock deletion proof * fixed id commitment population during deletion * updated input hash computation for deletion * updated logging * Fix verifier for deletion * Dzejkop/deletion-recovery-tests-fixes (#595) * Fix deletion tests * Remove commented out code * updated deletion test with todo * updated recovery test * add padded deletion test panicking atm * updated recovery test * updated pad index * added test function to get inclusion status * updated recovery test * Add V2 chain mocks (#594) * patched mock deletion proof * fixed id commitment population during deletion * updated input hash computation for deletion * updated logging * Fix verifier for deletion * Dzejkop/deletion-recovery-tests-fixes (#595) * Fix deletion tests * Remove commented out code * updated deletion test with todo * add padded deletion test panicking atm * fix calculation and rebase on fix still doesn't go through * conflict fix * updated BasicTreeOps to only update next leaf on non zero insertion * updated inclusion proof assertion for recover identity * updated inclusion proof inputs after recoveries * updated recover_identity to check inclusion status of replacement identities * patched recover identity test * add padded deletion tests (#597) * rebase on latest changes * Fix * rebase on latest changes * rebase on latest deletion-recovery-branch commit * fix merge conflict --------- Co-authored-by: Dzejkop * cargo fmt * chore: cargo clippy * chore: removed unused file * chore: removed duplicate test --------- Co-authored-by: Jakub TrÄ…d Co-authored-by: dcbuilder.eth --- schemas/database/004_identities.up.sql | 3 + sol/SimpleStateBridge.json | 414 - sol/WorldIDIdentityManagerImplV1.json | 18161 ----------------- sol/WorldIDIdentityManagerImplV2.json | 6052 ++++++ src/app.rs | 24 +- src/contracts/abi.rs | 2 +- src/contracts/mod.rs | 27 +- src/database/mod.rs | 71 +- src/identity_tree.rs | 69 +- src/prover/map.rs | 2 +- src/prover/mod.rs | 49 +- src/server/mod.rs | 11 +- src/task_monitor.rs | 11 +- src/task_monitor/tasks/delete_identities.rs | 10 +- src/task_monitor/tasks/mine_identities.rs | 6 +- src/task_monitor/tasks/process_identities.rs | 51 +- tests/common/abi.rs | 4 +- tests/common/chain_mock.rs | 66 +- tests/common/mod.rs | 232 +- tests/common/prover_mock.rs | 150 +- tests/delete_identity.rs | 160 + tests/delete_padded_identity.rs | 182 + tests/dynamic_batch_sizes.rs | 10 +- tests/insert_identity_and_proofs.rs | 8 +- tests/malformed_payload.rs | 8 +- tests/multi_prover.rs | 15 +- tests/recover_identity.rs | 201 + tests/unavailable_prover.rs | 8 +- tests/validate_proofs.rs | 8 +- 29 files changed, 7231 insertions(+), 18784 deletions(-) delete mode 100644 sol/SimpleStateBridge.json delete mode 100644 sol/WorldIDIdentityManagerImplV1.json create mode 100644 sol/WorldIDIdentityManagerImplV2.json create mode 100644 tests/delete_identity.rs create mode 100644 tests/delete_padded_identity.rs create mode 100644 tests/recover_identity.rs diff --git a/schemas/database/004_identities.up.sql b/schemas/database/004_identities.up.sql index 3c824bcf..ef302c7f 100644 --- a/schemas/database/004_identities.up.sql +++ b/schemas/database/004_identities.up.sql @@ -4,6 +4,9 @@ ALTER TABLE identities ADD COLUMN id BIGSERIAL; -- Set the new 'id' column as NOT NULL ALTER TABLE identities ALTER COLUMN id SET NOT NULL; +-- Drop the unique commitment constraint to allow for 0x00 to be inserted for deletions +ALTER TABLE identities DROP CONSTRAINT identities_commitment_key; + -- Set the id to be unique ALTER TABLE identities ADD CONSTRAINT id_unique UNIQUE(id); diff --git a/sol/SimpleStateBridge.json b/sol/SimpleStateBridge.json deleted file mode 100644 index c52090c4..00000000 --- a/sol/SimpleStateBridge.json +++ /dev/null @@ -1,414 +0,0 @@ -{ - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "name": "StateRootSentMultichain", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "name": "sendRootMultichain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": { - "object": "0x608060405234801561001057600080fd5b5060ba8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063393170cf14602d575b600080fd5b603c6038366004606c565b603e565b005b60405181907f118a5978e509351fb120eb558e2dc9bd6db3cf57cf66ec9744ef8acabf3b0aec90600090a250565b600060208284031215607d57600080fd5b503591905056fea264697066735822122009366b28a1bae882fe05cdba91a291fdd9387e34205b1448e93122db6c68797264736f6c63430008130033", - "sourceMap": "337:223:57:-:0;;;;;;;;;;;;;;;;;;;", - "linkReferences": {} - }, - "deployedBytecode": { - "object": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063393170cf14602d575b600080fd5b603c6038366004606c565b603e565b005b60405181907f118a5978e509351fb120eb558e2dc9bd6db3cf57cf66ec9744ef8acabf3b0aec90600090a250565b600060208284031215607d57600080fd5b503591905056fea264697066735822122009366b28a1bae882fe05cdba91a291fdd9387e34205b1448e93122db6c68797264736f6c63430008130033", - "sourceMap": "337:223:57:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;439:119;;;;;;:::i;:::-;;:::i;:::-;;;522:29;;546:4;;522:29;;;;;439:119;:::o;14:180:78:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:78;;14:180;-1:-1:-1;14:180:78:o", - "linkReferences": {} - }, - "methodIdentifiers": { - "sendRootMultichain(uint256)": "393170cf" - }, - "rawMetadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"StateRootSentMultichain\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"sendRootMultichain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Worldcoin\",\"kind\":\"dev\",\"methods\":{\"sendRootMultichain(uint256)\":{\"details\":\"Calls this method on the L1 Proxy contract to relay the latest root to all supported networks\",\"params\":{\"root\":\"The latest Semaphore root.\"}}},\"title\":\"State Bridge Mock\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"sendRootMultichain(uint256)\":{\"notice\":\"Sends the latest Semaphore root to Optimism.\"}},\"notice\":\"This purely exists to allow tests to compile and does not have any functionality.A dumb bridge to make it easy to fuzz test successes and failures.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/test/mock/SimpleStateBridge.sol\":\"SimpleStateBridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@zk-kit/=lib/zk-kit/packages/\",\":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":ds-test/=lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/\",\":semaphore/=lib/semaphore/packages/contracts/contracts/\",\":solmate/=lib/solmate/src/\",\":zk-kit/=lib/zk-kit/\"]},\"sources\":{\"src/interfaces/IBridge.sol\":{\"keccak256\":\"0xaa64f67fb28b78d9c270cdbebe00f19611e0eadb67c4287172c805cc2380d8d6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b79e327de5168c65e7d55009533f5d5c2b4262c4c0c86dccd8f8f495e5a7c37d\",\"dweb:/ipfs/QmYCeKYuT84QjdFaVh4vuJYV9aCjB9KyLvcpc73mzc3qXH\"]},\"src/test/mock/SimpleStateBridge.sol\":{\"keccak256\":\"0x70606221ef1952ff696af15db7881b0005b7c10b4934cc4b4f4f61a035792825\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0b451b400c0cb68338d9a09a800f8e259718f19e207a69e159f7117d3a551a10\",\"dweb:/ipfs/QmSgZWVfbnNttEzw8JSbLM2id8uacy7mztwP9EmD59BboC\"]}},\"version\":1}", - "metadata": { - "compiler": { - "version": "0.8.19+commit.7dd6d404" - }, - "language": "Solidity", - "output": { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256", - "indexed": true - } - ], - "type": "event", - "name": "StateRootSentMultichain", - "anonymous": false - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "sendRootMultichain" - } - ], - "devdoc": { - "kind": "dev", - "methods": { - "sendRootMultichain(uint256)": { - "details": "Calls this method on the L1 Proxy contract to relay the latest root to all supported networks", - "params": { - "root": "The latest Semaphore root." - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "sendRootMultichain(uint256)": { - "notice": "Sends the latest Semaphore root to Optimism." - } - }, - "version": 1 - } - }, - "settings": { - "remappings": [ - ":@zk-kit/=lib/zk-kit/packages/", - ":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", - ":ds-test/=lib/ds-test/src/", - ":forge-std/=lib/forge-std/src/", - ":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", - ":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", - ":semaphore/=lib/semaphore/packages/contracts/contracts/", - ":solmate/=lib/solmate/src/", - ":zk-kit/=lib/zk-kit/" - ], - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "compilationTarget": { - "src/test/mock/SimpleStateBridge.sol": "SimpleStateBridge" - }, - "libraries": {} - }, - "sources": { - "src/interfaces/IBridge.sol": { - "keccak256": "0xaa64f67fb28b78d9c270cdbebe00f19611e0eadb67c4287172c805cc2380d8d6", - "urls": [ - "bzz-raw://b79e327de5168c65e7d55009533f5d5c2b4262c4c0c86dccd8f8f495e5a7c37d", - "dweb:/ipfs/QmYCeKYuT84QjdFaVh4vuJYV9aCjB9KyLvcpc73mzc3qXH" - ], - "license": "MIT" - }, - "src/test/mock/SimpleStateBridge.sol": { - "keccak256": "0x70606221ef1952ff696af15db7881b0005b7c10b4934cc4b4f4f61a035792825", - "urls": [ - "bzz-raw://0b451b400c0cb68338d9a09a800f8e259718f19e207a69e159f7117d3a551a10", - "dweb:/ipfs/QmSgZWVfbnNttEzw8JSbLM2id8uacy7mztwP9EmD59BboC" - ], - "license": "MIT" - } - }, - "version": 1 - }, - "ast": { - "absolutePath": "src/test/mock/SimpleStateBridge.sol", - "id": 35680, - "exportedSymbols": { - "IBridge": [ - 26700 - ], - "SimpleStateBridge": [ - 35679 - ] - }, - "nodeType": "SourceUnit", - "src": "32:529:57", - "nodes": [ - { - "id": 35658, - "nodeType": "PragmaDirective", - "src": "32:24:57", - "nodes": [], - "literals": [ - "solidity", - "^", - "0.8", - ".19" - ] - }, - { - "id": 35660, - "nodeType": "ImportDirective", - "src": "58:53:57", - "nodes": [], - "absolutePath": "src/interfaces/IBridge.sol", - "file": "../../interfaces/IBridge.sol", - "nameLocation": "-1:-1:-1", - "scope": 35680, - "sourceUnit": 26701, - "symbolAliases": [ - { - "foreign": { - "id": 35659, - "name": "IBridge", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26700, - "src": "66:7:57", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 35679, - "nodeType": "ContractDefinition", - "src": "337:223:57", - "nodes": [ - { - "id": 35667, - "nodeType": "EventDefinition", - "src": "381:52:57", - "nodes": [], - "anonymous": false, - "eventSelector": "118a5978e509351fb120eb558e2dc9bd6db3cf57cf66ec9744ef8acabf3b0aec", - "name": "StateRootSentMultichain", - "nameLocation": "387:23:57", - "parameters": { - "id": 35666, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 35665, - "indexed": true, - "mutability": "mutable", - "name": "root", - "nameLocation": "427:4:57", - "nodeType": "VariableDeclaration", - "scope": 35667, - "src": "411:20:57", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 35664, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "411:7:57", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "410:22:57" - } - }, - { - "id": 35678, - "nodeType": "FunctionDefinition", - "src": "439:119:57", - "nodes": [], - "body": { - "id": 35677, - "nodeType": "Block", - "src": "507:51:57", - "nodes": [], - "statements": [ - { - "eventCall": { - "arguments": [ - { - "id": 35674, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 35669, - "src": "546:4:57", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 35673, - "name": "StateRootSentMultichain", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 35667, - "src": "522:23:57", - "typeDescriptions": { - "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", - "typeString": "function (uint256)" - } - }, - "id": 35675, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "522:29:57", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 35676, - "nodeType": "EmitStatement", - "src": "517:34:57" - } - ] - }, - "baseFunctions": [ - 26699 - ], - "functionSelector": "393170cf", - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "sendRootMultichain", - "nameLocation": "448:18:57", - "overrides": { - "id": 35671, - "nodeType": "OverrideSpecifier", - "overrides": [], - "src": "498:8:57" - }, - "parameters": { - "id": 35670, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 35669, - "mutability": "mutable", - "name": "root", - "nameLocation": "475:4:57", - "nodeType": "VariableDeclaration", - "scope": 35678, - "src": "467:12:57", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 35668, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "467:7:57", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "466:14:57" - }, - "returnParameters": { - "id": 35672, - "nodeType": "ParameterList", - "parameters": [], - "src": "507:0:57" - }, - "scope": 35679, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "external" - } - ], - "abstract": false, - "baseContracts": [ - { - "baseName": { - "id": 35662, - "name": "IBridge", - "nameLocations": [ - "367:7:57" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26700, - "src": "367:7:57" - }, - "id": 35663, - "nodeType": "InheritanceSpecifier", - "src": "367:7:57" - } - ], - "canonicalName": "SimpleStateBridge", - "contractDependencies": [], - "contractKind": "contract", - "documentation": { - "id": 35661, - "nodeType": "StructuredDocumentation", - "src": "113:224:57", - "text": "@title State Bridge Mock\n @notice This purely exists to allow tests to compile and does not have any functionality.\n @author Worldcoin\n @notice A dumb bridge to make it easy to fuzz test successes and failures." - }, - "fullyImplemented": true, - "linearizedBaseContracts": [ - 35679, - 26700 - ], - "name": "SimpleStateBridge", - "nameLocation": "346:17:57", - "scope": 35680, - "usedErrors": [] - } - ], - "license": "MIT" - }, - "id": 57 -} \ No newline at end of file diff --git a/sol/WorldIDIdentityManagerImplV1.json b/sol/WorldIDIdentityManagerImplV1.json deleted file mode 100644 index 09f870b5..00000000 --- a/sol/WorldIDIdentityManagerImplV1.json +++ /dev/null @@ -1,18161 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ExpiredRoot", - "type": "error" - }, - { - "inputs": [], - "name": "ImplementationNotInitialized", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "InvalidCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidStateBridgeProxyAddress", - "type": "error" - }, - { - "inputs": [], - "name": "NonExistentRoot", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "providedRoot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "latestRoot", - "type": "uint256" - } - ], - "name": "NotLatestRoot", - "type": "error" - }, - { - "inputs": [], - "name": "ProofValidationFailure", - "type": "error" - }, - { - "inputs": [], - "name": "StateBridgeAlreadyDisabled", - "type": "error" - }, - { - "inputs": [], - "name": "StateBridgeAlreadyEnabled", - "type": "error" - }, - { - "inputs": [], - "name": "StateBridgeProxySendRootMultichainFailure", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "enum WorldIDIdentityManagerImplV1.UnreducedElementType", - "name": "elementType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "element", - "type": "uint256" - } - ], - "name": "UnreducedElement", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "depth", - "type": "uint8" - } - ], - "name": "UnsupportedTreeDepth", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "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" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [], - "name": "NO_SUCH_ROOT", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "supersededTimestamp", - "type": "uint128" - }, - { - "internalType": "bool", - "name": "isValid", - "type": "bool" - } - ], - "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", - "name": "rootInfo", - "type": "tuple" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "startIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "identityCommitments", - "type": "uint256[]" - } - ], - "name": "calculateIdentityRegistrationInputHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "leafIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "oldCommitment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newCommitment", - "type": "uint256" - } - ], - "internalType": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]", - "name": "identities", - "type": "tuple[]" - } - ], - "name": "calculateIdentityUpdateInputHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "name": "checkValidRoot", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableStateBridge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableStateBridge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getIdentityUpdateVerifierLookupTableAddress", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRegisterIdentitiesVerifierLookupTableAddress", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHistoryExpiry", - "outputs": [ - { - "internalType": "uint256", - "name": "expiryTime", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSemaphoreVerifierAddress", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTreeDepth", - "outputs": [ - { - "internalType": "uint8", - "name": "initializedTreeDepth", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "_treeDepth", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "initialRoot", - "type": "uint256" - }, - { - "internalType": "contract VerifierLookupTable", - "name": "_batchInsertionVerifiers", - "type": "address" - }, - { - "internalType": "contract VerifierLookupTable", - "name": "_batchUpdateVerifiers", - "type": "address" - }, - { - "internalType": "contract ISemaphoreVerifier", - "name": "_semaphoreVerifier", - "type": "address" - }, - { - "internalType": "bool", - "name": "_enableStateBridge", - "type": "bool" - }, - { - "internalType": "address", - "name": "initialStateBridgeProxyAddress", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - } - ], - "name": "isInputInReducedForm", - "outputs": [ - { - "internalType": "bool", - "name": "isInReducedForm", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoot", - "outputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "name": "queryRoot", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "supersededTimestamp", - "type": "uint128" - }, - { - "internalType": "bool", - "name": "isValid", - "type": "bool" - } - ], - "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", - "name": "rootInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[8]", - "name": "insertionProof", - "type": "uint256[8]" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "startIndex", - "type": "uint32" - }, - { - "internalType": "uint256[]", - "name": "identityCommitments", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - } - ], - "name": "registerIdentities", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[8]", - "name": "removalProof", - "type": "uint256[8]" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "leafIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "oldCommitment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newCommitment", - "type": "uint256" - } - ], - "internalType": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]", - "name": "removedIdentities", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - } - ], - "name": "removeIdentities", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract VerifierLookupTable", - "name": "newTable", - "type": "address" - } - ], - "name": "setIdentityUpdateVerifierLookupTable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract VerifierLookupTable", - "name": "newTable", - "type": "address" - } - ], - "name": "setRegisterIdentitiesVerifierLookupTable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newExpiryTime", - "type": "uint256" - } - ], - "name": "setRootHistoryExpiry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ISemaphoreVerifier", - "name": "newVerifier", - "type": "address" - } - ], - "name": "setSemaphoreVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newStateBridgeProxyAddress", - "type": "address" - } - ], - "name": "setStateBridgeProxyAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "stateBridgeProxyAddress", - "outputs": [ - { - "internalType": "address", - "name": "proxy", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[8]", - "name": "updateProof", - "type": "uint256[8]" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "leafIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "oldCommitment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newCommitment", - "type": "uint256" - } - ], - "internalType": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]", - "name": "updatedIdentities", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - } - ], - "name": "updateIdentities", - "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" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "signalHash", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nullifierHash", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalNullifierHash", - "type": "uint256" - }, - { - "internalType": "uint256[8]", - "name": "proof", - "type": "uint256[8]" - } - ], - "name": "verifyProof", - "outputs": [], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": { - "object": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051613b1d6200027e600039600081816105e10152818161062a015281816107b5015281816107f5015281816108a3015281816108e301528181610caa01528181610cea01528181610d9901528181610dd901528181610e8601528181610ec601528181610fd201528181611012015281816110b7015281816110f701528181611248015281816112880152818161131301528181611353015281816116b8015281816116f801528181611773015281816117b301528181611849015281816118f90152818161193901528181611a0701528181611a4701528181611b0601528181611b4601528181611c3701528181611c7701528181611d8001528181611dc001528181611e6001528181611ea001528181611f3701528181611f770152818161200a0152818161204a0152818161211101528181612151015281816121f501528181612235015281816122c901528181612309015281816123eb0152818161242b015281816124b7015281816124f7015281816128e20152818161292201528181612a8f0152612acf0152613b1d6000f3fe6080604052600436106101d85760003560e01c80636b05660011610102578063a26b810e11610095578063d7b0fef111610064578063d7b0fef11461056b578063f2038f9514610580578063f2ebe63114610595578063f2fde38b146105b557600080fd5b8063a26b810e14610501578063b139090814610516578063b6621a3d14610536578063c70aa7271461054b57600080fd5b80638c76a909116100d15780638c76a909146104875780638da5cb5b146104a75780638e5cdd50146104c55780638fc22e9f146104ec57600080fd5b80636b05660014610412578063715018a6146104325780638939472e146104475780638b6c56c61461046757600080fd5b80633f7c178d1161017a5780634ffbdde5116101495780634ffbdde51461037757806352d1902d146103a4578063561f204b146103b957806361ea6a8d146103fd57600080fd5b80633f7c178d146102e257806343f974cb1461032f5780634bc511e6146103445780634f1ef2861461036457600080fd5b80632f059fca116101b65780632f059fca146102525780633492315214610272578063354ca120146102a25780633659cfe6146102c257600080fd5b806309edcb9c146101dd5780630e3a12f3146102105780632217b21114610232575b600080fd5b3480156101e957600080fd5b506101fd6101f836600461318b565b6105d5565b6040519081526020015b60405180910390f35b34801561021c57600080fd5b5061023061022b3660046131f3565b6107ab565b005b34801561023e57600080fd5b5061023061024d36600461327b565b610899565b34801561025e57600080fd5b5061023061026d3660046131f3565b610ca0565b34801561027e57600080fd5b5061029261028d3660046132f8565b610d8d565b6040519015158152602001610207565b3480156102ae57600080fd5b506102306102bd366004613311565b610e7c565b3480156102ce57600080fd5b506102306102dd3660046131f3565b610fc8565b3480156102ee57600080fd5b506103026102fd3660046132f8565b611090565b60408051825181526020808401516001600160801b03169082015291810151151590820152606001610207565b34801561033b57600080fd5b506101fd61123c565b34801561035057600080fd5b5061023061035f36600461335c565b611309565b610230610372366004613406565b6116ae565b34801561038357600080fd5b5061038c611767565b6040516001600160a01b039091168152602001610207565b3480156103b057600080fd5b506101fd61183c565b3480156103c557600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610302565b34801561040957600080fd5b506102306118ef565b34801561041e57600080fd5b5061023061042d3660046131f3565b6119fd565b34801561043e57600080fd5b50610230611aea565b34801561045357600080fd5b506102306104623660046131f3565b611afc565b34801561047357600080fd5b506102926104823660046132f8565b611c2b565b34801561049357600080fd5b506101fd6104a23660046134b2565b611d74565b3480156104b357600080fd5b506033546001600160a01b031661038c565b3480156104d157600080fd5b506104da611e54565b60405160ff9091168152602001610207565b3480156104f857600080fd5b5061038c611f2b565b34801561050d57600080fd5b50610230612000565b34801561052257600080fd5b5061023061053136600461335c565b612107565b34801561054257600080fd5b5061038c6121e9565b34801561055757600080fd5b506102306105663660046132f8565b6122bf565b34801561057757600080fd5b506101fd6123df565b34801561058c57600080fd5b5061038c6124ab565b3480156105a157600080fd5b506102306105b0366004613528565b612581565b3480156105c157600080fd5b506102306105d03660046131f3565b612720565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106285760405162461bcd60e51b815260040161061f906135bb565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661065a612796565b6001600160a01b0316146106805760405162461bcd60e51b815260040161061f90613607565b60c95460ff166106a357604051630103019560e11b815260040160405180910390fd5b60408051600080825260208201909252905b838110156107705760008585838181106106d1576106d1613653565b9050606002018036038101906106e79190613669565b8051602080830151604080850151905194955060009461072894930160e09390931b6001600160e01b03191683526004830191909152602482015260440190565b6040516020818303038152906040529050838160405160200161074c9291906136ee565b604051602081830303815290604052935050508061076990613733565b90506106b5565b5060008686836040516020016107889392919061374c565b60408051601f198184030181529190528051602090910120979650505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107f35760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610825612796565b6001600160a01b03161461084b5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661086e57604051630103019560e11b815260040160405180910390fd5b6108766127b2565b61010080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036108e15760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610913612796565b6001600160a01b0316146109395760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661095c57604051630103019560e11b815260040160405180910390fd5b6109646127b2565b61096d85610d8d565b61098f5760008560405163af1e188960e01b815260040161061f929190613779565b60fb5485146109bf5760fb5460405163542fced960e11b815261061f918791600401918252602082015260400190565b6109c881610d8d565b6109ea5760028160405163af1e188960e01b815260040161061f929190613779565b6109f4838361280c565b6000610a038587848787611d74565b90506000610a10826128a6565b60fe54604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015610a5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8391906137a5565b9050806001600160a01b03166343753b4d60405180604001604052808c600060088110610ab257610ab2613653565b602002013581526020018c600160088110610acf57610acf613653565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f600460088110610b1f57610b1f613653565b602002013581526020018f600560088110610b3c57610b3c613653565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610b7057610b70613653565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610ba694939291906137e5565b6020604051808303816000875af1925050508015610be1575060408051601f3d908101601f19168201909252610bde91810190613869565b60015b610c4157610bed613886565b806308c379a003610c265750610c016138a1565b80610c0c5750610c28565b8060405162461bcd60e51b815260040161061f919061392b565b505b604051631e716a8b60e01b815260040160405180910390fd5b80610c5f57604051631e716a8b60e01b815260040160405180910390fd5b60fb859055600089815260fc6020526040902080546001600160801b031916426001600160801b0316179055610c936128d8565b505b505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ce85760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610d1a612796565b6001600160a01b031614610d405760405162461bcd60e51b815260040161061f90613607565b60c95460ff16610d6357604051630103019560e11b815260040160405180910390fd5b610d6b6127b2565b60fe80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610dd75760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610e09612796565b6001600160a01b031614610e2f5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16610e5257604051630103019560e11b815260040160405180910390fd5b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181105b919050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ec45760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ef6612796565b6001600160a01b031614610f1c5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16610f3f57604051630103019560e11b815260040160405180910390fd5b610f4885611c2b565b15610fc1576101005461010154604051634d65479560e11b81526001600160a01b0390921691639aca8f2a91610f9591899188918a9189918991600160a81b900460ff169060040161395e565b60006040518083038186803b158015610fad57600080fd5b505afa158015610c95573d6000803e3d6000fd5b5050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110105760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611042612796565b6001600160a01b0316146110685760405162461bcd60e51b815260040161061f90613607565b61107181612a85565b6040805160008082526020820190925261108d91839190612b2d565b50565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110f55760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611127612796565b6001600160a01b03161461114d5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661117057604051630103019560e11b815260040160405180910390fd5b60fb54820361119d5750506040805160608101825260fb5481526000602082015260019181019190915290565b600082815260fc60205260408120546001600160801b0316908190036111f75760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b60fd546000906112106001600160801b0384164261399a565b604080516060810182528781526001600160801b03909516602086015291101590830152509050919050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112865760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112b8612796565b6001600160a01b0316146112de5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661130157604051630103019560e11b815260040160405180910390fd5b5060fd545b90565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113515760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611383612796565b6001600160a01b0316146113a95760405162461bcd60e51b815260040161061f90613607565b60c95460ff166113cc57604051630103019560e11b815260040160405180910390fd5b6113d46127b2565b6113dd84610d8d565b6113ff5760008460405163af1e188960e01b815260040161061f929190613779565b60fb54841461142f5760fb5460405163542fced960e11b815261061f918691600401918252602082015260400190565b61143881610d8d565b61145a5760028160405163af1e188960e01b815260040161061f929190613779565b6114648383612c9d565b6000611472858386866105d5565b9050600061147f826128a6565b60ff54604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa1580156114ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f291906137a5565b9050806001600160a01b03166343753b4d60405180604001604052808b60006008811061152157611521613653565b602002013581526020018b60016008811061153e5761153e613653565b60200201359052604080516080810182528c820135918101918252908190606082018e60036020020135815250815260200160405180604001604052808e60046008811061158e5761158e613653565b602002013581526020018e6005600881106115ab576115ab613653565b60200201359052905260408051808201909152808d6006602002013581526020018d6007600881106115df576115df613653565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b815260040161161594939291906137e5565b6020604051808303816000875af1925050508015611650575060408051601f3d908101601f1916820190925261164d91810190613869565b60015b61165c57610bed613886565b8061167a57604051631e716a8b60e01b815260040160405180910390fd5b60fb859055600088815260fc6020526040902080546001600160801b031916426001600160801b0316179055610c956128d8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116f65760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611728612796565b6001600160a01b03161461174e5760405162461bcd60e51b815260040161061f90613607565b61175782612a85565b61176382826001612b2d565b5050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036117b15760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166117e3612796565b6001600160a01b0316146118095760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661182c57604051630103019560e11b815260040160405180910390fd5b5060ff546001600160a01b031690565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118dc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161061f565b50600080516020613aa183398151915290565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119375760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611969612796565b6001600160a01b03161461198f5760405162461bcd60e51b815260040161061f90613607565b60c95460ff166119b257604051630103019560e11b815260040160405180910390fd5b6119ba6127b2565b61010154600160a01b900460ff166119e257610101805460ff60a01b1916600160a01b179055565b60405163963a8d4f60e01b815260040160405180910390fd5b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611a455760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611a77612796565b6001600160a01b031614611a9d5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611ac057604051630103019560e11b815260040160405180910390fd5b611ac86127b2565b60ff80546001600160a01b0319166001600160a01b0392909216919091179055565b611af26127b2565b6119fb6000612d4a565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b445760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b76612796565b6001600160a01b031614611b9c5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611bbf57604051630103019560e11b815260040160405180910390fd5b611bc76127b2565b6001600160a01b038116611bee57604051632d566eef60e11b815260040160405180910390fd5b61010154600160a01b900460ff16611c0857611c086118ef565b61010180546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611c755760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ca7612796565b6001600160a01b031614611ccd5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611cf057604051630103019560e11b815260040160405180910390fd5b60fb548214611d6c57600082815260fc602052604090205460fd546001600160801b0390911690611d21824261399a565b1115611d4057604051631d739acf60e11b815260040160405180910390fd5b806001600160801b0316600003611d6a5760405163ddae3b7160e01b815260040160405180910390fd5b505b506001919050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611dbe5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611df0612796565b6001600160a01b031614611e165760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611e3957604051630103019560e11b815260040160405180910390fd5b600086868686866040516020016107889594939291906139ad565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611e9e5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ed0612796565b6001600160a01b031614611ef65760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611f1957604051630103019560e11b815260040160405180910390fd5b5061010154600160a81b900460ff1690565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611f755760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa7612796565b6001600160a01b031614611fcd5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611ff057604051630103019560e11b815260040160405180910390fd5b5060fe546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120485760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661207a612796565b6001600160a01b0316146120a05760405162461bcd60e51b815260040161061f90613607565b60c95460ff166120c357604051630103019560e11b815260040160405180910390fd5b6120cb6127b2565b61010154600160a01b900460ff16156120ee57610101805460ff60a01b19169055565b6040516331ae429160e21b815260040160405180910390fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361214f5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612181612796565b6001600160a01b0316146121a75760405162461bcd60e51b815260040161061f90613607565b60c95460ff166121ca57604051630103019560e11b815260040160405180910390fd5b6121d26127b2565b6121dc8383612d9c565b610fc18585858585611309565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122335760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612265612796565b6001600160a01b03161461228b5760405162461bcd60e51b815260040161061f90613607565b60c95460ff166122ae57604051630103019560e11b815260040160405180910390fd5b50610101546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036123075760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612339612796565b6001600160a01b03161461235f5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661238257604051630103019560e11b815260040160405180910390fd5b61238a6127b2565b806000036123da5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e0000000000604482015260640161061f565b60fd55565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124295760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661245b612796565b6001600160a01b0316146124815760405162461bcd60e51b815260040161061f90613607565b60c95460ff166124a457604051630103019560e11b815260040160405180910390fd5b5060fb5490565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124f55760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612527612796565b6001600160a01b03161461254d5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661257057604051630103019560e11b815260040160405180910390fd5b50610100546001600160a01b031690565b600054600190610100900460ff161580156125a3575060005460ff8083169116105b6126065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161061f565b6000805461ffff191660ff831617610100179055612622612e0c565b61262b88612e43565b61264d57604051630220cee360e61b815260ff8916600482015260240161061f565b6101018054610e1060fd5560fb89905560fe80546001600160a01b03199081166001600160a01b038b81169190911790925560ff805482168a84161781556101008054909216898416179091559085166001600160b01b0319909216600160a81b918c16919091026001600160a81b0319161717600160a01b851515021790556126d5612e6a565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050565b6127286127b2565b6001600160a01b03811661278d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061f565b61108d81612d4a565b600080516020613aa1833981519152546001600160a01b031690565b6033546001600160a01b031633146119fb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161061f565b6000805b828110156128a057600084848381811061282c5761282c613653565b90506020020135905082801561284157508015155b156128625760405163018f31f560e51b81526004810183905260240161061f565b61286b81610d8d565b61288d5760018160405163af1e188960e01b815260040161061f929190613779565b15915061289981613733565b9050612810565b50505050565b60006128d27f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139fe565b92915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036129205760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612952612796565b6001600160a01b0316146129785760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661299b57604051630103019560e11b815260040160405180910390fd5b61010154600160a01b900460ff1680156129c05750610101546001600160a01b031615155b156119fb576101015460fb546040516000926001600160a01b0316916129ec9160240190815260200190565b60408051601f198184030181529181526020820180516001600160e01b031663393170cf60e01b17905251612a219190613a20565b6000604051808303816000865af19150503d8060008114612a5e576040519150601f19603f3d011682016040523d82523d6000602084013e612a63565b606091505b505090508061108d5760405163ca27883560e01b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612acd5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612aff612796565b6001600160a01b031614612b255760405162461bcd60e51b815260040161061f90613607565b61108d6127b2565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612b6557612b6083612ea0565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bbf575060408051601f3d908101601f19168201909252612bbc91810190613a3c565b60015b612c225760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161061f565b600080516020613aa18339815191528114612c915760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161061f565b50612b60838383612f3c565b60005b81811015612b60576000838383818110612cbc57612cbc613653565b905060600201803603810190612cd29190613669565b9050612ce18160200151610d8d565b612d0657602081015160405163af1e188960e01b815261061f91600191600401613779565b612d138160400151610d8d565b612d39576001816040015160405163af1e188960e01b815260040161061f929190613779565b50612d4381613733565b9050612ca0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b81811015612b60576000838383818110612dbb57612dbb613653565b905060600201803603810190612dd19190613669565b90508060400151600014612dfb5760405163018f31f560e51b81526004810183905260240161061f565b50612e0581613733565b9050612d9f565b600054610100900460ff16612e335760405162461bcd60e51b815260040161061f90613a55565b612e3b612f61565b6119fb612f90565b60006010602060ff84168211801590612e6257508060ff168460ff1611155b949350505050565b600054610100900460ff16612e915760405162461bcd60e51b815260040161061f90613a55565b60c9805460ff19166001179055565b6001600160a01b0381163b612f0d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161061f565b600080516020613aa183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612f4583612fb7565b600082511180612f525750805b15612b60576128a08383612ff7565b600054610100900460ff16612f885760405162461bcd60e51b815260040161061f90613a55565b6119fb6130eb565b600054610100900460ff166119fb5760405162461bcd60e51b815260040161061f90613a55565b612fc081612ea0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b61305f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161061f565b600080846001600160a01b03168460405161307a9190613a20565b600060405180830381855af49150503d80600081146130b5576040519150601f19603f3d011682016040523d82523d6000602084013e6130ba565b606091505b50915091506130e28282604051806060016040528060278152602001613ac16027913961311b565b95945050505050565b600054610100900460ff166131125760405162461bcd60e51b815260040161061f90613a55565b6119fb33612d4a565b6060831561312a5750816111f0565b6111f08383815115610c0c5781518083602001fd5b60008083601f84011261315157600080fd5b50813567ffffffffffffffff81111561316957600080fd5b60208301915083602060608302850101111561318457600080fd5b9250929050565b600080600080606085870312156131a157600080fd5b8435935060208501359250604085013567ffffffffffffffff8111156131c657600080fd5b6131d28782880161313f565b95989497509550505050565b6001600160a01b038116811461108d57600080fd5b60006020828403121561320557600080fd5b81356111f0816131de565b8061010081018310156128d257600080fd5b803563ffffffff81168114610e7757600080fd5b60008083601f84011261324857600080fd5b50813567ffffffffffffffff81111561326057600080fd5b6020830191508360208260051b850101111561318457600080fd5b600080600080600080610180878903121561329557600080fd5b61329f8888613210565b955061010087013594506132b66101208801613222565b935061014087013567ffffffffffffffff8111156132d357600080fd5b6132df89828a01613236565b979a969950949794969561016090950135949350505050565b60006020828403121561330a57600080fd5b5035919050565b6000806000806000610180868803121561332a57600080fd5b853594506020860135935060408601359250606086013591506133508760808801613210565b90509295509295909350565b6000806000806000610160868803121561337557600080fd5b61337f8787613210565b9450610100860135935061012086013567ffffffffffffffff8111156133a457600080fd5b6133b08882890161313f565b9699959850966101400135949350505050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff811182821017156133ff576133ff6133c3565b6040525050565b6000806040838503121561341957600080fd5b8235613424816131de565b915060208381013567ffffffffffffffff8082111561344257600080fd5b818601915086601f83011261345657600080fd5b813581811115613468576134686133c3565b6040519150613480601f8201601f19168501836133d9565b808252878482850101111561349457600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806000806000608086880312156134ca57600080fd5b6134d386613222565b94506020860135935060408601359250606086013567ffffffffffffffff8111156134fd57600080fd5b61350988828901613236565b969995985093965092949392505050565b801515811461108d57600080fd5b600080600080600080600060e0888a03121561354357600080fd5b873560ff8116811461355457600080fd5b965060208801359550604088013561356b816131de565b9450606088013561357b816131de565b9350608088013561358b816131de565b925060a088013561359b8161351a565b915060c08801356135ab816131de565b8091505092959891949750929550565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006060828403121561367b57600080fd5b6040516060810181811067ffffffffffffffff8211171561369e5761369e6133c3565b6040526136aa83613222565b815260208301356020820152604083013560408201528091505092915050565b60005b838110156136e55781810151838201526020016136cd565b50506000910152565b600083516137008184602088016136ca565b8351908301906137148183602088016136ca565b01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000600182016137455761374561371d565b5060010190565b8381528260208201526000825161376a8160408501602087016136ca565b91909101604001949350505050565b604081016003841061379b57634e487b7160e01b600052602160045260246000fd5b9281526020015290565b6000602082840312156137b757600080fd5b81516111f0816131de565b8060005b60028110156128a05781518452602093840193909101906001016137c6565b61012081016137f482876137c2565b60408083018660005b6002811015613824576138118383516137c2565b91830191602091909101906001016137fd565b5050505061383560c08301856137c2565b61010082018360005b600181101561385d57815183526020928301929091019060010161383e565b50505095945050505050565b60006020828403121561387b57600080fd5b81516111f08161351a565b600060033d11156113065760046000803e5060005160e01c90565b600060443d10156138af5790565b6040516003193d81016004833e81513d67ffffffffffffffff81602484011181841117156138df57505050505090565b82850191508151818111156138f75750505050505090565b843d87010160208285010111156139115750505050505090565b613920602082860101876133d9565b509095945050505050565b602081526000825180602084015261394a8160408501602087016136ca565b601f01601f19169190910160400192915050565b60006101a08201905087825286602083015285604083015284606083015261010084608084013760ff8316610180830152979650505050505050565b818103818111156128d2576128d261371d565b60e086901b6001600160e01b0319168152600481018590526024810184905260006001600160fb1b038311156139e257600080fd5b8260051b80856044850137919091016044019695505050505050565b600082613a1b57634e487b7160e01b600052601260045260246000fd5b500690565b60008251613a328184602087016136ca565b9190910192915050565b600060208284031215613a4e57600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b1e1c92eedc95f652511b147bb1f74a7227be4e1ca3c66ea0b69932f8258403064736f6c63430008130033", - "sourceMap": "835:44461:29:-:0;;;1332:4:11;1289:48;;10133:281:29;;;;;;;;;-1:-1:-1;10385:22:29;:20;:22::i;:::-;835:44461;;5928:279:10;5996:13;;;;;;;5995:14;5987:66;;;;-1:-1:-1;;;5987:66:10;;216:2:78;5987:66:10;;;198:21:78;255:2;235:18;;;228:30;294:34;274:18;;;267:62;-1:-1:-1;;;345:18:78;;;338:37;392:19;;5987:66:10;;;;;;;;6067:12;;6082:15;6067:12;;;:30;6063:138;;;6113:12;:30;;-1:-1:-1;;6113:30:10;6128:15;6113:30;;;;;;6162:28;;564:36:78;;;6162:28:10;;552:2:78;537:18;6162:28:10;;;;;;;6063:138;5928:279::o;422:184:78:-;835:44461:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", - "linkReferences": {} - }, - "deployedBytecode": { - "object": "0x6080604052600436106101d85760003560e01c80636b05660011610102578063a26b810e11610095578063d7b0fef111610064578063d7b0fef11461056b578063f2038f9514610580578063f2ebe63114610595578063f2fde38b146105b557600080fd5b8063a26b810e14610501578063b139090814610516578063b6621a3d14610536578063c70aa7271461054b57600080fd5b80638c76a909116100d15780638c76a909146104875780638da5cb5b146104a75780638e5cdd50146104c55780638fc22e9f146104ec57600080fd5b80636b05660014610412578063715018a6146104325780638939472e146104475780638b6c56c61461046757600080fd5b80633f7c178d1161017a5780634ffbdde5116101495780634ffbdde51461037757806352d1902d146103a4578063561f204b146103b957806361ea6a8d146103fd57600080fd5b80633f7c178d146102e257806343f974cb1461032f5780634bc511e6146103445780634f1ef2861461036457600080fd5b80632f059fca116101b65780632f059fca146102525780633492315214610272578063354ca120146102a25780633659cfe6146102c257600080fd5b806309edcb9c146101dd5780630e3a12f3146102105780632217b21114610232575b600080fd5b3480156101e957600080fd5b506101fd6101f836600461318b565b6105d5565b6040519081526020015b60405180910390f35b34801561021c57600080fd5b5061023061022b3660046131f3565b6107ab565b005b34801561023e57600080fd5b5061023061024d36600461327b565b610899565b34801561025e57600080fd5b5061023061026d3660046131f3565b610ca0565b34801561027e57600080fd5b5061029261028d3660046132f8565b610d8d565b6040519015158152602001610207565b3480156102ae57600080fd5b506102306102bd366004613311565b610e7c565b3480156102ce57600080fd5b506102306102dd3660046131f3565b610fc8565b3480156102ee57600080fd5b506103026102fd3660046132f8565b611090565b60408051825181526020808401516001600160801b03169082015291810151151590820152606001610207565b34801561033b57600080fd5b506101fd61123c565b34801561035057600080fd5b5061023061035f36600461335c565b611309565b610230610372366004613406565b6116ae565b34801561038357600080fd5b5061038c611767565b6040516001600160a01b039091168152602001610207565b3480156103b057600080fd5b506101fd61183c565b3480156103c557600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610302565b34801561040957600080fd5b506102306118ef565b34801561041e57600080fd5b5061023061042d3660046131f3565b6119fd565b34801561043e57600080fd5b50610230611aea565b34801561045357600080fd5b506102306104623660046131f3565b611afc565b34801561047357600080fd5b506102926104823660046132f8565b611c2b565b34801561049357600080fd5b506101fd6104a23660046134b2565b611d74565b3480156104b357600080fd5b506033546001600160a01b031661038c565b3480156104d157600080fd5b506104da611e54565b60405160ff9091168152602001610207565b3480156104f857600080fd5b5061038c611f2b565b34801561050d57600080fd5b50610230612000565b34801561052257600080fd5b5061023061053136600461335c565b612107565b34801561054257600080fd5b5061038c6121e9565b34801561055757600080fd5b506102306105663660046132f8565b6122bf565b34801561057757600080fd5b506101fd6123df565b34801561058c57600080fd5b5061038c6124ab565b3480156105a157600080fd5b506102306105b0366004613528565b612581565b3480156105c157600080fd5b506102306105d03660046131f3565b612720565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106285760405162461bcd60e51b815260040161061f906135bb565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661065a612796565b6001600160a01b0316146106805760405162461bcd60e51b815260040161061f90613607565b60c95460ff166106a357604051630103019560e11b815260040160405180910390fd5b60408051600080825260208201909252905b838110156107705760008585838181106106d1576106d1613653565b9050606002018036038101906106e79190613669565b8051602080830151604080850151905194955060009461072894930160e09390931b6001600160e01b03191683526004830191909152602482015260440190565b6040516020818303038152906040529050838160405160200161074c9291906136ee565b604051602081830303815290604052935050508061076990613733565b90506106b5565b5060008686836040516020016107889392919061374c565b60408051601f198184030181529190528051602090910120979650505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107f35760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610825612796565b6001600160a01b03161461084b5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661086e57604051630103019560e11b815260040160405180910390fd5b6108766127b2565b61010080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036108e15760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610913612796565b6001600160a01b0316146109395760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661095c57604051630103019560e11b815260040160405180910390fd5b6109646127b2565b61096d85610d8d565b61098f5760008560405163af1e188960e01b815260040161061f929190613779565b60fb5485146109bf5760fb5460405163542fced960e11b815261061f918791600401918252602082015260400190565b6109c881610d8d565b6109ea5760028160405163af1e188960e01b815260040161061f929190613779565b6109f4838361280c565b6000610a038587848787611d74565b90506000610a10826128a6565b60fe54604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015610a5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8391906137a5565b9050806001600160a01b03166343753b4d60405180604001604052808c600060088110610ab257610ab2613653565b602002013581526020018c600160088110610acf57610acf613653565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f600460088110610b1f57610b1f613653565b602002013581526020018f600560088110610b3c57610b3c613653565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610b7057610b70613653565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610ba694939291906137e5565b6020604051808303816000875af1925050508015610be1575060408051601f3d908101601f19168201909252610bde91810190613869565b60015b610c4157610bed613886565b806308c379a003610c265750610c016138a1565b80610c0c5750610c28565b8060405162461bcd60e51b815260040161061f919061392b565b505b604051631e716a8b60e01b815260040160405180910390fd5b80610c5f57604051631e716a8b60e01b815260040160405180910390fd5b60fb859055600089815260fc6020526040902080546001600160801b031916426001600160801b0316179055610c936128d8565b505b505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ce85760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610d1a612796565b6001600160a01b031614610d405760405162461bcd60e51b815260040161061f90613607565b60c95460ff16610d6357604051630103019560e11b815260040160405180910390fd5b610d6b6127b2565b60fe80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610dd75760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610e09612796565b6001600160a01b031614610e2f5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16610e5257604051630103019560e11b815260040160405180910390fd5b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181105b919050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ec45760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ef6612796565b6001600160a01b031614610f1c5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16610f3f57604051630103019560e11b815260040160405180910390fd5b610f4885611c2b565b15610fc1576101005461010154604051634d65479560e11b81526001600160a01b0390921691639aca8f2a91610f9591899188918a9189918991600160a81b900460ff169060040161395e565b60006040518083038186803b158015610fad57600080fd5b505afa158015610c95573d6000803e3d6000fd5b5050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110105760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611042612796565b6001600160a01b0316146110685760405162461bcd60e51b815260040161061f90613607565b61107181612a85565b6040805160008082526020820190925261108d91839190612b2d565b50565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110f55760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611127612796565b6001600160a01b03161461114d5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661117057604051630103019560e11b815260040160405180910390fd5b60fb54820361119d5750506040805160608101825260fb5481526000602082015260019181019190915290565b600082815260fc60205260408120546001600160801b0316908190036111f75760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b60fd546000906112106001600160801b0384164261399a565b604080516060810182528781526001600160801b03909516602086015291101590830152509050919050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112865760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112b8612796565b6001600160a01b0316146112de5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661130157604051630103019560e11b815260040160405180910390fd5b5060fd545b90565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113515760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611383612796565b6001600160a01b0316146113a95760405162461bcd60e51b815260040161061f90613607565b60c95460ff166113cc57604051630103019560e11b815260040160405180910390fd5b6113d46127b2565b6113dd84610d8d565b6113ff5760008460405163af1e188960e01b815260040161061f929190613779565b60fb54841461142f5760fb5460405163542fced960e11b815261061f918691600401918252602082015260400190565b61143881610d8d565b61145a5760028160405163af1e188960e01b815260040161061f929190613779565b6114648383612c9d565b6000611472858386866105d5565b9050600061147f826128a6565b60ff54604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa1580156114ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f291906137a5565b9050806001600160a01b03166343753b4d60405180604001604052808b60006008811061152157611521613653565b602002013581526020018b60016008811061153e5761153e613653565b60200201359052604080516080810182528c820135918101918252908190606082018e60036020020135815250815260200160405180604001604052808e60046008811061158e5761158e613653565b602002013581526020018e6005600881106115ab576115ab613653565b60200201359052905260408051808201909152808d6006602002013581526020018d6007600881106115df576115df613653565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b815260040161161594939291906137e5565b6020604051808303816000875af1925050508015611650575060408051601f3d908101601f1916820190925261164d91810190613869565b60015b61165c57610bed613886565b8061167a57604051631e716a8b60e01b815260040160405180910390fd5b60fb859055600088815260fc6020526040902080546001600160801b031916426001600160801b0316179055610c956128d8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116f65760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611728612796565b6001600160a01b03161461174e5760405162461bcd60e51b815260040161061f90613607565b61175782612a85565b61176382826001612b2d565b5050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036117b15760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166117e3612796565b6001600160a01b0316146118095760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661182c57604051630103019560e11b815260040160405180910390fd5b5060ff546001600160a01b031690565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118dc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161061f565b50600080516020613aa183398151915290565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119375760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611969612796565b6001600160a01b03161461198f5760405162461bcd60e51b815260040161061f90613607565b60c95460ff166119b257604051630103019560e11b815260040160405180910390fd5b6119ba6127b2565b61010154600160a01b900460ff166119e257610101805460ff60a01b1916600160a01b179055565b60405163963a8d4f60e01b815260040160405180910390fd5b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611a455760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611a77612796565b6001600160a01b031614611a9d5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611ac057604051630103019560e11b815260040160405180910390fd5b611ac86127b2565b60ff80546001600160a01b0319166001600160a01b0392909216919091179055565b611af26127b2565b6119fb6000612d4a565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b445760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b76612796565b6001600160a01b031614611b9c5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611bbf57604051630103019560e11b815260040160405180910390fd5b611bc76127b2565b6001600160a01b038116611bee57604051632d566eef60e11b815260040160405180910390fd5b61010154600160a01b900460ff16611c0857611c086118ef565b61010180546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611c755760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ca7612796565b6001600160a01b031614611ccd5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611cf057604051630103019560e11b815260040160405180910390fd5b60fb548214611d6c57600082815260fc602052604090205460fd546001600160801b0390911690611d21824261399a565b1115611d4057604051631d739acf60e11b815260040160405180910390fd5b806001600160801b0316600003611d6a5760405163ddae3b7160e01b815260040160405180910390fd5b505b506001919050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611dbe5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611df0612796565b6001600160a01b031614611e165760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611e3957604051630103019560e11b815260040160405180910390fd5b600086868686866040516020016107889594939291906139ad565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611e9e5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ed0612796565b6001600160a01b031614611ef65760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611f1957604051630103019560e11b815260040160405180910390fd5b5061010154600160a81b900460ff1690565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611f755760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa7612796565b6001600160a01b031614611fcd5760405162461bcd60e51b815260040161061f90613607565b60c95460ff16611ff057604051630103019560e11b815260040160405180910390fd5b5060fe546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120485760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661207a612796565b6001600160a01b0316146120a05760405162461bcd60e51b815260040161061f90613607565b60c95460ff166120c357604051630103019560e11b815260040160405180910390fd5b6120cb6127b2565b61010154600160a01b900460ff16156120ee57610101805460ff60a01b19169055565b6040516331ae429160e21b815260040160405180910390fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361214f5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612181612796565b6001600160a01b0316146121a75760405162461bcd60e51b815260040161061f90613607565b60c95460ff166121ca57604051630103019560e11b815260040160405180910390fd5b6121d26127b2565b6121dc8383612d9c565b610fc18585858585611309565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122335760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612265612796565b6001600160a01b03161461228b5760405162461bcd60e51b815260040161061f90613607565b60c95460ff166122ae57604051630103019560e11b815260040160405180910390fd5b50610101546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036123075760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612339612796565b6001600160a01b03161461235f5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661238257604051630103019560e11b815260040160405180910390fd5b61238a6127b2565b806000036123da5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e0000000000604482015260640161061f565b60fd55565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124295760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661245b612796565b6001600160a01b0316146124815760405162461bcd60e51b815260040161061f90613607565b60c95460ff166124a457604051630103019560e11b815260040160405180910390fd5b5060fb5490565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124f55760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612527612796565b6001600160a01b03161461254d5760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661257057604051630103019560e11b815260040160405180910390fd5b50610100546001600160a01b031690565b600054600190610100900460ff161580156125a3575060005460ff8083169116105b6126065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161061f565b6000805461ffff191660ff831617610100179055612622612e0c565b61262b88612e43565b61264d57604051630220cee360e61b815260ff8916600482015260240161061f565b6101018054610e1060fd5560fb89905560fe80546001600160a01b03199081166001600160a01b038b81169190911790925560ff805482168a84161781556101008054909216898416179091559085166001600160b01b0319909216600160a81b918c16919091026001600160a81b0319161717600160a01b851515021790556126d5612e6a565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050565b6127286127b2565b6001600160a01b03811661278d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061f565b61108d81612d4a565b600080516020613aa1833981519152546001600160a01b031690565b6033546001600160a01b031633146119fb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161061f565b6000805b828110156128a057600084848381811061282c5761282c613653565b90506020020135905082801561284157508015155b156128625760405163018f31f560e51b81526004810183905260240161061f565b61286b81610d8d565b61288d5760018160405163af1e188960e01b815260040161061f929190613779565b15915061289981613733565b9050612810565b50505050565b60006128d27f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139fe565b92915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036129205760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612952612796565b6001600160a01b0316146129785760405162461bcd60e51b815260040161061f90613607565b60c95460ff1661299b57604051630103019560e11b815260040160405180910390fd5b61010154600160a01b900460ff1680156129c05750610101546001600160a01b031615155b156119fb576101015460fb546040516000926001600160a01b0316916129ec9160240190815260200190565b60408051601f198184030181529181526020820180516001600160e01b031663393170cf60e01b17905251612a219190613a20565b6000604051808303816000865af19150503d8060008114612a5e576040519150601f19603f3d011682016040523d82523d6000602084013e612a63565b606091505b505090508061108d5760405163ca27883560e01b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612acd5760405162461bcd60e51b815260040161061f906135bb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612aff612796565b6001600160a01b031614612b255760405162461bcd60e51b815260040161061f90613607565b61108d6127b2565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612b6557612b6083612ea0565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bbf575060408051601f3d908101601f19168201909252612bbc91810190613a3c565b60015b612c225760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161061f565b600080516020613aa18339815191528114612c915760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161061f565b50612b60838383612f3c565b60005b81811015612b60576000838383818110612cbc57612cbc613653565b905060600201803603810190612cd29190613669565b9050612ce18160200151610d8d565b612d0657602081015160405163af1e188960e01b815261061f91600191600401613779565b612d138160400151610d8d565b612d39576001816040015160405163af1e188960e01b815260040161061f929190613779565b50612d4381613733565b9050612ca0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b81811015612b60576000838383818110612dbb57612dbb613653565b905060600201803603810190612dd19190613669565b90508060400151600014612dfb5760405163018f31f560e51b81526004810183905260240161061f565b50612e0581613733565b9050612d9f565b600054610100900460ff16612e335760405162461bcd60e51b815260040161061f90613a55565b612e3b612f61565b6119fb612f90565b60006010602060ff84168211801590612e6257508060ff168460ff1611155b949350505050565b600054610100900460ff16612e915760405162461bcd60e51b815260040161061f90613a55565b60c9805460ff19166001179055565b6001600160a01b0381163b612f0d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161061f565b600080516020613aa183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612f4583612fb7565b600082511180612f525750805b15612b60576128a08383612ff7565b600054610100900460ff16612f885760405162461bcd60e51b815260040161061f90613a55565b6119fb6130eb565b600054610100900460ff166119fb5760405162461bcd60e51b815260040161061f90613a55565b612fc081612ea0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b61305f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161061f565b600080846001600160a01b03168460405161307a9190613a20565b600060405180830381855af49150503d80600081146130b5576040519150601f19603f3d011682016040523d82523d6000602084013e6130ba565b606091505b50915091506130e28282604051806060016040528060278152602001613ac16027913961311b565b95945050505050565b600054610100900460ff166131125760405162461bcd60e51b815260040161061f90613a55565b6119fb33612d4a565b6060831561312a5750816111f0565b6111f08383815115610c0c5781518083602001fd5b60008083601f84011261315157600080fd5b50813567ffffffffffffffff81111561316957600080fd5b60208301915083602060608302850101111561318457600080fd5b9250929050565b600080600080606085870312156131a157600080fd5b8435935060208501359250604085013567ffffffffffffffff8111156131c657600080fd5b6131d28782880161313f565b95989497509550505050565b6001600160a01b038116811461108d57600080fd5b60006020828403121561320557600080fd5b81356111f0816131de565b8061010081018310156128d257600080fd5b803563ffffffff81168114610e7757600080fd5b60008083601f84011261324857600080fd5b50813567ffffffffffffffff81111561326057600080fd5b6020830191508360208260051b850101111561318457600080fd5b600080600080600080610180878903121561329557600080fd5b61329f8888613210565b955061010087013594506132b66101208801613222565b935061014087013567ffffffffffffffff8111156132d357600080fd5b6132df89828a01613236565b979a969950949794969561016090950135949350505050565b60006020828403121561330a57600080fd5b5035919050565b6000806000806000610180868803121561332a57600080fd5b853594506020860135935060408601359250606086013591506133508760808801613210565b90509295509295909350565b6000806000806000610160868803121561337557600080fd5b61337f8787613210565b9450610100860135935061012086013567ffffffffffffffff8111156133a457600080fd5b6133b08882890161313f565b9699959850966101400135949350505050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff811182821017156133ff576133ff6133c3565b6040525050565b6000806040838503121561341957600080fd5b8235613424816131de565b915060208381013567ffffffffffffffff8082111561344257600080fd5b818601915086601f83011261345657600080fd5b813581811115613468576134686133c3565b6040519150613480601f8201601f19168501836133d9565b808252878482850101111561349457600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806000806000608086880312156134ca57600080fd5b6134d386613222565b94506020860135935060408601359250606086013567ffffffffffffffff8111156134fd57600080fd5b61350988828901613236565b969995985093965092949392505050565b801515811461108d57600080fd5b600080600080600080600060e0888a03121561354357600080fd5b873560ff8116811461355457600080fd5b965060208801359550604088013561356b816131de565b9450606088013561357b816131de565b9350608088013561358b816131de565b925060a088013561359b8161351a565b915060c08801356135ab816131de565b8091505092959891949750929550565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006060828403121561367b57600080fd5b6040516060810181811067ffffffffffffffff8211171561369e5761369e6133c3565b6040526136aa83613222565b815260208301356020820152604083013560408201528091505092915050565b60005b838110156136e55781810151838201526020016136cd565b50506000910152565b600083516137008184602088016136ca565b8351908301906137148183602088016136ca565b01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000600182016137455761374561371d565b5060010190565b8381528260208201526000825161376a8160408501602087016136ca565b91909101604001949350505050565b604081016003841061379b57634e487b7160e01b600052602160045260246000fd5b9281526020015290565b6000602082840312156137b757600080fd5b81516111f0816131de565b8060005b60028110156128a05781518452602093840193909101906001016137c6565b61012081016137f482876137c2565b60408083018660005b6002811015613824576138118383516137c2565b91830191602091909101906001016137fd565b5050505061383560c08301856137c2565b61010082018360005b600181101561385d57815183526020928301929091019060010161383e565b50505095945050505050565b60006020828403121561387b57600080fd5b81516111f08161351a565b600060033d11156113065760046000803e5060005160e01c90565b600060443d10156138af5790565b6040516003193d81016004833e81513d67ffffffffffffffff81602484011181841117156138df57505050505090565b82850191508151818111156138f75750505050505090565b843d87010160208285010111156139115750505050505090565b613920602082860101876133d9565b509095945050505050565b602081526000825180602084015261394a8160408501602087016136ca565b601f01601f19169190910160400192915050565b60006101a08201905087825286602083015285604083015284606083015261010084608084013760ff8316610180830152979650505050505050565b818103818111156128d2576128d261371d565b60e086901b6001600160e01b0319168152600481018590526024810184905260006001600160fb1b038311156139e257600080fd5b8260051b80856044850137919091016044019695505050505050565b600082613a1b57634e487b7160e01b600052601260045260246000fd5b500690565b60008251613a328184602087016136ca565b9190910192915050565b600060208284031215613a4e57600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b1e1c92eedc95f652511b147bb1f74a7227be4e1ca3c66ea0b69932f8258403064736f6c63430008130033", - "sourceMap": "835:44461:29:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29877:720;;;;;;;;;;-1:-1:-1;29877:720:29;;;;;:::i;:::-;;:::i;:::-;;;1194:25:78;;;1182:2;1167:18;29877:720:29;;;;;;;;42589:205;;;;;;;;;;-1:-1:-1;42589:205:29;;;;;:::i;:::-;;:::i;:::-;;15922:3385;;;;;;;;;;-1:-1:-1;15922:3385:29;;;;;:::i;:::-;;:::i;40528:226::-;;;;;;;;;;-1:-1:-1;40528:226:29;;;;;:::i;:::-;;:::i;37923:224::-;;;;;;;;;;-1:-1:-1;37923:224:29;;;;;:::i;:::-;;:::i;:::-;;;3820:14:78;;3813:22;3795:41;;3783:2;3768:18;37923:224:29;3655:187:78;44866:428:29;;;;;;;;;;-1:-1:-1;44866:428:29;;;;;:::i;:::-;;:::i;3317:197:11:-;;;;;;;;;;-1:-1:-1;3317:197:11;;;;;:::i;:::-;;:::i;33760:576:29:-;;;;;;;;;;-1:-1:-1;33760:576:29;;;;;:::i;:::-;;:::i;:::-;;;;4851:13:78;;4833:32;;4925:4;4913:17;;;4907:24;-1:-1:-1;;;;;4903:65:78;4881:20;;;4874:95;5027:17;;;5021:24;5014:32;5007:40;4985:20;;;4978:70;4821:2;4806:18;33760:576:29;4633:421:78;42970:200:29;;;;;;;;;;;;;:::i;24400:2949::-;;;;;;;;;;-1:-1:-1;24400:2949:29;;;;;:::i;:::-;;:::i;3763:222:11:-;;;;;;:::i;:::-;;:::i;41048:232:29:-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;7512:32:78;;;7494:51;;7482:2;7467:18;41048:232:29;7348:203:78;3006:131:11;;;;;;;;;;;;;:::i;7105:120:29:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;7193:25:29;;;;;;;;;;;;;;;;;;;;7105:120;;32661:242;;;;;;;;;;;;;:::i;41670:222::-;;;;;;;;;;-1:-1:-1;41670:222:29;;;;;:::i;:::-;;:::i;2071:101:6:-;;;;;;;;;;;;;:::i;32106:439:29:-;;;;;;;;;;-1:-1:-1;32106:439:29;;;;;:::i;:::-;;:::i;39100:631::-;;;;;;;;;;-1:-1:-1;39100:631:29;;;;;:::i;:::-;;:::i;28480:413::-;;;;;;;;;;-1:-1:-1;28480:413:29;;;;;:::i;:::-;;:::i;1441:85:6:-;;;;;;;;;;-1:-1:-1;1513:6:6;;-1:-1:-1;;;;;1513:6:6;1441:85;;43839:192:29;;;;;;;;;;;;;:::i;:::-;;;8379:4:78;8367:17;;;8349:36;;8337:2;8322:18;43839:192:29;8207:184:78;39964:236:29;;;;;;;;;;;;;:::i;33020:244::-;;;;;;;;;;;;;:::i;21567:672::-;;;;;;;;;;-1:-1:-1;21567:672:29;;;;;:::i;:::-;;:::i;31672:205::-;;;;;;;;;;;;;:::i;43402:293::-;;;;;;;;;;-1:-1:-1;43402:293:29;;;;;:::i;:::-;;:::i;30725:126::-;;;;;;;;;;;;;:::i;42076:210::-;;;;;;;;;;;;;:::i;11753:1099::-;;;;;;;;;;-1:-1:-1;11753:1099:29;;;;;:::i;:::-;;:::i;2321:198:6:-;;;;;;;;;;-1:-1:-1;2321:198:6;;;;;:::i;:::-;;:::i;29877:720:29:-;30077:12;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;;;;;;;;;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;30130:12:29::2;::::0;;30101:26:::2;30130:12:::0;;;::::2;::::0;::::2;::::0;;;;30152:312:::2;30172:21:::0;;::::2;30152:312;;;30214:27;30244:10;;30255:1;30244:13;;;;;;;:::i;:::-;;;;;;30214:43;;;;;;;;;;:::i;:::-;30328:15:::0;;30345:19:::2;::::0;;::::2;::::0;30366::::2;::::0;;::::2;::::0;30311:75;;30214:43;;-1:-1:-1;30271:21:29::2;::::0;30311:75:::2;::::0;30328:15;30311:75:::2;11497:3:78::0;11475:16;;;;-1:-1:-1;;;;;;11471:43:78;11459:56;;11540:1;11531:11;;11524:27;;;;11576:2;11567:12;;11560:28;11613:2;11604:12;;11276:346;30311:75:29::2;;;;;;;;;;;;;30271:115;;30429:13;30444:8;30416:37;;;;;;;;;:::i;:::-;;;;;;;;;;;;;30400:53;;30200:264;;30195:3;;;;:::i;:::-;;;30152:312;;;;30473:24;30517:7;30526:8;30536:13;30500:50;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;30500:50:29;;::::2;::::0;;;;;;30568:22;;30500:50:::2;30568:22:::0;;::::2;::::0;;29877:720;-1:-1:-1;;;;;;;29877:720:29:o;42589:205::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;42756:17:29::3;:31:::0;;-1:-1:-1;;;;;;42756:31:29::3;-1:-1:-1::0;;;;;42756:31:29;;;::::3;::::0;;;::::3;::::0;;42589:205::o;15922:3385::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;16259:29:29::3;16280:7;16259:20;:29::i;:::-;16254:123;;16328:28;16358:7;16311:55;;-1:-1:-1::0;;;16311:55:29::3;;;;;;;;;:::i;16254:123::-;16401:11;;16390:7;:22;16386:95;;16458:11;::::0;16435:35:::3;::::0;-1:-1:-1;;;16435:35:29;;::::3;::::0;16449:7;;16435:35:::3;;13684:25:78::0;;;13740:2;13725:18;;13718:34;13672:2;13657:18;;13510:248;16386:95:29::3;16870:30;16891:8;16870:20;:30::i;:::-;16865:126;;16940:29;16971:8;16923:57;;-1:-1:-1::0;;;16923:57:29::3;;;;;;;;;:::i;16865:126::-;17082:63;17125:19;;17082:42;:63::i;:::-;17237:17;17257:112;17309:10;17321:7;17330:8;17340:19;;17257:38;:112::i;:::-;17237:132:::0;-1:-1:-1;17593:22:29::3;17618:56;17237:132:::0;17618:36:::3;:56::i;:::-;17804:23;::::0;:66:::3;::::0;-1:-1:-1;;;17804:66:29;;::::3;::::0;::::3;1194:25:78::0;;;17593:81:29;;-1:-1:-1;17758:31:29::3;::::0;-1:-1:-1;;;;;17804:23:29;;::::3;::::0;:38:::3;::::0;1167:18:78;;17804:66:29::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17758:112;;17939:17;-1:-1:-1::0;;;;;17939:29:29::3;;:267;;;;;;;;17983:14;17998:1;17983:17;;;;;;;:::i;:::-;;;;;17939:267;;;;18002:14;18017:1;18002:17;;;;;;;:::i;:::-;;;;;17939:267:::0;;::::3;::::0;;;;;;;18036:17;;::::3;;17939:267:::0;;::::3;::::0;;;;;;;;;18036:14;18070:1:::3;18055:17;;;;17939:267;;::::0;::::3;;;;;;;;;;;;18076:14;18091:1;18076:17;;;;;;;:::i;:::-;;;;;17939:267;;;;18095:14;18110:1;18095:17;;;;;;;:::i;:::-;;;;;17939:267:::0;;;;::::3;::::0;;;;::::3;::::0;;;;18129:14;18144:1:::3;18129:17;;;;17939:267;;;;18148:14;18163:1;18148:17;;;;;;;:::i;:::-;;;;;17939:267;;::::0;::::3;;;;;;;;18181:14;17939:267;;::::0;::::3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;17939:267:29::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;17939:267:29::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;17935:1366;;;;:::i;:::-;;;::::0;::::3;;;;;:::i;:::-;;;;;;;;19053:9;19046:17;;-1:-1:-1::0;;;19046:17:29::3;;;;;;;;:::i;17935:1366::-;;;19266:24;;-1:-1:-1::0;;;19266:24:29::3;;;;;;;;;;;17935:1366;18326:14;18321:85;;18367:24;;-1:-1:-1::0;;;18367:24:29::3;;;;;;;;;;;18321:85;18574:11;:22:::0;;;18742:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;18742:47:29::3;18773:15;-1:-1:-1::0;;;;;18742:47:29::3;;::::0;;18902:23:::3;:21;:23::i;:::-;18207:729;17935:1366;16177:3130;;;15922:3385:::0;;;;;;:::o;40528:226::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;40713:23:29::3;:34:::0;;-1:-1:-1;;;;;;40713:34:29::3;-1:-1:-1::0;;;;;40713:34:29;;;::::3;::::0;;;::::3;::::0;;40528:226::o;37923:224::-;38071:20;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;4308:77:29::2;38114:26:::0;::::2;1144:1:75;37923:224:29::0;;;:::o;44866:428::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;45108:20:29::2;45123:4;45108:14;:20::i;:::-;45104:184;;;45144:17;::::0;45254:9:::2;::::0;45144:133:::2;::::0;-1:-1:-1;;;45144:133:29;;-1:-1:-1;;;;;45144:17:29;;::::2;::::0;:29:::2;::::0;:133:::2;::::0;45191:4;;45197:13;;45212:10;;45224:21;;45247:5;;-1:-1:-1;;;45254:9:29;::::2;;;::::0;45144:133:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;45104:184;44866:428:::0;;;;;:::o;3317:197:11:-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;3400:36:::1;3418:17;3400;:36::i;:::-;3487:12;::::0;;3497:1:::1;3487:12:::0;;;::::1;::::0;::::1;::::0;;;3446:61:::1;::::0;3468:17;;3487:12;3446:21:::1;:61::i;:::-;3317:197:::0;:::o;33760:576:29:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;33948:11:29::2;;33940:4;:19:::0;33936:394:::2;;-1:-1:-1::0;;33982:30:29::2;::::0;;::::2;::::0;::::2;::::0;;33991:11:::2;::::0;33982:30;;-1:-1:-1;33982:30:29::2;::::0;::::2;::::0;34007:4:::2;33982:30:::0;;;;;;;;37923:224::o;33936:394::-:2;34043:21;34067:17:::0;;;:11:::2;:17;::::0;;;;;-1:-1:-1;;;;;34067:17:29::2;::::0;34103:18;;;34099:78:::2;;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;;;;;7193:25:29;;;;;;;;;;;;;;;;;;;;34148:14:::2;34141:21:::0;37923:224;-1:-1:-1;;;37923:224:29:o;34099:78::-:2;34242:17;::::0;34191:12:::2;::::0;34208:31:::2;-1:-1:-1::0;;;;;34208:31:29;::::2;:15;:31;:::i;:::-;34281:38;::::0;;::::2;::::0;::::2;::::0;;;;;-1:-1:-1;;;;;34281:38:29;;::::2;;::::0;::::2;::::0;34208:51;-1:-1:-1;34206:54:29::2;34281:38:::0;;;;-1:-1:-1;34281:38:29;-1:-1:-1;37923:224:29;;;:::o;42970:200::-;43105:18;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;43146:17:29::2;::::0;1144:1:75::2;42970:200:29::0;:::o;24400:2949::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;24710:29:29::3;24731:7;24710:20;:29::i;:::-;24705:123;;24779:28;24809:7;24762:55;;-1:-1:-1::0;;;24762:55:29::3;;;;;;;;;:::i;24705:123::-;24852:11;;24841:7;:22;24837:95;;24909:11;::::0;24886:35:::3;::::0;-1:-1:-1;;;24886:35:29;;::::3;::::0;24900:7;;24886:35:::3;;13684:25:78::0;;;13740:2;13725:18;;13718:34;13672:2;13657:18;;13510:248;24837:95:29::3;25008:30;25029:8;25008:20;:30::i;:::-;25003:126;;25078:29;25109:8;25061:57;;-1:-1:-1::0;;;25061:57:29::3;;;;;;;;;:::i;25003:126::-;25206:50;25238:17;;25206:31;:50::i;:::-;25344:17;25364:70;25397:7;25406:8;25416:17;;25364:32;:70::i;:::-;25344:90:::0;-1:-1:-1;25633:24:29::3;25660:56;25344:90:::0;25660:36:::3;:56::i;:::-;25843:23;::::0;:64:::3;::::0;-1:-1:-1;;;25843:64:29;;::::3;::::0;::::3;1194:25:78::0;;;25633:83:29;;-1:-1:-1;25800:28:29::3;::::0;-1:-1:-1;;;;;25843:23:29;;::::3;::::0;:38:::3;::::0;1167:18:78;;25843:64:29::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25800:107;;26006:14;-1:-1:-1::0;;;;;26006:26:29::3;;:242;;;;;;;;26047:11;26059:1;26047:14;;;;;;;:::i;:::-;;;;;26006:242;;;;26063:11;26075:1;26063:14;;;;;;;:::i;:::-;;;;;26006:242:::0;;::::3;::::0;;;;;;;26094:14;;::::3;;26006:242:::0;;::::3;::::0;;;;;;;;;26094:11;26122:1:::3;26110:14;;;;26006:242;;::::0;::::3;;;;;;;;;;;;26128:11;26140:1;26128:14;;;;;;;:::i;:::-;;;;;26006:242;;;;26144:11;26156:1;26144:14;;;;;;;:::i;:::-;;;;;26006:242:::0;;;;::::3;::::0;;;;::::3;::::0;;;;26175:11;26187:1:::3;26175:14;;;;26006:242;;;;26191:11;26203:1;26191:14;;;;;;;:::i;:::-;;;;;26006:242;;::::0;::::3;;;;;;;;26221:16;26006:242;;::::0;::::3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;26006:242:29::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;26006:242:29::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;26002:1341;;;;:::i;:::-;26368:14;26363:85;;26409:24;;-1:-1:-1::0;;;26409:24:29::3;;;;;;;;;;;26363:85;26616:11;:22:::0;;;26784:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;26784:47:29::3;26815:15;-1:-1:-1::0;;;;;26784:47:29::3;;::::0;;26944:23:::3;:21;:23::i;3763:222:11:-:0;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;3880:36:::1;3898:17;3880;:36::i;:::-;3926:52;3948:17;3967:4;3973;3926:21;:52::i;:::-;3763:222:::0;;:::o;41048:232:29:-;41206:12;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;41249:23:29::2;::::0;-1:-1:-1;;;;;41249:23:29::2;41048:232:::0;:::o;3006:131:11:-;3084:7;2324:4;-1:-1:-1;;;;;2333:6:11;2316:23;;2308:92;;;;-1:-1:-1;;;2308:92:11;;18083:2:78;2308:92:11;;;18065:21:78;18122:2;18102:18;;;18095:30;18161:34;18141:18;;;18134:62;18232:26;18212:18;;;18205:54;18276:19;;2308:92:11;17881:420:78;2308:92:11;-1:-1:-1;;;;;;;;;;;;3006:131:11;:::o;32661:242:29:-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;32756:21:29::3;::::0;-1:-1:-1;;;32756:21:29;::::3;;;32751:146;;32793:21;:28:::0;;-1:-1:-1;;;;32793:28:29::3;-1:-1:-1::0;;;32793:28:29::3;::::0;;32661:242::o;32751:146::-:3;32859:27;;-1:-1:-1::0;;;32859:27:29::3;;;;;;;;;;;32751:146;32661:242::o:0;41670:222::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;41851:23:29::3;:34:::0;;-1:-1:-1;;;;;;41851:34:29::3;-1:-1:-1::0;;;;;41851:34:29;;;::::3;::::0;;;::::3;::::0;;41670:222::o;2071:101:6:-;1334:13;:11;:13::i;:::-;2135:30:::1;2162:1;2135:18;:30::i;32106:439:29:-:0;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;-1:-1:-1::0;;;;;32287:40:29;::::3;32283:110;;32350:32;;-1:-1:-1::0;;;32350:32:29::3;;;;;;;;;;;32283:110;32408:21;::::0;-1:-1:-1;;;32408:21:29;::::3;;;32403:72;;32445:19;:17;:19::i;:::-;32485:24;:53:::0;;-1:-1:-1;;;;;;32485:53:29::3;-1:-1:-1::0;;;;;32485:53:29;;;::::3;::::0;;;::::3;::::0;;32106:439::o;39100:631::-;39241:4;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;39273:11:29::2;;39265:4;:19;39261:442;;39300:21;39324:17:::0;;;:11:::2;:17;::::0;;;;;39454::::2;::::0;-1:-1:-1;;;;;39324:17:29;;::::2;::::0;39420:31:::2;39324:17:::0;39420:15:::2;:31;:::i;:::-;:51;39416:110;;;39498:13;;-1:-1:-1::0;;;39498:13:29::2;;;;;;;;;;;39416:110;39616:13;-1:-1:-1::0;;;;;39616:18:29::2;39633:1;39616:18:::0;39612:81:::2;;39661:17;;-1:-1:-1::0;;;39661:17:29::2;;;;;;;;;;;39612:81;39286:417;39261:442;-1:-1:-1::0;39720:4:29::2;39100:631:::0;;;:::o;28480:413::-;28715:12;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;28739:24:29::2;28795:10;28807:7;28816:8;28826:19;;28778:68;;;;;;;;;;;;:::i;43839:192::-:0;43966:26;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;44015:9:29::2;::::0;-1:-1:-1;;;44015:9:29;::::2;;;::::0;43839:192::o;39964:236::-;40126:12;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;40169:23:29::2;::::0;-1:-1:-1;;;;;40169:23:29::2;39964:236:::0;:::o;33020:244::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;33115:21:29::3;::::0;-1:-1:-1;;;33115:21:29;::::3;;;33111:147;;;33152:21;:29:::0;;-1:-1:-1;;;;33152:29:29::3;::::0;;32661:242::o;33111:147::-:3;33219:28;;-1:-1:-1::0;;;33219:28:29::3;;;;;;;;;;;21567:672:::0;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;21934:56:29::3;21972:17;;21934:37;:56::i;:::-;22164:68;22181:12;22195:7;22204:17;;22223:8;22164:16;:68::i;31672:205::-:0;31810:13;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;31846:24:29::2;::::0;-1:-1:-1;;;;;31846:24:29::2;31672:205:::0;:::o;43402:293::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;1334:13:6::2;:11;:13::i;:::-;43564::29::3;43581:1;43564:18:::0;43560:86:::3;;43598:37;::::0;-1:-1:-1;;;43598:37:29;;19108:2:78;43598:37:29::3;::::0;::::3;19090:21:78::0;19147:2;19127:18;;;19120:30;19186:29;19166:18;;;19159:57;19233:18;;43598:37:29::3;18906:351:78::0;43560:86:29::3;43655:17;:33:::0;43402:293::o;30725:126::-;30802:12;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;30833:11:29::2;::::0;30725:126;:::o;42076:210::-;42218:12;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;-1:-1:-1::0;42261:17:29::2;::::0;-1:-1:-1;;;;;42261:17:29::2;42076:210:::0;:::o;11753:1099::-;4871:13:10;;12088:1:29;;4871:13:10;;;;;4870:14;:40;;;;-1:-1:-1;4888:12:10;;:22;;;;:12;;:22;4870:40;4862:99;;;;-1:-1:-1;;;4862:99:10;;19464:2:78;4862:99:10;;;19446:21:78;19503:2;19483:18;;;19476:30;19542:34;19522:18;;;19515:62;-1:-1:-1;;;19593:18:78;;;19586:44;19647:19;;4862:99:10;19262:410:78;4862:99:10;4971:12;:22;;-1:-1:-1;;5003:20:10;4971:22;;;5003:20;4971:22;5003:20;;;12176:16:29::1;:14;:16::i;:::-;12208:48;12245:10;12208:36;:48::i;:::-;12203:119;;12279:32;::::0;-1:-1:-1;;;12279:32:29;;8379:4:78;8367:17;;12279:32:29::1;::::0;::::1;8349:36:78::0;8322:18;;12279:32:29::1;8207:184:78::0;12203:119:29::1;12389:9;:22:::0;;12441:7:::1;12421:17;:27:::0;12458:11:::1;:25:::0;;;12493:23:::1;:50:::0;;-1:-1:-1;;;;;;12493:50:29;;::::1;-1:-1:-1::0;;;;;12493:50:29;;::::1;::::0;;;::::1;::::0;;;12389:22:::1;12553:47:::0;;;::::1;::::0;;::::1;;::::0;;12389:22:::1;12610:38:::0;;;;::::1;::::0;;::::1;;::::0;;;12658:57;;::::1;-1:-1:-1::0;;;;;;12725:42:29;;;-1:-1:-1;;;12389:22:29;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;;12725:42:29;;;-1:-1:-1;;;12725:42:29;::::1;;;;::::0;;12827:18:::1;:16;:18::i;:::-;5060:5:10::0;5044:21;;-1:-1:-1;;5044:21:10;;;5080:20;;8379:4:78;8367:17;;8349:36;;5080:20:10;;8337:2:78;8322:18;5080:20:10;;;;;;;11753:1099:29;;;;;;;;:::o;2321:198:6:-;1334:13;:11;:13::i;:::-;-1:-1:-1;;;;;2409:22:6;::::1;2401:73;;;::::0;-1:-1:-1;;;2401:73:6;;19879:2:78;2401:73:6::1;::::0;::::1;19861:21:78::0;19918:2;19898:18;;;19891:30;19957:34;19937:18;;;19930:62;-1:-1:-1;;;20008:18:78;;;20001:36;20054:19;;2401:73:6::1;19677:402:78::0;2401:73:6::1;2484:28;2503:8;2484:18;:28::i;1563:151:8:-:0;-1:-1:-1;;;;;;;;;;;1642:65:8;-1:-1:-1;;;;;1642:65:8;;1563:151::o;1599:130:6:-;1513:6;;-1:-1:-1;;;;;1513:6:6;929:10:13;1662:23:6;1654:68;;;;-1:-1:-1;;;1654:68:6;;20286:2:78;1654:68:6;;;20268:21:78;;;20305:18;;;20298:30;20364:34;20344:18;;;20337:62;20416:18;;1654:68:6;20084:356:78;35005:658:29;35157:19;35200:9;35195:462;35215:30;;;35195:462;;;35266:18;35287:19;;35307:1;35287:22;;;;;;;:::i;:::-;;;;;;;35266:43;;35327:14;:42;;;;-1:-1:-1;35345:24:29;;;35327:42;35323:108;;;35396:20;;-1:-1:-1;;;35396:20:29;;;;;1194:25:78;;;1167:18;;35396:20:29;1048:177:78;35323:108:29;35449:32;35470:10;35449:20;:32::i;:::-;35444:148;;35525:39;35566:10;35508:69;;-1:-1:-1;;;35508:69:29;;;;;;;;;:::i;35444:148::-;35622:24;;-1:-1:-1;35247:3:29;;;:::i;:::-;;;35195:462;;;;35147:516;35005:658;;:::o;38453:192::-;38577:12;38612:26;4308:77;38612:5;:26;:::i;:::-;38605:33;38453:192;-1:-1:-1;;38453:192:29:o;31001:498::-;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1059:12:75::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:75::1;;;;;;;;;;;1054:81;31091:21:29::2;::::0;-1:-1:-1;;;31091:21:29;::::2;;;:63:::0;::::2;;;-1:-1:-1::0;31116:24:29::2;::::0;-1:-1:-1;;;;;31116:24:29::2;:38:::0;::::2;31091:63;31087:406;;;31188:24;::::0;31290:11:::2;::::0;31235:67:::2;::::0;31171:12:::2;::::0;-1:-1:-1;;;;;31188:24:29::2;::::0;31235:67:::2;::::0;::::2;;1194:25:78::0;;;1182:2;1167:18;;1048:177;31235:67:29::2;;::::0;;-1:-1:-1;;31235:67:29;;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;-1:-1:-1;;;;;31235:67:29::2;-1:-1:-1::0;;;31235:67:29::2;::::0;;31188:128;::::2;::::0;31235:67;31188:128:::2;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31170:146;;;31423:7;31418:64;;31439:43;;-1:-1:-1::0;;;31439:43:29::2;;;;;;;;;;;3112:204:32::0;-1:-1:-1;;;;;1898:6:11;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:11;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:11;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:11;;1963:87;;;;-1:-1:-1;;;1963:87:11;;;;;;;:::i;:::-;1334:13:6::1;:11;:13::i;2938:974:8:-:0;951:66;3384:59;;;3380:526;;;3459:37;3478:17;3459:18;:37::i;:::-;2938:974;;;:::o;3380:526::-;3560:17;-1:-1:-1;;;;;3531:61:8;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3531:63:8;;;;;;;;-1:-1:-1;;3531:63:8;;;;;;;;;;;;:::i;:::-;;;3527:302;;3758:56;;-1:-1:-1;;;3758:56:8;;21342:2:78;3758:56:8;;;21324:21:78;21381:2;21361:18;;;21354:30;21420:34;21400:18;;;21393:62;-1:-1:-1;;;21471:18:78;;;21464:44;21525:19;;3758:56:8;21140:410:78;3527:302:8;-1:-1:-1;;;;;;;;;;;3644:28:8;;3636:82;;;;-1:-1:-1;;;3636:82:8;;21757:2:78;3636:82:8;;;21739:21:78;21796:2;21776:18;;;21769:30;21835:34;21815:18;;;21808:62;-1:-1:-1;;;21886:18:78;;;21879:39;21935:19;;3636:82:8;21555:405:78;3636:82:8;3595:138;3842:53;3860:17;3879:4;3885:9;3842:17;:53::i;36043:710:29:-;36187:9;36182:565;36202:21;;;36182:565;;;36244:30;36277:10;;36288:1;36277:13;;;;;;;:::i;:::-;;;;;;36244:46;;;;;;;;;;:::i;:::-;;;36309:44;36330:8;:22;;;36309:20;:44::i;:::-;36304:210;;36459:22;;;;36380:119;;-1:-1:-1;;;36380:119:29;;;;36418:39;;36380:119;;;:::i;36304:210::-;36532:44;36553:8;:22;;;36532:20;:44::i;:::-;36527:210;;36641:39;36682:8;:22;;;36603:119;;-1:-1:-1;;;36603:119:29;;;;;;;;;:::i;36527:210::-;-1:-1:-1;36225:3:29;;;:::i;:::-;;;36182:565;;2673:187:6;2765:6;;;-1:-1:-1;;;;;2781:17:6;;;-1:-1:-1;;;;;;2781:17:6;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2736:124;2673:187;:::o;37202:390:29:-;37352:9;37347:239;37367:21;;;37347:239;;;37409:37;37449:10;;37460:1;37449:13;;;;;;;:::i;:::-;;;;;;37409:53;;;;;;;;;;:::i;:::-;;;37480:15;:29;;;37513:1;37480:34;37476:100;;37541:20;;-1:-1:-1;;;37541:20:29;;;;;1194:25:78;;;1167:18;;37541:20:29;1048:177:78;37476:100:29;-1:-1:-1;37390:3:29;;;:::i;:::-;;;37347:239;;13186:127;5363:13:10;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:10;;;;;;;:::i;:::-;13256:16:29::1;:14;:16::i;:::-;13282:24;:22;:24::i;434:207:76:-:0;492:19;540:2;569;588:21;;;;-1:-1:-1;588:21:76;;;:46;;;626:8;613:21;;:9;:21;;;;588:46;581:53;434:207;-1:-1:-1;;;;434:207:76:o;794:90:75:-;5363:13:10;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:10;;;;;;;:::i;:::-;858:12:75::1;:19:::0;;-1:-1:-1;;858:19:75::1;873:4;858:19;::::0;;794:90::o;1805:281:8:-;-1:-1:-1;;;;;1476:19:12;;;1878:106:8;;;;-1:-1:-1;;;1878:106:8;;22579:2:78;1878:106:8;;;22561:21:78;22618:2;22598:18;;;22591:30;22657:34;22637:18;;;22630:62;-1:-1:-1;;;22708:18:78;;;22701:43;22761:19;;1878:106:8;22377:409:78;1878:106:8;-1:-1:-1;;;;;;;;;;;1994:85:8;;-1:-1:-1;;;;;;1994:85:8;-1:-1:-1;;;;;1994:85:8;;;;;;;;;;1805:281::o;2478:288::-;2616:29;2627:17;2616:10;:29::i;:::-;2673:1;2659:4;:11;:15;:28;;;;2678:9;2659:28;2655:105;;;2703:46;2725:17;2744:4;2703:21;:46::i;1003:95:6:-;5363:13:10;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:10;;;;;;;:::i;:::-;1065:26:6::1;:24;:26::i;1042:67:11:-:0;5363:13:10;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:10;;;;;;;:::i;2192:152:8:-;2258:37;2277:17;2258:18;:37::i;:::-;2310:27;;-1:-1:-1;;;;;2310:27:8;;;;;;;;2192:152;:::o;7088:455::-;7171:12;-1:-1:-1;;;;;1476:19:12;;;7195:88:8;;;;-1:-1:-1;;;7195:88:8;;22993:2:78;7195:88:8;;;22975:21:78;23032:2;23012:18;;;23005:30;23071:34;23051:18;;;23044:62;-1:-1:-1;;;23122:18:78;;;23115:36;23168:19;;7195:88:8;22791:402:78;7195:88:8;7354:12;7368:23;7395:6;-1:-1:-1;;;;;7395:19:8;7415:4;7395:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7353:67;;;;7437:99;7473:7;7482:10;7437:99;;;;;;;;;;;;;;;;;:35;:99::i;:::-;7430:106;7088:455;-1:-1:-1;;;;;7088:455:8:o;1104:111:6:-;5363:13:10;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:10;;;;;;;:::i;:::-;1176:32:6::1;929:10:13::0;1176:18:6::1;:32::i;7438:295:12:-:0;7584:12;7612:7;7608:119;;;-1:-1:-1;7642:10:12;7635:17;;7608:119;7683:33;7691:10;7703:12;7898:17;;:21;7894:379;;8126:10;8120:17;8182:15;8169:10;8165:2;8161:19;8154:44;14:393:78;100:8;110:6;164:3;157:4;149:6;145:17;141:27;131:55;;182:1;179;172:12;131:55;-1:-1:-1;205:20:78;;248:18;237:30;;234:50;;;280:1;277;270:12;234:50;317:4;309:6;305:17;293:29;;380:3;373:4;365;357:6;353:17;345:6;341:30;337:41;334:50;331:70;;;397:1;394;387:12;331:70;14:393;;;;;:::o;412:631::-;551:6;559;567;575;628:2;616:9;607:7;603:23;599:32;596:52;;;644:1;641;634:12;596:52;680:9;667:23;657:33;;737:2;726:9;722:18;709:32;699:42;;792:2;781:9;777:18;764:32;819:18;811:6;808:30;805:50;;;851:1;848;841:12;805:50;890:93;975:7;966:6;955:9;951:22;890:93;:::i;:::-;412:631;;;;-1:-1:-1;1002:8:78;-1:-1:-1;;;;412:631:78:o;1230:151::-;-1:-1:-1;;;;;1325:31:78;;1315:42;;1305:70;;1371:1;1368;1361:12;1386:295;1473:6;1526:2;1514:9;1505:7;1501:23;1497:32;1494:52;;;1542:1;1539;1532:12;1494:52;1581:9;1568:23;1600:51;1645:5;1600:51;:::i;1686:160::-;1780:6;1813:3;1801:16;;1798:25;-1:-1:-1;1795:45:78;;;1836:1;1833;1826:12;1851:163;1918:20;;1978:10;1967:22;;1957:33;;1947:61;;2004:1;2001;1994:12;2019:367;2082:8;2092:6;2146:3;2139:4;2131:6;2127:17;2123:27;2113:55;;2164:1;2161;2154:12;2113:55;-1:-1:-1;2187:20:78;;2230:18;2219:30;;2216:50;;;2262:1;2259;2252:12;2216:50;2299:4;2291:6;2287:17;2275:29;;2359:3;2352:4;2342:6;2339:1;2335:14;2327:6;2323:27;2319:38;2316:47;2313:67;;;2376:1;2373;2366:12;2391:773;2537:6;2545;2553;2561;2569;2577;2630:3;2618:9;2609:7;2605:23;2601:33;2598:53;;;2647:1;2644;2637:12;2598:53;2670;2715:7;2704:9;2670:53;:::i;:::-;2660:63;;2770:3;2759:9;2755:19;2742:33;2732:43;;2794:38;2827:3;2816:9;2812:19;2794:38;:::i;:::-;2784:48;;2883:3;2872:9;2868:19;2855:33;2911:18;2903:6;2900:30;2897:50;;;2943:1;2940;2933:12;2897:50;2982:70;3044:7;3035:6;3024:9;3020:22;2982:70;:::i;:::-;2391:773;;;;-1:-1:-1;2391:773:78;;;;;3153:3;3138:19;;;3125:33;;2391:773;-1:-1:-1;;;;2391:773:78:o;3470:180::-;3529:6;3582:2;3570:9;3561:7;3557:23;3553:32;3550:52;;;3598:1;3595;3588:12;3550:52;-1:-1:-1;3621:23:78;;3470:180;-1:-1:-1;3470:180:78:o;3847:509::-;3967:6;3975;3983;3991;3999;4052:3;4040:9;4031:7;4027:23;4023:33;4020:53;;;4069:1;4066;4059:12;4020:53;4105:9;4092:23;4082:33;;4162:2;4151:9;4147:18;4134:32;4124:42;;4213:2;4202:9;4198:18;4185:32;4175:42;;4264:2;4253:9;4249:18;4236:32;4226:42;;4287:63;4342:7;4336:3;4325:9;4321:19;4287:63;:::i;:::-;4277:73;;3847:509;;;;;;;;:::o;5241:758::-;5414:6;5422;5430;5438;5446;5499:3;5487:9;5478:7;5474:23;5470:33;5467:53;;;5516:1;5513;5506:12;5467:53;5539;5584:7;5573:9;5539:53;:::i;:::-;5529:63;;5639:3;5628:9;5624:19;5611:33;5601:43;;5695:3;5684:9;5680:19;5667:33;5723:18;5715:6;5712:30;5709:50;;;5755:1;5752;5745:12;5709:50;5794:93;5879:7;5870:6;5859:9;5855:22;5794:93;:::i;:::-;5241:758;;;;-1:-1:-1;5906:8:78;5988:3;5973:19;5960:33;;5241:758;-1:-1:-1;;;;5241:758:78:o;6004:127::-;6065:10;6060:3;6056:20;6053:1;6046:31;6096:4;6093:1;6086:15;6120:4;6117:1;6110:15;6136:249;6246:2;6227:13;;-1:-1:-1;;6223:27:78;6211:40;;6281:18;6266:34;;6302:22;;;6263:62;6260:88;;;6328:18;;:::i;:::-;6364:2;6357:22;-1:-1:-1;;6136:249:78:o;6390:953::-;6467:6;6475;6528:2;6516:9;6507:7;6503:23;6499:32;6496:52;;;6544:1;6541;6534:12;6496:52;6583:9;6570:23;6602:51;6647:5;6602:51;:::i;:::-;6672:5;-1:-1:-1;6696:2:78;6734:18;;;6721:32;6772:18;6802:14;;;6799:34;;;6829:1;6826;6819:12;6799:34;6867:6;6856:9;6852:22;6842:32;;6912:7;6905:4;6901:2;6897:13;6893:27;6883:55;;6934:1;6931;6924:12;6883:55;6970:2;6957:16;6992:2;6988;6985:10;6982:36;;;6998:18;;:::i;:::-;7047:2;7041:9;;-1:-1:-1;7059:65:78;7114:2;7095:13;;-1:-1:-1;;7091:27:78;7087:36;;7041:9;7059:65;:::i;:::-;7148:2;7140:6;7133:18;7188:7;7183:2;7178;7174;7170:11;7166:20;7163:33;7160:53;;;7209:1;7206;7199:12;7160:53;7265:2;7260;7256;7252:11;7247:2;7239:6;7235:15;7222:46;7310:1;7305:2;7300;7292:6;7288:15;7284:24;7277:35;;7331:6;7321:16;;;;;6390:953;;;;;:::o;7556:646::-;7668:6;7676;7684;7692;7700;7753:3;7741:9;7732:7;7728:23;7724:33;7721:53;;;7770:1;7767;7760:12;7721:53;7793:28;7811:9;7793:28;:::i;:::-;7783:38;;7868:2;7857:9;7853:18;7840:32;7830:42;;7919:2;7908:9;7904:18;7891:32;7881:42;;7974:2;7963:9;7959:18;7946:32;8001:18;7993:6;7990:30;7987:50;;;8033:1;8030;8023:12;7987:50;8072:70;8134:7;8125:6;8114:9;8110:22;8072:70;:::i;:::-;7556:646;;;;-1:-1:-1;7556:646:78;;-1:-1:-1;8161:8:78;;8046:96;7556:646;-1:-1:-1;;;7556:646:78:o;8396:118::-;8482:5;8475:13;8468:21;8461:5;8458:32;8448:60;;8504:1;8501;8494:12;8519:1206;8713:6;8721;8729;8737;8745;8753;8761;8814:3;8802:9;8793:7;8789:23;8785:33;8782:53;;;8831:1;8828;8821:12;8782:53;8870:9;8857:23;8920:4;8913:5;8909:16;8902:5;8899:27;8889:55;;8940:1;8937;8930:12;8889:55;8963:5;-1:-1:-1;9015:2:78;9000:18;;8987:32;;-1:-1:-1;9071:2:78;9056:18;;9043:32;9084:53;9043:32;9084:53;:::i;:::-;9156:7;-1:-1:-1;9215:2:78;9200:18;;9187:32;9228:53;9187:32;9228:53;:::i;:::-;9300:7;-1:-1:-1;9359:3:78;9344:19;;9331:33;9373:53;9331:33;9373:53;:::i;:::-;9445:7;-1:-1:-1;9504:3:78;9489:19;;9476:33;9518:30;9476:33;9518:30;:::i;:::-;9567:7;-1:-1:-1;9626:3:78;9611:19;;9598:33;9640:53;9598:33;9640:53;:::i;:::-;9712:7;9702:17;;;8519:1206;;;;;;;;;;:::o;9730:408::-;9932:2;9914:21;;;9971:2;9951:18;;;9944:30;10010:34;10005:2;9990:18;;9983:62;-1:-1:-1;;;10076:2:78;10061:18;;10054:42;10128:3;10113:19;;9730:408::o;10143:::-;10345:2;10327:21;;;10384:2;10364:18;;;10357:30;10423:34;10418:2;10403:18;;10396:62;-1:-1:-1;;;10489:2:78;10474:18;;10467:42;10541:3;10526:19;;10143:408::o;10556:127::-;10617:10;10612:3;10608:20;10605:1;10598:31;10648:4;10645:1;10638:15;10672:4;10669:1;10662:15;10688:583;10780:6;10833:2;10821:9;10812:7;10808:23;10804:32;10801:52;;;10849:1;10846;10839:12;10801:52;10882:2;10876:9;10924:2;10916:6;10912:15;10993:6;10981:10;10978:22;10957:18;10945:10;10942:34;10939:62;10936:88;;;11004:18;;:::i;:::-;11040:2;11033:22;11079:28;11097:9;11079:28;:::i;:::-;11071:6;11064:44;11169:2;11158:9;11154:18;11141:32;11136:2;11128:6;11124:15;11117:57;11235:2;11224:9;11220:18;11207:32;11202:2;11194:6;11190:15;11183:57;11259:6;11249:16;;;10688:583;;;;:::o;11627:250::-;11712:1;11722:113;11736:6;11733:1;11730:13;11722:113;;;11812:11;;;11806:18;11793:11;;;11786:39;11758:2;11751:10;11722:113;;;-1:-1:-1;;11869:1:78;11851:16;;11844:27;11627:250::o;11882:492::-;12057:3;12095:6;12089:13;12111:66;12170:6;12165:3;12158:4;12150:6;12146:17;12111:66;:::i;:::-;12240:13;;12199:16;;;;12262:70;12240:13;12199:16;12309:4;12297:17;;12262:70;:::i;:::-;12348:20;;11882:492;-1:-1:-1;;;;11882:492:78:o;12379:127::-;12440:10;12435:3;12431:20;12428:1;12421:31;12471:4;12468:1;12461:15;12495:4;12492:1;12485:15;12511:135;12550:3;12571:17;;;12568:43;;12591:18;;:::i;:::-;-1:-1:-1;12638:1:78;12627:13;;12511:135::o;12651:424::-;12866:6;12861:3;12854:19;12903:6;12898:2;12893:3;12889:12;12882:28;12836:3;12939:6;12933:13;12955:73;13021:6;13016:2;13011:3;13007:12;13002:2;12994:6;12990:15;12955:73;:::i;:::-;13048:16;;;;13066:2;13044:25;;12651:424;-1:-1:-1;;;;12651:424:78:o;13080:425::-;13266:2;13251:18;;13299:1;13288:13;;13278:144;;13344:10;13339:3;13335:20;13332:1;13325:31;13379:4;13376:1;13369:15;13407:4;13404:1;13397:15;13278:144;13431:25;;;13487:2;13472:18;13465:34;13080:425;:::o;13763:294::-;13856:6;13909:2;13897:9;13888:7;13884:23;13880:32;13877:52;;;13925:1;13922;13915:12;13877:52;13957:9;13951:16;13976:51;14021:5;13976:51;:::i;14062:326::-;14155:5;14178:1;14188:194;14202:4;14199:1;14196:11;14188:194;;;14261:13;;14249:26;;14298:4;14322:12;;;;14357:15;;;;14222:1;14215:9;14188:194;;14393:1228;14841:3;14826:19;;14854:43;14830:9;14879:6;14854:43;:::i;:::-;14916:2;14953;14942:9;14938:18;14998:6;15022:1;15032:187;15046:4;15043:1;15040:11;15032:187;;;15093:44;15133:3;15124:6;15118:13;15093:44;:::i;:::-;15157:12;;;;15204:4;15192:17;;;;;15066:1;15059:9;15032:187;;;15036:3;;;;15228:53;15276:3;15265:9;15261:19;15253:6;15228:53;:::i;:::-;15318:3;15307:9;15303:19;15370:6;15396:1;15406:209;15422:1;15417:3;15414:10;15406:209;;;15484:15;;15470:30;;15523:4;15549:14;;;;15588:17;;;;15443:1;15434:11;15406:209;;;15410:3;;;14393:1228;;;;;;;:::o;15626:245::-;15693:6;15746:2;15734:9;15725:7;15721:23;15717:32;15714:52;;;15762:1;15759;15752:12;15714:52;15794:9;15788:16;15813:28;15835:5;15813:28;:::i;15876:179::-;15911:3;15953:1;15935:16;15932:23;15929:120;;;15999:1;15996;15993;15978:23;-1:-1:-1;16036:1:78;16030:8;16025:3;16021:18;15876:179;:::o;16060:671::-;16099:3;16141:4;16123:16;16120:26;16117:39;;;16060:671;:::o;16117:39::-;16183:2;16177:9;-1:-1:-1;;16248:16:78;16244:25;;16241:1;16177:9;16220:50;16299:4;16293:11;16323:16;16358:18;16429:2;16422:4;16414:6;16410:17;16407:25;16402:2;16394:6;16391:14;16388:45;16385:58;;;16436:5;;;;;16060:671;:::o;16385:58::-;16473:6;16467:4;16463:17;16452:28;;16509:3;16503:10;16536:2;16528:6;16525:14;16522:27;;;16542:5;;;;;;16060:671;:::o;16522:27::-;16626:2;16607:16;16601:4;16597:27;16593:36;16586:4;16577:6;16572:3;16568:16;16564:27;16561:69;16558:82;;;16633:5;;;;;;16060:671;:::o;16558:82::-;16649:57;16700:4;16691:6;16683;16679:19;16675:30;16669:4;16649:57;:::i;:::-;-1:-1:-1;16722:3:78;;16060:671;-1:-1:-1;;;;;16060:671:78:o;16736:396::-;16885:2;16874:9;16867:21;16848:4;16917:6;16911:13;16960:6;16955:2;16944:9;16940:18;16933:34;16976:79;17048:6;17043:2;17032:9;17028:18;17023:2;17015:6;17011:15;16976:79;:::i;:::-;17116:2;17095:15;-1:-1:-1;;17091:29:78;17076:45;;;;17123:2;17072:54;;16736:396;-1:-1:-1;;16736:396:78:o;17137:606::-;17415:4;17457:3;17446:9;17442:19;17434:27;;17488:6;17477:9;17470:25;17531:6;17526:2;17515:9;17511:18;17504:34;17574:6;17569:2;17558:9;17554:18;17547:34;17617:6;17612:2;17601:9;17597:18;17590:34;17675:6;17667;17661:3;17650:9;17646:19;17633:49;17731:4;17723:6;17719:17;17713:3;17702:9;17698:19;17691:46;17137:606;;;;;;;;;:::o;17748:128::-;17815:9;;;17836:11;;;17833:37;;;17850:18;;:::i;18306:595::-;18615:3;18593:16;;;-1:-1:-1;;;;;;18589:43:78;18577:56;;18658:1;18649:11;;18642:27;;;18694:2;18685:12;;18678:28;;;-1:-1:-1;;;;;;18718:31:78;;18715:51;;;18762:1;18759;18752:12;18715:51;18796:6;18793:1;18789:14;18847:6;18839;18834:2;18829:3;18825:12;18812:42;18874:16;;;;18892:2;18870:25;;18306:595;-1:-1:-1;;;;;;18306:595:78:o;20445:209::-;20477:1;20503;20493:132;;20547:10;20542:3;20538:20;20535:1;20528:31;20582:4;20579:1;20572:15;20610:4;20607:1;20600:15;20493:132;-1:-1:-1;20639:9:78;;20445:209::o;20659:287::-;20788:3;20826:6;20820:13;20842:66;20901:6;20896:3;20889:4;20881:6;20877:17;20842:66;:::i;:::-;20924:16;;;;;20659:287;-1:-1:-1;;20659:287:78:o;20951:184::-;21021:6;21074:2;21062:9;21053:7;21049:23;21045:32;21042:52;;;21090:1;21087;21080:12;21042:52;-1:-1:-1;21113:16:78;;20951:184;-1:-1:-1;20951:184:78:o;21965:407::-;22167:2;22149:21;;;22206:2;22186:18;;;22179:30;22245:34;22240:2;22225:18;;22218:62;-1:-1:-1;;;22311:2:78;22296:18;;22289:41;22362:3;22347:19;;21965:407::o", - "linkReferences": {}, - "immutableReferences": { - "21546": [ - { - "start": 1505, - "length": 32 - }, - { - "start": 1578, - "length": 32 - }, - { - "start": 1973, - "length": 32 - }, - { - "start": 2037, - "length": 32 - }, - { - "start": 2211, - "length": 32 - }, - { - "start": 2275, - "length": 32 - }, - { - "start": 3242, - "length": 32 - }, - { - "start": 3306, - "length": 32 - }, - { - "start": 3481, - "length": 32 - }, - { - "start": 3545, - "length": 32 - }, - { - "start": 3718, - "length": 32 - }, - { - "start": 3782, - "length": 32 - }, - { - "start": 4050, - "length": 32 - }, - { - "start": 4114, - "length": 32 - }, - { - "start": 4279, - "length": 32 - }, - { - "start": 4343, - "length": 32 - }, - { - "start": 4680, - "length": 32 - }, - { - "start": 4744, - "length": 32 - }, - { - "start": 4883, - "length": 32 - }, - { - "start": 4947, - "length": 32 - }, - { - "start": 5816, - "length": 32 - }, - { - "start": 5880, - "length": 32 - }, - { - "start": 6003, - "length": 32 - }, - { - "start": 6067, - "length": 32 - }, - { - "start": 6217, - "length": 32 - }, - { - "start": 6393, - "length": 32 - }, - { - "start": 6457, - "length": 32 - }, - { - "start": 6663, - "length": 32 - }, - { - "start": 6727, - "length": 32 - }, - { - "start": 6918, - "length": 32 - }, - { - "start": 6982, - "length": 32 - }, - { - "start": 7223, - "length": 32 - }, - { - "start": 7287, - "length": 32 - }, - { - "start": 7552, - "length": 32 - }, - { - "start": 7616, - "length": 32 - }, - { - "start": 7776, - "length": 32 - }, - { - "start": 7840, - "length": 32 - }, - { - "start": 7991, - "length": 32 - }, - { - "start": 8055, - "length": 32 - }, - { - "start": 8202, - "length": 32 - }, - { - "start": 8266, - "length": 32 - }, - { - "start": 8465, - "length": 32 - }, - { - "start": 8529, - "length": 32 - }, - { - "start": 8693, - "length": 32 - }, - { - "start": 8757, - "length": 32 - }, - { - "start": 8905, - "length": 32 - }, - { - "start": 8969, - "length": 32 - }, - { - "start": 9195, - "length": 32 - }, - { - "start": 9259, - "length": 32 - }, - { - "start": 9399, - "length": 32 - }, - { - "start": 9463, - "length": 32 - }, - { - "start": 10466, - "length": 32 - }, - { - "start": 10530, - "length": 32 - }, - { - "start": 10895, - "length": 32 - }, - { - "start": 10959, - "length": 32 - } - ] - } - }, - "methodIdentifiers": { - "NO_SUCH_ROOT()": "561f204b", - "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": "8c76a909", - "calculateIdentityUpdateInputHash(uint256,uint256,(uint32,uint256,uint256)[])": "09edcb9c", - "checkValidRoot(uint256)": "8b6c56c6", - "disableStateBridge()": "a26b810e", - "enableStateBridge()": "61ea6a8d", - "getIdentityUpdateVerifierLookupTableAddress()": "4ffbdde5", - "getRegisterIdentitiesVerifierLookupTableAddress()": "8fc22e9f", - "getRootHistoryExpiry()": "43f974cb", - "getSemaphoreVerifierAddress()": "f2038f95", - "getTreeDepth()": "8e5cdd50", - "initialize(uint8,uint256,address,address,address,bool,address)": "f2ebe631", - "isInputInReducedForm(uint256)": "34923152", - "latestRoot()": "d7b0fef1", - "owner()": "8da5cb5b", - "proxiableUUID()": "52d1902d", - "queryRoot(uint256)": "3f7c178d", - "registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)": "2217b211", - "removeIdentities(uint256[8],uint256,(uint32,uint256,uint256)[],uint256)": "b1390908", - "renounceOwnership()": "715018a6", - "setIdentityUpdateVerifierLookupTable(address)": "6b056600", - "setRegisterIdentitiesVerifierLookupTable(address)": "2f059fca", - "setRootHistoryExpiry(uint256)": "c70aa727", - "setSemaphoreVerifier(address)": "0e3a12f3", - "setStateBridgeProxyAddress(address)": "8939472e", - "stateBridgeProxyAddress()": "b6621a3d", - "transferOwnership(address)": "f2fde38b", - "updateIdentities(uint256[8],uint256,(uint32,uint256,uint256)[],uint256)": "4bc511e6", - "upgradeTo(address)": "3659cfe6", - "upgradeToAndCall(address,bytes)": "4f1ef286", - "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": "354ca120" - }, - "rawMetadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ExpiredRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ImplementationNotInitialized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"InvalidCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStateBridgeProxyAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"latestRoot\",\"type\":\"uint256\"}],\"name\":\"NotLatestRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProofValidationFailure\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeAlreadyDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeAlreadyEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeProxySendRootMultichainFailure\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WorldIDIdentityManagerImplV1.UnreducedElementType\",\"name\":\"elementType\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"element\",\"type\":\"uint256\"}],\"name\":\"UnreducedElement\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"depth\",\"type\":\"uint8\"}],\"name\":\"UnsupportedTreeDepth\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NO_SUCH_ROOT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"supersededTimestamp\",\"type\":\"uint128\"},{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.RootInfo\",\"name\":\"rootInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"startIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"identityCommitments\",\"type\":\"uint256[]\"}],\"name\":\"calculateIdentityRegistrationInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"leafIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"oldCommitment\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newCommitment\",\"type\":\"uint256\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.IdentityUpdate[]\",\"name\":\"identities\",\"type\":\"tuple[]\"}],\"name\":\"calculateIdentityUpdateInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"checkValidRoot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableStateBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"enableStateBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getIdentityUpdateVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegisterIdentitiesVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRootHistoryExpiry\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"expiryTime\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSemaphoreVerifierAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTreeDepth\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"initializedTreeDepth\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_treeDepth\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"initialRoot\",\"type\":\"uint256\"},{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchInsertionVerifiers\",\"type\":\"address\"},{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchUpdateVerifiers\",\"type\":\"address\"},{\"internalType\":\"contract ISemaphoreVerifier\",\"name\":\"_semaphoreVerifier\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_enableStateBridge\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"initialStateBridgeProxyAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"input\",\"type\":\"uint256\"}],\"name\":\"isInputInReducedForm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isInReducedForm\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"queryRoot\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"supersededTimestamp\",\"type\":\"uint128\"},{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.RootInfo\",\"name\":\"rootInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"insertionProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256[]\",\"name\":\"identityCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"registerIdentities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"removalProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"leafIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"oldCommitment\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newCommitment\",\"type\":\"uint256\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.IdentityUpdate[]\",\"name\":\"removedIdentities\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"removeIdentities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setIdentityUpdateVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setRegisterIdentitiesVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newExpiryTime\",\"type\":\"uint256\"}],\"name\":\"setRootHistoryExpiry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ISemaphoreVerifier\",\"name\":\"newVerifier\",\"type\":\"address\"}],\"name\":\"setSemaphoreVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newStateBridgeProxyAddress\",\"type\":\"address\"}],\"name\":\"setStateBridgeProxyAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stateBridgeProxyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"updateProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"leafIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"oldCommitment\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newCommitment\",\"type\":\"uint256\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.IdentityUpdate[]\",\"name\":\"updatedIdentities\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"updateIdentities\",\"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\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signalHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nullifierHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalNullifierHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256[8]\",\"name\":\"proof\",\"type\":\"uint256[8]\"}],\"name\":\"verifyProof\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Worldcoin\",\"details\":\"The manager is based on the principle of verifying externally-created Zero Knowledge Proofs to perform the insertions.This is the implementation delegated to by a proxy.\",\"errors\":{\"InvalidCommitment(uint256)\":[{\"params\":{\"index\":\"The index in the array of identity commitments where the invalid commitment was found.\"}}],\"NotLatestRoot(uint256,uint256)\":[{\"params\":{\"latestRoot\":\"The actual latest root at the time of the transaction.\",\"providedRoot\":\"The root that was provided as the `preRoot` for a transaction.\"}}],\"Unauthorized(address)\":[{\"params\":{\"user\":\"The user that attempted the action that they were not authorised for.\"}}],\"UnreducedElement(uint8,uint256)\":[{\"details\":\"`r` in this case is given by `SNARK_SCALAR_FIELD`.\",\"params\":{\"element\":\"The value of that element.\",\"elementType\":\"The kind of element that was encountered unreduced.\"}}],\"UnsupportedTreeDepth(uint8)\":[{\"params\":{\"depth\":\"Passed tree depth.\"}}]},\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is upgraded.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"NO_SUCH_ROOT()\":{\"details\":\"Can be checked against when querying for root data.\"},\"calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])\":{\"details\":\"Implements the computation described below.\",\"params\":{\"identityCommitments\":\"The identities that were added to the tree to produce `postRoot`.\",\"postRoot\":\"The root value of the tree after these insertsions were made.\",\"preRoot\":\"The root value of the tree before these insertions were made.\",\"startIndex\":\"The index in the tree from which inserting started.\"},\"returns\":{\"hash\":\"The input hash calculated as described below. We keccak hash all input to save verification gas. Inputs are arranged as follows: StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] 32\\t || 256 || 256 || 256 || 256 || ... || 256 bits\"}},\"calculateIdentityUpdateInputHash(uint256,uint256,(uint32,uint256,uint256)[])\":{\"details\":\"Implements the computation described below.\",\"params\":{\"identities\":\"The identity structures providing the identity data.\",\"postRoot\":\"The root value of the tree after the udpates were made.\",\"preRoot\":\"The root value of the tree before the updates were made.\"},\"returns\":{\"hash\":\"The input hash calculated as described below. We keccak hash all input to save verification gas. The inputs are arranged as follows: preRoot || postRoot || id[0].leafIndex || id[0].oldCommitment || id[0].newCommitment || ... || id[n].leafIndex || id[n].oldCommitment || id[n].newCommitment 256 || 256 || 32 || 256 || 256 || ... || 32 || 256 || 256 where: - `id[n] == identities[n]` - `n == batchSize - 1`\"}},\"checkValidRoot(uint256)\":{\"custom:reverts\":\"ExpiredRoot If the root is not valid due to being expired.NonExistentRoot If the root does not exist.\",\"details\":\"Reverts with `ExpiredRoot` if the root has expired, and `NonExistentRoot` if the root is not in the root history.\",\"params\":{\"root\":\"The root of a given identity group.\"}},\"disableStateBridge()\":{\"details\":\"Only the owner of the contract can call this function.\"},\"enableStateBridge()\":{\"details\":\"Only the owner of the contract can call this function.\"},\"getIdentityUpdateVerifierLookupTableAddress()\":{\"details\":\"The update verifier is also used for member removals.\",\"returns\":{\"addr\":\"The addresss of the contract being used as the verifier lookup table.\"}},\"getRegisterIdentitiesVerifierLookupTableAddress()\":{\"returns\":{\"addr\":\"The addresss of the contract being used as the verifier lookup table.\"}},\"getRootHistoryExpiry()\":{\"returns\":{\"expiryTime\":\"The amount of time it takes for a root to expire.\"}},\"getSemaphoreVerifierAddress()\":{\"returns\":{\"addr\":\"The addresss of the contract being used as the verifier.\"}},\"getTreeDepth()\":{\"returns\":{\"initializedTreeDepth\":\"Tree depth.\"}},\"initialize(uint8,uint256,address,address,address,bool,address)\":{\"custom:reverts\":\"string If called more than once at the same initalisation number.UnsupportedTreeDepth If passed tree depth is not amoung defined values.\",\"details\":\"Must be called exactly once.This is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.\",\"params\":{\"_batchInsertionVerifiers\":\"The verifier lookup table for batch insertions.\",\"_batchUpdateVerifiers\":\"The verifier lookup table for batch updates.\",\"_enableStateBridge\":\"Whether or not the state bridge should be enabled when initialising the identity manager.\",\"_semaphoreVerifier\":\"The verifier to use for semaphore protocol proofs.\",\"_treeDepth\":\"The depth of the MerkeTree\",\"initialRoot\":\"The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree.\",\"initialStateBridgeProxyAddress\":\"The initial state bridge proxy address to use.\"}},\"isInputInReducedForm(uint256)\":{\"details\":\"`r` in this case is given by `SNARK_SCALAR_FIELD`.\",\"params\":{\"input\":\"The input to check for being in reduced form.\"},\"returns\":{\"isInReducedForm\":\"Returns `true` if `input` is in reduced form, `false` otherwise.\"}},\"latestRoot()\":{\"returns\":{\"root\":\"The value of the latest tree root.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"queryRoot(uint256)\":{\"details\":\"Should be used sparingly as the query can be quite expensive.\",\"params\":{\"root\":\"The root for which you are querying information.\"},\"returns\":{\"rootInfo\":\"The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. Note that if the queried root is the current, the timestamp will be invalid as the root has not been superseded.\"}},\"registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to add identities.InvalidCommitment If one or more of the provided commitments is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `insertionProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identityCommitments` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.\",\"params\":{\"identityCommitments\":\"The identities that were inserted into the tree starting at `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be elements of the field `Kr`.\",\"postRoot\":\"The root obtained after inserting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`.\",\"startIndex\":\"The position in the tree at which the insertions were made.\"}},\"removeIdentities(uint256[8],uint256,(uint32,uint256,uint256)[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to remove identities.InvalidCommitment If one or more of the provided identities is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `removedIdentities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.\",\"params\":{\"postRoot\":\"The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`.\",\"removedIdentities\":\"The identities that were removed from the tree. As they each hold their own leaf index, these need not be contiguous. All of the commitments must be elements of the field `Kr`.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setIdentityUpdateVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.The update verifier is also used for member removals.\",\"params\":{\"newTable\":\"The new lookup table instance to be used for verifying identity updates.\"}},\"setRegisterIdentitiesVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newTable\":\"The new verifier lookup table to be used for verifying identity registrations.\"}},\"setRootHistoryExpiry(uint256)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newExpiryTime\":\"The new time to use to expire roots.\"}},\"setSemaphoreVerifier(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newVerifier\":\"The new verifier instance to be used for verifying semaphore proofs.\"}},\"setStateBridgeProxyAddress(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newStateBridgeProxyAddress\":\"The address of the new stateBridgeProxy\"}},\"stateBridgeProxyAddress()\":{\"returns\":{\"proxy\":\"The address of the currently used stateBridgeProxy\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"updateIdentities(uint256[8],uint256,(uint32,uint256,uint256)[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to update identities.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.NoSuchVerifier If the batch sizes doesn't match a known verifier.\",\"params\":{\"postRoot\":\"The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`.\",\"updatedIdentities\":\"The identities that were updated in the tree. As they each hold their own leaf index, these need not be contiguous. All of the commitments must be elements of the field `Kr`.\"}},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"verifyProof(uint256,uint256,uint256,uint256,uint256[8])\":{\"custom:reverts\":\"string If the zero-knowledge proof cannot be verified for the public inputs.\",\"details\":\"Note that a double-signaling check is not included here, and should be carried by the caller.\",\"params\":{\"externalNullifierHash\":\"A keccak256 hash of the external nullifier\",\"nullifierHash\":\"The nullifier hash\",\"proof\":\"The zero-knowledge proof\",\"root\":\"The of the Merkle tree\",\"signalHash\":\"A keccak256 hash of the Semaphore signal\"}}},\"stateVariables\":{\"EMPTY_LEAF\":{\"details\":\"Prevents the empty leaf from being inserted into the root history.\"},\"SNARK_SCALAR_FIELD\":{\"details\":\"Used internally to ensure that the proof input is scaled to within the field `Fr`.\"},\"rootHistoryExpiry\":{\"details\":\"This prevents proofs getting invalidated in the mempool by another tx modifying the group.\"}},\"title\":\"WorldID Identity Manager Implementation Version 1\",\"version\":1},\"userdoc\":{\"errors\":{\"ExpiredRoot()\":[{\"notice\":\"Thrown when attempting to validate a root that has expired.\"}],\"ImplementationNotInitialized()\":[{\"notice\":\"Thrown when attempting to call a function while the implementation has not been initialized.\"}],\"InvalidCommitment(uint256)\":[{\"notice\":\"Thrown when one or more of the identity commitments to be inserted is invalid.\"}],\"InvalidStateBridgeProxyAddress()\":[{\"notice\":\"Thrown when attempting to set the state bridge proxy address to the zero address.\"}],\"NonExistentRoot()\":[{\"notice\":\"Thrown when attempting to validate a root that has yet to be added to the root history.\"}],\"NotLatestRoot(uint256,uint256)\":[{\"notice\":\"Thrown when the provided root is not the very latest root.\"}],\"ProofValidationFailure()\":[{\"notice\":\"Thrown when the provided proof cannot be verified for the accompanying inputs.\"}],\"StateBridgeAlreadyDisabled()\":[{\"notice\":\"Thrown when attempting to disable the bridge when it is already disabled.\"}],\"StateBridgeAlreadyEnabled()\":[{\"notice\":\"Thrown when attempting to enable the bridge when it is already enabled.\"}],\"StateBridgeProxySendRootMultichainFailure()\":[{\"notice\":\"Thrown when attempting to send a transaction to the state bridge proxy that fails.\"}],\"Unauthorized(address)\":[{\"notice\":\"Thrown when trying to execute a privileged action without being the contract manager.\"}],\"UnreducedElement(uint8,uint256)\":[{\"notice\":\"Thrown when encountering an element that should be reduced as a member of `Fr` but is not.\"}],\"UnsupportedTreeDepth(uint8)\":[{\"notice\":\"Thrown when Semaphore tree depth is not supported.\"}]},\"kind\":\"user\",\"methods\":{\"NO_SUCH_ROOT()\":{\"notice\":\"A constant representing a root that doesn't exist.\"},\"calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])\":{\"notice\":\"Calculates the input hash for the identity registration verifier.\"},\"calculateIdentityUpdateInputHash(uint256,uint256,(uint32,uint256,uint256)[])\":{\"notice\":\"Calculates the input hash for the identity update verifier.\"},\"checkValidRoot(uint256)\":{\"notice\":\"Checks if a given root value is valid and has been added to the root history.\"},\"constructor\":{\"notice\":\"Constructs the contract.\"},\"disableStateBridge()\":{\"notice\":\"Disables the state bridge.\"},\"enableStateBridge()\":{\"notice\":\"Enables the state bridge.\"},\"getIdentityUpdateVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for identity updates.\"},\"getRegisterIdentitiesVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for identity registrations.\"},\"getRootHistoryExpiry()\":{\"notice\":\"Gets the current amount of time used to expire roots in the history.\"},\"getSemaphoreVerifierAddress()\":{\"notice\":\"Gets the address of the verifier used for verification of semaphore proofs.\"},\"getTreeDepth()\":{\"notice\":\"Gets the Semaphore tree depth the contract was initialized with.\"},\"initialize(uint8,uint256,address,address,address,bool,address)\":{\"notice\":\"Initializes the contract.\"},\"isInputInReducedForm(uint256)\":{\"notice\":\"Checks if the provided `input` is in reduced form within the field `Fr`.\"},\"latestRoot()\":{\"notice\":\"Allows a caller to query the latest root.\"},\"queryRoot(uint256)\":{\"notice\":\"Allows a caller to query the root history for information about a given root.\"},\"setIdentityUpdateVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers to be used for verification of identity updates.\"},\"setRegisterIdentitiesVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers used for identity registrations.\"},\"setRootHistoryExpiry(uint256)\":{\"notice\":\"Sets the time to wait before expiring a root from the root history.\"},\"setSemaphoreVerifier(address)\":{\"notice\":\"Sets the address for the semaphore verifier to be used for verification of semaphore proofs.\"},\"setStateBridgeProxyAddress(address)\":{\"notice\":\"Allows a caller to upgrade the stateBridgeProxy.\"},\"stateBridgeProxyAddress()\":{\"notice\":\"Allows a caller to query the address of the current stateBridgeProxy.\"},\"verifyProof(uint256,uint256,uint256,uint256,uint256[8])\":{\"notice\":\"A verifier for the semaphore protocol.\"}},\"notice\":\"An implementation of a batch-based identity manager for the WorldID protocol.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/WorldIDIdentityManagerImplV1.sol\":\"WorldIDIdentityManagerImplV1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@zk-kit/=lib/zk-kit/packages/\",\":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":ds-test/=lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/\",\":semaphore/=lib/semaphore/packages/contracts/contracts/\",\":solmate/=lib/solmate/src/\",\":zk-kit/=lib/zk-kit/\"]},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol\":{\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053\",\"dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"keccak256\":\"0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2\",\"dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol\":{\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1\",\"dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8a313cf42389440e2706837c91370323b85971c06afd6d056d21e2bc86459618\",\"dweb:/ipfs/QmT8XUrUvQ9aZaPKrqgRU2JVGWnaxBcUYJA7Q7K5KcLBSZ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0x7967d130887c4b40666cd88f8744691d4527039a1b2a38aa0de41481ef646778\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40e60cbf0e2efede4d9c169e66336a64615af7b719a896ef1f37ae8cd4614ec1\",\"dweb:/ipfs/QmYNiwY22ifhfa8yK6mLCEKfj39caYUHLqe2VBtzDnvdsV\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06\",\"dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol\":{\"keccak256\":\"0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3\",\"dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"lib/semaphore/packages/contracts/contracts/base/Pairing.sol\":{\"keccak256\":\"0x44390032d1247a0e3931eb39f1220f170db653c6b3b4321b2e2b0034f5e07334\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://725cc4bdf047d17bf9d47c9a0205d90897c0da334de8e556c1a3049b1beb9aed\",\"dweb:/ipfs/QmSo7SXpqyrqHFhYi7F8SGjcVxCdVr6FNdgiw7Qfre1NGt\"]},\"lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol\":{\"keccak256\":\"0x5b5b1118ed7936014d3e410419d6048cc9c0ae69fd700442593f2c2cc782e1af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://601cf2c7e3c98735ff38eaff225af090ec847d63ec599ecc2340323145430668\",\"dweb:/ipfs/QmUoZYgge8GmQokXrYiRXn24s4HgBZetiNWQssiSoTFrdi\"]},\"src/WorldIDIdentityManagerImplV1.sol\":{\"keccak256\":\"0x3374bdbde178e10a7b7568c00d6c26002b5cc7f3e238d0e5af7222de8483f69c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f026da813703b09df2eb5444eb639c84703986be3ee34624f51654eacc2be8cb\",\"dweb:/ipfs/QmaiY8mAA1DEonCN1YkT6hAPgifW65Km2AFxzxEiQt6YgB\"]},\"src/abstract/WorldIDImpl.sol\":{\"keccak256\":\"0x76f5d1d4041620d795b93fc2406caa692d5d7e702ae8b6f620add6463e832a88\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fcc368c8c8ee433f6278148df849f462b0d149e1c8e7e6d410257ebdb7236bc5\",\"dweb:/ipfs/QmNM6GJ3iUaRcQn6CJKyN4pZVyzx6mBGGZhhmq8ui1aEbM\"]},\"src/data/VerifierLookupTable.sol\":{\"keccak256\":\"0x38e32904ee20021cd30e07c0ddccdc3fdc6ba6ffa84380c8b5a14135d75cae99\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bf45bfc037af32f83ba3cd101f5643b136f845b224527554fca78a9c3d61d97f\",\"dweb:/ipfs/Qmc8n2o9EEsdmZwUho4KWweYsEXyjRqjgcY4CFpn8iTx6x\"]},\"src/interfaces/ITreeVerifier.sol\":{\"keccak256\":\"0x3f980c7fa04a40d3e128a27ac7eb2fba6020a2a81baec4172e3ce809a1189388\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5e7cca84723edc4bfffec31b48dcd93bf78b677b80939d97209c57ad8a248f15\",\"dweb:/ipfs/QmSxNKodWF1Fh94b3UmKQS63KE7arLqgdrXyGxVq7gXJHR\"]},\"src/interfaces/IWorldID.sol\":{\"keccak256\":\"0x525a2d0b2fa218a279f19344846a70a9021f9911ab22de63b2f371551d7ea4fe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2b869a850ea0568e52348c2e57db1bc06c4a3c1855626beba10925a252f732d\",\"dweb:/ipfs/QmXaS8eX18tzHNHoEEEZBdATsmC1oi45CEu5L8ewhGyRZz\"]},\"src/utils/CheckInitialized.sol\":{\"keccak256\":\"0x7584ed171e4ed8d98b52ad166b1c357e2fd98cde5eb6de2e7f60eb4d12be1742\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f5f8065c502cf9f1ee508c875ebaa71fc09456d6501cc0c2724c28fc221138b\",\"dweb:/ipfs/QmNwqpcNUyDZKuPBAtBTdPfGEKHMJY83aHBETgReDFJq9m\"]},\"src/utils/SemaphoreTreeDepthValidator.sol\":{\"keccak256\":\"0xa1fc61c574575ffc686ca1ffc18d0b2236588f783d8fab0dfadfe7cd12188978\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0393f27b5c73eebfa053e3bfa666784df261e4d68ffa86240064702d378c22e6\",\"dweb:/ipfs/QmYs3cKa45V78irViZWfSnLHpDaRqPLNrLHuQGJqSnZmnY\"]}},\"version\":1}", - "metadata": { - "compiler": { - "version": "0.8.19+commit.7dd6d404" - }, - "language": "Solidity", - "output": { - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "type": "error", - "name": "ExpiredRoot" - }, - { - "inputs": [], - "type": "error", - "name": "ImplementationNotInitialized" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "type": "error", - "name": "InvalidCommitment" - }, - { - "inputs": [], - "type": "error", - "name": "InvalidStateBridgeProxyAddress" - }, - { - "inputs": [], - "type": "error", - "name": "NonExistentRoot" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "providedRoot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "latestRoot", - "type": "uint256" - } - ], - "type": "error", - "name": "NotLatestRoot" - }, - { - "inputs": [], - "type": "error", - "name": "ProofValidationFailure" - }, - { - "inputs": [], - "type": "error", - "name": "StateBridgeAlreadyDisabled" - }, - { - "inputs": [], - "type": "error", - "name": "StateBridgeAlreadyEnabled" - }, - { - "inputs": [], - "type": "error", - "name": "StateBridgeProxySendRootMultichainFailure" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "type": "error", - "name": "Unauthorized" - }, - { - "inputs": [ - { - "internalType": "enum WorldIDIdentityManagerImplV1.UnreducedElementType", - "name": "elementType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "element", - "type": "uint256" - } - ], - "type": "error", - "name": "UnreducedElement" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "depth", - "type": "uint8" - } - ], - "type": "error", - "name": "UnsupportedTreeDepth" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "previousAdmin", - "type": "address", - "indexed": false - }, - { - "internalType": "address", - "name": "newAdmin", - "type": "address", - "indexed": false - } - ], - "type": "event", - "name": "AdminChanged", - "anonymous": false - }, - { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address", - "indexed": true - } - ], - "type": "event", - "name": "BeaconUpgraded", - "anonymous": false - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "version", - "type": "uint8", - "indexed": false - } - ], - "type": "event", - "name": "Initialized", - "anonymous": false - }, - { - "inputs": [ - { - "internalType": "address", - "name": "previousOwner", - "type": "address", - "indexed": true - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address", - "indexed": true - } - ], - "type": "event", - "name": "OwnershipTransferred", - "anonymous": false - }, - { - "inputs": [ - { - "internalType": "address", - "name": "implementation", - "type": "address", - "indexed": true - } - ], - "type": "event", - "name": "Upgraded", - "anonymous": false - }, - { - "inputs": [], - "stateMutability": "pure", - "type": "function", - "name": "NO_SUCH_ROOT", - "outputs": [ - { - "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", - "name": "rootInfo", - "type": "tuple", - "components": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "supersededTimestamp", - "type": "uint128" - }, - { - "internalType": "bool", - "name": "isValid", - "type": "bool" - } - ] - } - ] - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "startIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "identityCommitments", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function", - "name": "calculateIdentityRegistrationInputHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ] - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - }, - { - "internalType": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]", - "name": "identities", - "type": "tuple[]", - "components": [ - { - "internalType": "uint32", - "name": "leafIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "oldCommitment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newCommitment", - "type": "uint256" - } - ] - } - ], - "stateMutability": "view", - "type": "function", - "name": "calculateIdentityUpdateInputHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ] - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function", - "name": "checkValidRoot", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ] - }, - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "name": "disableStateBridge" - }, - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "name": "enableStateBridge" - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "getIdentityUpdateVerifierLookupTableAddress", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "getRegisterIdentitiesVerifierLookupTableAddress", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "getRootHistoryExpiry", - "outputs": [ - { - "internalType": "uint256", - "name": "expiryTime", - "type": "uint256" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "getSemaphoreVerifierAddress", - "outputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "getTreeDepth", - "outputs": [ - { - "internalType": "uint8", - "name": "initializedTreeDepth", - "type": "uint8" - } - ] - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "_treeDepth", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "initialRoot", - "type": "uint256" - }, - { - "internalType": "contract VerifierLookupTable", - "name": "_batchInsertionVerifiers", - "type": "address" - }, - { - "internalType": "contract VerifierLookupTable", - "name": "_batchUpdateVerifiers", - "type": "address" - }, - { - "internalType": "contract ISemaphoreVerifier", - "name": "_semaphoreVerifier", - "type": "address" - }, - { - "internalType": "bool", - "name": "_enableStateBridge", - "type": "bool" - }, - { - "internalType": "address", - "name": "initialStateBridgeProxyAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "initialize" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function", - "name": "isInputInReducedForm", - "outputs": [ - { - "internalType": "bool", - "name": "isInReducedForm", - "type": "bool" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "latestRoot", - "outputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ] - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ] - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function", - "name": "queryRoot", - "outputs": [ - { - "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", - "name": "rootInfo", - "type": "tuple", - "components": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "supersededTimestamp", - "type": "uint128" - }, - { - "internalType": "bool", - "name": "isValid", - "type": "bool" - } - ] - } - ] - }, - { - "inputs": [ - { - "internalType": "uint256[8]", - "name": "insertionProof", - "type": "uint256[8]" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "startIndex", - "type": "uint32" - }, - { - "internalType": "uint256[]", - "name": "identityCommitments", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "registerIdentities" - }, - { - "inputs": [ - { - "internalType": "uint256[8]", - "name": "removalProof", - "type": "uint256[8]" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]", - "name": "removedIdentities", - "type": "tuple[]", - "components": [ - { - "internalType": "uint32", - "name": "leafIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "oldCommitment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newCommitment", - "type": "uint256" - } - ] - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "removeIdentities" - }, - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "name": "renounceOwnership" - }, - { - "inputs": [ - { - "internalType": "contract VerifierLookupTable", - "name": "newTable", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "setIdentityUpdateVerifierLookupTable" - }, - { - "inputs": [ - { - "internalType": "contract VerifierLookupTable", - "name": "newTable", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "setRegisterIdentitiesVerifierLookupTable" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newExpiryTime", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "setRootHistoryExpiry" - }, - { - "inputs": [ - { - "internalType": "contract ISemaphoreVerifier", - "name": "newVerifier", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "setSemaphoreVerifier" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newStateBridgeProxyAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "setStateBridgeProxyAddress" - }, - { - "inputs": [], - "stateMutability": "view", - "type": "function", - "name": "stateBridgeProxyAddress", - "outputs": [ - { - "internalType": "address", - "name": "proxy", - "type": "address" - } - ] - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "transferOwnership" - }, - { - "inputs": [ - { - "internalType": "uint256[8]", - "name": "updateProof", - "type": "uint256[8]" - }, - { - "internalType": "uint256", - "name": "preRoot", - "type": "uint256" - }, - { - "internalType": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]", - "name": "updatedIdentities", - "type": "tuple[]", - "components": [ - { - "internalType": "uint32", - "name": "leafIndex", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "oldCommitment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newCommitment", - "type": "uint256" - } - ] - }, - { - "internalType": "uint256", - "name": "postRoot", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "updateIdentities" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "upgradeTo" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function", - "name": "upgradeToAndCall" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "signalHash", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nullifierHash", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalNullifierHash", - "type": "uint256" - }, - { - "internalType": "uint256[8]", - "name": "proof", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function", - "name": "verifyProof" - } - ], - "devdoc": { - "kind": "dev", - "methods": { - "NO_SUCH_ROOT()": { - "details": "Can be checked against when querying for root data." - }, - "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": { - "details": "Implements the computation described below.", - "params": { - "identityCommitments": "The identities that were added to the tree to produce `postRoot`.", - "postRoot": "The root value of the tree after these insertsions were made.", - "preRoot": "The root value of the tree before these insertions were made.", - "startIndex": "The index in the tree from which inserting started." - }, - "returns": { - "hash": "The input hash calculated as described below. We keccak hash all input to save verification gas. Inputs are arranged as follows: StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] 32\t || 256 || 256 || 256 || 256 || ... || 256 bits" - } - }, - "calculateIdentityUpdateInputHash(uint256,uint256,(uint32,uint256,uint256)[])": { - "details": "Implements the computation described below.", - "params": { - "identities": "The identity structures providing the identity data.", - "postRoot": "The root value of the tree after the udpates were made.", - "preRoot": "The root value of the tree before the updates were made." - }, - "returns": { - "hash": "The input hash calculated as described below. We keccak hash all input to save verification gas. The inputs are arranged as follows: preRoot || postRoot || id[0].leafIndex || id[0].oldCommitment || id[0].newCommitment || ... || id[n].leafIndex || id[n].oldCommitment || id[n].newCommitment 256 || 256 || 32 || 256 || 256 || ... || 32 || 256 || 256 where: - `id[n] == identities[n]` - `n == batchSize - 1`" - } - }, - "checkValidRoot(uint256)": { - "custom:reverts": "ExpiredRoot If the root is not valid due to being expired.NonExistentRoot If the root does not exist.", - "details": "Reverts with `ExpiredRoot` if the root has expired, and `NonExistentRoot` if the root is not in the root history.", - "params": { - "root": "The root of a given identity group." - } - }, - "disableStateBridge()": { - "details": "Only the owner of the contract can call this function." - }, - "enableStateBridge()": { - "details": "Only the owner of the contract can call this function." - }, - "getIdentityUpdateVerifierLookupTableAddress()": { - "details": "The update verifier is also used for member removals.", - "returns": { - "addr": "The addresss of the contract being used as the verifier lookup table." - } - }, - "getRegisterIdentitiesVerifierLookupTableAddress()": { - "returns": { - "addr": "The addresss of the contract being used as the verifier lookup table." - } - }, - "getRootHistoryExpiry()": { - "returns": { - "expiryTime": "The amount of time it takes for a root to expire." - } - }, - "getSemaphoreVerifierAddress()": { - "returns": { - "addr": "The addresss of the contract being used as the verifier." - } - }, - "getTreeDepth()": { - "returns": { - "initializedTreeDepth": "Tree depth." - } - }, - "initialize(uint8,uint256,address,address,address,bool,address)": { - "custom:reverts": "string If called more than once at the same initalisation number.UnsupportedTreeDepth If passed tree depth is not amoung defined values.", - "details": "Must be called exactly once.This is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.", - "params": { - "_batchInsertionVerifiers": "The verifier lookup table for batch insertions.", - "_batchUpdateVerifiers": "The verifier lookup table for batch updates.", - "_enableStateBridge": "Whether or not the state bridge should be enabled when initialising the identity manager.", - "_semaphoreVerifier": "The verifier to use for semaphore protocol proofs.", - "_treeDepth": "The depth of the MerkeTree", - "initialRoot": "The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree.", - "initialStateBridgeProxyAddress": "The initial state bridge proxy address to use." - } - }, - "isInputInReducedForm(uint256)": { - "details": "`r` in this case is given by `SNARK_SCALAR_FIELD`.", - "params": { - "input": "The input to check for being in reduced form." - }, - "returns": { - "isInReducedForm": "Returns `true` if `input` is in reduced form, `false` otherwise." - } - }, - "latestRoot()": { - "returns": { - "root": "The value of the latest tree root." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "proxiableUUID()": { - "details": "Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." - }, - "queryRoot(uint256)": { - "details": "Should be used sparingly as the query can be quite expensive.", - "params": { - "root": "The root for which you are querying information." - }, - "returns": { - "rootInfo": "The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. Note that if the queried root is the current, the timestamp will be invalid as the root has not been superseded." - } - }, - "registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)": { - "custom:reverts": "Unauthorized If the message sender is not authorised to add identities.InvalidCommitment If one or more of the provided commitments is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `insertionProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identityCommitments` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.", - "params": { - "identityCommitments": "The identities that were inserted into the tree starting at `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be elements of the field `Kr`.", - "postRoot": "The root obtained after inserting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`.", - "startIndex": "The position in the tree at which the insertions were made." - } - }, - "removeIdentities(uint256[8],uint256,(uint32,uint256,uint256)[],uint256)": { - "custom:reverts": "Unauthorized If the message sender is not authorised to remove identities.InvalidCommitment If one or more of the provided identities is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `removedIdentities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.", - "params": { - "postRoot": "The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`.", - "removedIdentities": "The identities that were removed from the tree. As they each hold their own leaf index, these need not be contiguous. All of the commitments must be elements of the field `Kr`." - } - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "setIdentityUpdateVerifierLookupTable(address)": { - "details": "Only the owner of the contract can call this function.The update verifier is also used for member removals.", - "params": { - "newTable": "The new lookup table instance to be used for verifying identity updates." - } - }, - "setRegisterIdentitiesVerifierLookupTable(address)": { - "details": "Only the owner of the contract can call this function.", - "params": { - "newTable": "The new verifier lookup table to be used for verifying identity registrations." - } - }, - "setRootHistoryExpiry(uint256)": { - "details": "Only the owner of the contract can call this function.", - "params": { - "newExpiryTime": "The new time to use to expire roots." - } - }, - "setSemaphoreVerifier(address)": { - "details": "Only the owner of the contract can call this function.", - "params": { - "newVerifier": "The new verifier instance to be used for verifying semaphore proofs." - } - }, - "setStateBridgeProxyAddress(address)": { - "details": "Only the owner of the contract can call this function.", - "params": { - "newStateBridgeProxyAddress": "The address of the new stateBridgeProxy" - } - }, - "stateBridgeProxyAddress()": { - "returns": { - "proxy": "The address of the currently used stateBridgeProxy" - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - }, - "updateIdentities(uint256[8],uint256,(uint32,uint256,uint256)[],uint256)": { - "custom:reverts": "Unauthorized If the message sender is not authorised to update identities.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.NoSuchVerifier If the batch sizes doesn't match a known verifier.", - "params": { - "postRoot": "The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`.", - "updatedIdentities": "The identities that were updated in the tree. As they each hold their own leaf index, these need not be contiguous. All of the commitments must be elements of the field `Kr`." - } - }, - "upgradeTo(address)": { - "details": "Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." - }, - "upgradeToAndCall(address,bytes)": { - "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." - }, - "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": { - "custom:reverts": "string If the zero-knowledge proof cannot be verified for the public inputs.", - "details": "Note that a double-signaling check is not included here, and should be carried by the caller.", - "params": { - "externalNullifierHash": "A keccak256 hash of the external nullifier", - "nullifierHash": "The nullifier hash", - "proof": "The zero-knowledge proof", - "root": "The of the Merkle tree", - "signalHash": "A keccak256 hash of the Semaphore signal" - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "NO_SUCH_ROOT()": { - "notice": "A constant representing a root that doesn't exist." - }, - "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": { - "notice": "Calculates the input hash for the identity registration verifier." - }, - "calculateIdentityUpdateInputHash(uint256,uint256,(uint32,uint256,uint256)[])": { - "notice": "Calculates the input hash for the identity update verifier." - }, - "checkValidRoot(uint256)": { - "notice": "Checks if a given root value is valid and has been added to the root history." - }, - "constructor": { - "notice": "Constructs the contract." - }, - "disableStateBridge()": { - "notice": "Disables the state bridge." - }, - "enableStateBridge()": { - "notice": "Enables the state bridge." - }, - "getIdentityUpdateVerifierLookupTableAddress()": { - "notice": "Gets the address for the lookup table of merkle tree verifiers used for identity updates." - }, - "getRegisterIdentitiesVerifierLookupTableAddress()": { - "notice": "Gets the address for the lookup table of merkle tree verifiers used for identity registrations." - }, - "getRootHistoryExpiry()": { - "notice": "Gets the current amount of time used to expire roots in the history." - }, - "getSemaphoreVerifierAddress()": { - "notice": "Gets the address of the verifier used for verification of semaphore proofs." - }, - "getTreeDepth()": { - "notice": "Gets the Semaphore tree depth the contract was initialized with." - }, - "initialize(uint8,uint256,address,address,address,bool,address)": { - "notice": "Initializes the contract." - }, - "isInputInReducedForm(uint256)": { - "notice": "Checks if the provided `input` is in reduced form within the field `Fr`." - }, - "latestRoot()": { - "notice": "Allows a caller to query the latest root." - }, - "queryRoot(uint256)": { - "notice": "Allows a caller to query the root history for information about a given root." - }, - "setIdentityUpdateVerifierLookupTable(address)": { - "notice": "Sets the address for the lookup table of merkle tree verifiers to be used for verification of identity updates." - }, - "setRegisterIdentitiesVerifierLookupTable(address)": { - "notice": "Sets the address for the lookup table of merkle tree verifiers used for identity registrations." - }, - "setRootHistoryExpiry(uint256)": { - "notice": "Sets the time to wait before expiring a root from the root history." - }, - "setSemaphoreVerifier(address)": { - "notice": "Sets the address for the semaphore verifier to be used for verification of semaphore proofs." - }, - "setStateBridgeProxyAddress(address)": { - "notice": "Allows a caller to upgrade the stateBridgeProxy." - }, - "stateBridgeProxyAddress()": { - "notice": "Allows a caller to query the address of the current stateBridgeProxy." - }, - "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": { - "notice": "A verifier for the semaphore protocol." - } - }, - "version": 1 - } - }, - "settings": { - "remappings": [ - ":@zk-kit/=lib/zk-kit/packages/", - ":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", - ":ds-test/=lib/ds-test/src/", - ":forge-std/=lib/forge-std/src/", - ":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", - ":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", - ":semaphore/=lib/semaphore/packages/contracts/contracts/", - ":solmate/=lib/solmate/src/", - ":zk-kit/=lib/zk-kit/" - ], - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "compilationTarget": { - "src/WorldIDIdentityManagerImplV1.sol": "WorldIDIdentityManagerImplV1" - }, - "libraries": {} - }, - "sources": { - "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol": { - "keccak256": "0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888", - "urls": [ - "bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a", - "dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol": { - "keccak256": "0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f", - "urls": [ - "bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053", - "dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { - "keccak256": "0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823", - "urls": [ - "bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2", - "dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol": { - "keccak256": "0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908", - "urls": [ - "bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1", - "dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": { - "keccak256": "0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271", - "urls": [ - "bzz-raw://8a313cf42389440e2706837c91370323b85971c06afd6d056d21e2bc86459618", - "dweb:/ipfs/QmT8XUrUvQ9aZaPKrqgRU2JVGWnaxBcUYJA7Q7K5KcLBSZ" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol": { - "keccak256": "0x7967d130887c4b40666cd88f8744691d4527039a1b2a38aa0de41481ef646778", - "urls": [ - "bzz-raw://40e60cbf0e2efede4d9c169e66336a64615af7b719a896ef1f37ae8cd4614ec1", - "dweb:/ipfs/QmYNiwY22ifhfa8yK6mLCEKfj39caYUHLqe2VBtzDnvdsV" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": { - "keccak256": "0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183", - "urls": [ - "bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06", - "dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": { - "keccak256": "0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149", - "urls": [ - "bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c", - "dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol": { - "keccak256": "0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a", - "urls": [ - "bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3", - "dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts/contracts/access/Ownable.sol": { - "keccak256": "0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673", - "urls": [ - "bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2", - "dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y" - ], - "license": "MIT" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "keccak256": "0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7", - "urls": [ - "bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92", - "dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3" - ], - "license": "MIT" - }, - "lib/semaphore/packages/contracts/contracts/base/Pairing.sol": { - "keccak256": "0x44390032d1247a0e3931eb39f1220f170db653c6b3b4321b2e2b0034f5e07334", - "urls": [ - "bzz-raw://725cc4bdf047d17bf9d47c9a0205d90897c0da334de8e556c1a3049b1beb9aed", - "dweb:/ipfs/QmSo7SXpqyrqHFhYi7F8SGjcVxCdVr6FNdgiw7Qfre1NGt" - ], - "license": "MIT" - }, - "lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol": { - "keccak256": "0x5b5b1118ed7936014d3e410419d6048cc9c0ae69fd700442593f2c2cc782e1af", - "urls": [ - "bzz-raw://601cf2c7e3c98735ff38eaff225af090ec847d63ec599ecc2340323145430668", - "dweb:/ipfs/QmUoZYgge8GmQokXrYiRXn24s4HgBZetiNWQssiSoTFrdi" - ], - "license": "MIT" - }, - "src/WorldIDIdentityManagerImplV1.sol": { - "keccak256": "0x3374bdbde178e10a7b7568c00d6c26002b5cc7f3e238d0e5af7222de8483f69c", - "urls": [ - "bzz-raw://f026da813703b09df2eb5444eb639c84703986be3ee34624f51654eacc2be8cb", - "dweb:/ipfs/QmaiY8mAA1DEonCN1YkT6hAPgifW65Km2AFxzxEiQt6YgB" - ], - "license": "MIT" - }, - "src/abstract/WorldIDImpl.sol": { - "keccak256": "0x76f5d1d4041620d795b93fc2406caa692d5d7e702ae8b6f620add6463e832a88", - "urls": [ - "bzz-raw://fcc368c8c8ee433f6278148df849f462b0d149e1c8e7e6d410257ebdb7236bc5", - "dweb:/ipfs/QmNM6GJ3iUaRcQn6CJKyN4pZVyzx6mBGGZhhmq8ui1aEbM" - ], - "license": "MIT" - }, - "src/data/VerifierLookupTable.sol": { - "keccak256": "0x38e32904ee20021cd30e07c0ddccdc3fdc6ba6ffa84380c8b5a14135d75cae99", - "urls": [ - "bzz-raw://bf45bfc037af32f83ba3cd101f5643b136f845b224527554fca78a9c3d61d97f", - "dweb:/ipfs/Qmc8n2o9EEsdmZwUho4KWweYsEXyjRqjgcY4CFpn8iTx6x" - ], - "license": "MIT" - }, - "src/interfaces/ITreeVerifier.sol": { - "keccak256": "0x3f980c7fa04a40d3e128a27ac7eb2fba6020a2a81baec4172e3ce809a1189388", - "urls": [ - "bzz-raw://5e7cca84723edc4bfffec31b48dcd93bf78b677b80939d97209c57ad8a248f15", - "dweb:/ipfs/QmSxNKodWF1Fh94b3UmKQS63KE7arLqgdrXyGxVq7gXJHR" - ], - "license": "MIT" - }, - "src/interfaces/IWorldID.sol": { - "keccak256": "0x525a2d0b2fa218a279f19344846a70a9021f9911ab22de63b2f371551d7ea4fe", - "urls": [ - "bzz-raw://e2b869a850ea0568e52348c2e57db1bc06c4a3c1855626beba10925a252f732d", - "dweb:/ipfs/QmXaS8eX18tzHNHoEEEZBdATsmC1oi45CEu5L8ewhGyRZz" - ], - "license": "MIT" - }, - "src/utils/CheckInitialized.sol": { - "keccak256": "0x7584ed171e4ed8d98b52ad166b1c357e2fd98cde5eb6de2e7f60eb4d12be1742", - "urls": [ - "bzz-raw://8f5f8065c502cf9f1ee508c875ebaa71fc09456d6501cc0c2724c28fc221138b", - "dweb:/ipfs/QmNwqpcNUyDZKuPBAtBTdPfGEKHMJY83aHBETgReDFJq9m" - ], - "license": "MIT" - }, - "src/utils/SemaphoreTreeDepthValidator.sol": { - "keccak256": "0xa1fc61c574575ffc686ca1ffc18d0b2236588f783d8fab0dfadfe7cd12188978", - "urls": [ - "bzz-raw://0393f27b5c73eebfa053e3bfa666784df261e4d68ffa86240064702d378c22e6", - "dweb:/ipfs/QmYs3cKa45V78irViZWfSnLHpDaRqPLNrLHuQGJqSnZmnY" - ], - "license": "MIT" - } - }, - "version": 1 - }, - "ast": { - "absolutePath": "src/WorldIDIdentityManagerImplV1.sol", - "id": 26046, - "exportedSymbols": { - "ISemaphoreVerifier": [ - 24290 - ], - "ITreeVerifier": [ - 26728 - ], - "IWorldID": [ - 26748 - ], - "SemaphoreTreeDepthValidator": [ - 41077 - ], - "VerifierLookupTable": [ - 26691 - ], - "WorldIDIdentityManagerImplV1": [ - 26045 - ], - "WorldIDImpl": [ - 26507 - ] - }, - "nodeType": "SourceUnit", - "src": "32:45265:29", - "nodes": [ - { - "id": 24701, - "nodeType": "PragmaDirective", - "src": "32:24:29", - "nodes": [], - "literals": [ - "solidity", - "^", - "0.8", - ".19" - ] - }, - { - "id": 24703, - "nodeType": "ImportDirective", - "src": "58:55:29", - "nodes": [], - "absolutePath": "src/abstract/WorldIDImpl.sol", - "file": "./abstract/WorldIDImpl.sol", - "nameLocation": "-1:-1:-1", - "scope": 26046, - "sourceUnit": 26508, - "symbolAliases": [ - { - "foreign": { - "id": 24702, - "name": "WorldIDImpl", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26507, - "src": "66:11:29", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 24705, - "nodeType": "ImportDirective", - "src": "115:51:29", - "nodes": [], - "absolutePath": "src/interfaces/IWorldID.sol", - "file": "./interfaces/IWorldID.sol", - "nameLocation": "-1:-1:-1", - "scope": 26046, - "sourceUnit": 26749, - "symbolAliases": [ - { - "foreign": { - "id": 24704, - "name": "IWorldID", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26748, - "src": "123:8:29", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 24707, - "nodeType": "ImportDirective", - "src": "167:61:29", - "nodes": [], - "absolutePath": "src/interfaces/ITreeVerifier.sol", - "file": "./interfaces/ITreeVerifier.sol", - "nameLocation": "-1:-1:-1", - "scope": 26046, - "sourceUnit": 26729, - "symbolAliases": [ - { - "foreign": { - "id": 24706, - "name": "ITreeVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26728, - "src": "175:13:29", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 24709, - "nodeType": "ImportDirective", - "src": "229:79:29", - "nodes": [], - "absolutePath": "lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol", - "file": "semaphore/interfaces/ISemaphoreVerifier.sol", - "nameLocation": "-1:-1:-1", - "scope": 26046, - "sourceUnit": 24291, - "symbolAliases": [ - { - "foreign": { - "id": 24708, - "name": "ISemaphoreVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24290, - "src": "237:18:29", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 24711, - "nodeType": "ImportDirective", - "src": "310:84:29", - "nodes": [], - "absolutePath": "src/utils/SemaphoreTreeDepthValidator.sol", - "file": "./utils/SemaphoreTreeDepthValidator.sol", - "nameLocation": "-1:-1:-1", - "scope": 26046, - "sourceUnit": 41078, - "symbolAliases": [ - { - "foreign": { - "id": 24710, - "name": "SemaphoreTreeDepthValidator", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 41077, - "src": "318:27:29", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 24713, - "nodeType": "ImportDirective", - "src": "395:67:29", - "nodes": [], - "absolutePath": "src/data/VerifierLookupTable.sol", - "file": "./data/VerifierLookupTable.sol", - "nameLocation": "-1:-1:-1", - "scope": 26046, - "sourceUnit": 26692, - "symbolAliases": [ - { - "foreign": { - "id": 24712, - "name": "VerifierLookupTable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26691, - "src": "403:19:29", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 26045, - "nodeType": "ContractDefinition", - "src": "835:44461:29", - "nodes": [ - { - "id": 24721, - "nodeType": "VariableDeclaration", - "src": "3380:28:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24719, - "nodeType": "StructuredDocumentation", - "src": "3319:56:29", - "text": "@notice The latest root of the identity merkle tree." - }, - "mutability": "mutable", - "name": "_latestRoot", - "nameLocation": "3397:11:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24720, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "3380:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "id": 24726, - "nodeType": "VariableDeclaration", - "src": "3562:48:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24722, - "nodeType": "StructuredDocumentation", - "src": "3415:142:29", - "text": "@notice A mapping from the value of the merkle tree root to the timestamp at which the root\n was superseded by a newer one." - }, - "mutability": "mutable", - "name": "rootHistory", - "nameLocation": "3599:11:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", - "typeString": "mapping(uint256 => uint128)" - }, - "typeName": { - "id": 24725, - "keyName": "", - "keyNameLocation": "-1:-1:-1", - "keyType": { - "id": 24723, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "3570:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Mapping", - "src": "3562:27:29", - "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", - "typeString": "mapping(uint256 => uint128)" - }, - "valueName": "", - "valueNameLocation": "-1:-1:-1", - "valueType": { - "id": 24724, - "name": "uint128", - "nodeType": "ElementaryTypeName", - "src": "3581:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - } - }, - "visibility": "internal" - }, - { - "id": 24729, - "nodeType": "VariableDeclaration", - "src": "3810:34:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24727, - "nodeType": "StructuredDocumentation", - "src": "3617:188:29", - "text": "@notice The amount of time an outdated root is considered as valid.\n @dev This prevents proofs getting invalidated in the mempool by another tx modifying the\n group." - }, - "mutability": "mutable", - "name": "rootHistoryExpiry", - "nameLocation": "3827:17:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24728, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "3810:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "id": 24736, - "nodeType": "VariableDeclaration", - "src": "4000:49:29", - "nodes": [], - "constant": true, - "documentation": { - "id": 24730, - "nodeType": "StructuredDocumentation", - "src": "3851:144:29", - "text": "@notice Represents the initial leaf in an empty merkle tree.\n @dev Prevents the empty leaf from being inserted into the root history." - }, - "mutability": "constant", - "name": "EMPTY_LEAF", - "nameLocation": "4026:10:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24731, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "4000:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": { - "arguments": [ - { - "hexValue": "30", - "id": 24734, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "4047:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - } - ], - "id": 24733, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "4039:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_uint256_$", - "typeString": "type(uint256)" - }, - "typeName": { - "id": 24732, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "4039:7:29", - "typeDescriptions": {} - } - }, - "id": 24735, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4039:10:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "id": 24740, - "nodeType": "VariableDeclaration", - "src": "4253:132:29", - "nodes": [], - "constant": true, - "documentation": { - "id": 24737, - "nodeType": "StructuredDocumentation", - "src": "4056:192:29", - "text": "@notice The `r` for the finite field `Fr` under which arithmetic is done on the proof input.\n @dev Used internally to ensure that the proof input is scaled to within the field `Fr`." - }, - "mutability": "constant", - "name": "SNARK_SCALAR_FIELD", - "nameLocation": "4279:18:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24738, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "4253:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": { - "hexValue": "3231383838323432383731383339323735323232323436343035373435323537323735303838353438333634343030343136303334333433363938323034313836353735383038343935363137", - "id": 24739, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "4308:77:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_21888242871839275222246405745257275088548364400416034343698204186575808495617_by_1", - "typeString": "int_const 2188...(69 digits omitted)...5617" - }, - "value": "21888242871839275222246405745257275088548364400416034343698204186575808495617" - }, - "visibility": "internal" - }, - { - "id": 24744, - "nodeType": "VariableDeclaration", - "src": "4472:52:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24741, - "nodeType": "StructuredDocumentation", - "src": "4392:75:29", - "text": "@notice The table of verifiers for verifying batch identity insertions." - }, - "mutability": "mutable", - "name": "batchInsertionVerifiers", - "nameLocation": "4501:23:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - }, - "typeName": { - "id": 24743, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24742, - "name": "VerifierLookupTable", - "nameLocations": [ - "4472:19:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26691, - "src": "4472:19:29" - }, - "referencedDeclaration": 26691, - "src": "4472:19:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "visibility": "internal" - }, - { - "id": 24748, - "nodeType": "VariableDeclaration", - "src": "4611:52:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24745, - "nodeType": "StructuredDocumentation", - "src": "4531:75:29", - "text": "@notice The table of verifiers for verifying batch identity insertions." - }, - "mutability": "mutable", - "name": "identityUpdateVerifiers", - "nameLocation": "4640:23:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - }, - "typeName": { - "id": 24747, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24746, - "name": "VerifierLookupTable", - "nameLocations": [ - "4611:19:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26691, - "src": "4611:19:29" - }, - "referencedDeclaration": 26691, - "src": "4611:19:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "visibility": "internal" - }, - { - "id": 24752, - "nodeType": "VariableDeclaration", - "src": "4760:45:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24749, - "nodeType": "StructuredDocumentation", - "src": "4670:85:29", - "text": "@notice The verifier instance needed for operating within the semaphore protocol." - }, - "mutability": "mutable", - "name": "semaphoreVerifier", - "nameLocation": "4788:17:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - }, - "typeName": { - "id": 24751, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24750, - "name": "ISemaphoreVerifier", - "nameLocations": [ - "4760:18:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24290, - "src": "4760:18:29" - }, - "referencedDeclaration": 24290, - "src": "4760:18:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "visibility": "internal" - }, - { - "id": 24755, - "nodeType": "VariableDeclaration", - "src": "4901:41:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24753, - "nodeType": "StructuredDocumentation", - "src": "4812:84:29", - "text": "@notice The interface of the bridge contract from L1 to supported target chains." - }, - "mutability": "mutable", - "name": "_stateBridgeProxyAddress", - "nameLocation": "4918:24:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 24754, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "4901:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - }, - { - "id": 24758, - "nodeType": "VariableDeclaration", - "src": "5014:35:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24756, - "nodeType": "StructuredDocumentation", - "src": "4949:60:29", - "text": "@notice Boolean flag to enable/disable the state bridge." - }, - "mutability": "mutable", - "name": "_isStateBridgeEnabled", - "nameLocation": "5028:21:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 24757, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "5014:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - }, - { - "id": 24761, - "nodeType": "VariableDeclaration", - "src": "5112:24:29", - "nodes": [], - "constant": false, - "documentation": { - "id": 24759, - "nodeType": "StructuredDocumentation", - "src": "5056:51:29", - "text": "@notice The depth of the Semaphore merkle tree." - }, - "mutability": "mutable", - "name": "treeDepth", - "nameLocation": "5127:9:29", - "scope": 26045, - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - }, - "typeName": { - "id": 24760, - "name": "uint8", - "nodeType": "ElementaryTypeName", - "src": "5112:5:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "visibility": "internal" - }, - { - "id": 24768, - "nodeType": "StructDefinition", - "src": "5833:104:29", - "nodes": [], - "canonicalName": "WorldIDIdentityManagerImplV1.RootInfo", - "members": [ - { - "constant": false, - "id": 24763, - "mutability": "mutable", - "name": "root", - "nameLocation": "5867:4:29", - "nodeType": "VariableDeclaration", - "scope": 24768, - "src": "5859:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24762, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "5859:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24765, - "mutability": "mutable", - "name": "supersededTimestamp", - "nameLocation": "5889:19:29", - "nodeType": "VariableDeclaration", - "scope": 24768, - "src": "5881:27:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - }, - "typeName": { - "id": 24764, - "name": "uint128", - "nodeType": "ElementaryTypeName", - "src": "5881:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24767, - "mutability": "mutable", - "name": "isValid", - "nameLocation": "5923:7:29", - "nodeType": "VariableDeclaration", - "scope": 24768, - "src": "5918:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 24766, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "5918:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "name": "RootInfo", - "nameLocation": "5840:8:29", - "scope": 26045, - "visibility": "public" - }, - { - "id": 24775, - "nodeType": "StructDefinition", - "src": "6405:117:29", - "nodes": [], - "canonicalName": "WorldIDIdentityManagerImplV1.IdentityUpdate", - "members": [ - { - "constant": false, - "id": 24770, - "mutability": "mutable", - "name": "leafIndex", - "nameLocation": "6444:9:29", - "nodeType": "VariableDeclaration", - "scope": 24775, - "src": "6437:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - }, - "typeName": { - "id": 24769, - "name": "uint32", - "nodeType": "ElementaryTypeName", - "src": "6437:6:29", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24772, - "mutability": "mutable", - "name": "oldCommitment", - "nameLocation": "6471:13:29", - "nodeType": "VariableDeclaration", - "scope": 24775, - "src": "6463:21:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24771, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "6463:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24774, - "mutability": "mutable", - "name": "newCommitment", - "nameLocation": "6502:13:29", - "nodeType": "VariableDeclaration", - "scope": 24775, - "src": "6494:21:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24773, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "6494:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "name": "IdentityUpdate", - "nameLocation": "6412:14:29", - "scope": 26045, - "visibility": "public" - }, - { - "id": 24779, - "nodeType": "EnumDefinition", - "src": "6619:95:29", - "nodes": [], - "canonicalName": "WorldIDIdentityManagerImplV1.UnreducedElementType", - "members": [ - { - "id": 24776, - "name": "PreRoot", - "nameLocation": "6655:7:29", - "nodeType": "EnumValue", - "src": "6655:7:29" - }, - { - "id": 24777, - "name": "IdentityCommitment", - "nameLocation": "6672:18:29", - "nodeType": "EnumValue", - "src": "6672:18:29" - }, - { - "id": 24778, - "name": "PostRoot", - "nameLocation": "6700:8:29", - "nodeType": "EnumValue", - "src": "6700:8:29" - } - ], - "name": "UnreducedElementType", - "nameLocation": "6624:20:29" - }, - { - "id": 24793, - "nodeType": "FunctionDefinition", - "src": "7105:120:29", - "nodes": [], - "body": { - "id": 24792, - "nodeType": "Block", - "src": "7176:49:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [ - { - "hexValue": "307830", - "id": 24787, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "7202:3:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0x0" - }, - { - "hexValue": "307830", - "id": 24788, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "7207:3:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0x0" - }, - { - "hexValue": "66616c7365", - "id": 24789, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "bool", - "lValueRequested": false, - "nodeType": "Literal", - "src": "7212:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "value": "false" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - ], - "id": 24786, - "name": "RootInfo", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24768, - "src": "7193:8:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_struct$_RootInfo_$24768_storage_ptr_$", - "typeString": "type(struct WorldIDIdentityManagerImplV1.RootInfo storage pointer)" - } - }, - "id": 24790, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "structConstructorCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "7193:25:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo memory" - } - }, - "functionReturnParameters": 24785, - "id": 24791, - "nodeType": "Return", - "src": "7186:32:29" - } - ] - }, - "documentation": { - "id": 24780, - "nodeType": "StructuredDocumentation", - "src": "6973:127:29", - "text": "@notice A constant representing a root that doesn't exist.\n @dev Can be checked against when querying for root data." - }, - "functionSelector": "561f204b", - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "NO_SUCH_ROOT", - "nameLocation": "7114:12:29", - "parameters": { - "id": 24781, - "nodeType": "ParameterList", - "parameters": [], - "src": "7126:2:29" - }, - "returnParameters": { - "id": 24785, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24784, - "mutability": "mutable", - "name": "rootInfo", - "nameLocation": "7166:8:29", - "nodeType": "VariableDeclaration", - "scope": 24793, - "src": "7150:24:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo" - }, - "typeName": { - "id": 24783, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24782, - "name": "RootInfo", - "nameLocations": [ - "7150:8:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24768, - "src": "7150:8:29" - }, - "referencedDeclaration": 24768, - "src": "7150:8:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo" - } - }, - "visibility": "internal" - } - ], - "src": "7149:26:29" - }, - "scope": 26045, - "stateMutability": "pure", - "virtual": false, - "visibility": "public" - }, - { - "id": 24801, - "nodeType": "ErrorDefinition", - "src": "7808:74:29", - "nodes": [], - "documentation": { - "id": 24794, - "nodeType": "StructuredDocumentation", - "src": "7484:319:29", - "text": "@notice Thrown when encountering an element that should be reduced as a member of `Fr` but\n is not.\n @dev `r` in this case is given by `SNARK_SCALAR_FIELD`.\n @param elementType The kind of element that was encountered unreduced.\n @param element The value of that element." - }, - "errorSelector": "af1e1889", - "name": "UnreducedElement", - "nameLocation": "7814:16:29", - "parameters": { - "id": 24800, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24797, - "mutability": "mutable", - "name": "elementType", - "nameLocation": "7852:11:29", - "nodeType": "VariableDeclaration", - "scope": 24801, - "src": "7831:32:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - "typeName": { - "id": 24796, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24795, - "name": "UnreducedElementType", - "nameLocations": [ - "7831:20:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24779, - "src": "7831:20:29" - }, - "referencedDeclaration": 24779, - "src": "7831:20:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24799, - "mutability": "mutable", - "name": "element", - "nameLocation": "7873:7:29", - "nodeType": "VariableDeclaration", - "scope": 24801, - "src": "7865:15:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24798, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "7865:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "7830:51:29" - } - }, - { - "id": 24806, - "nodeType": "ErrorDefinition", - "src": "8104:33:29", - "nodes": [], - "documentation": { - "id": 24802, - "nodeType": "StructuredDocumentation", - "src": "7888:211:29", - "text": "@notice Thrown when trying to execute a privileged action without being the contract\n manager.\n @param user The user that attempted the action that they were not authorised for." - }, - "errorSelector": "8e4a23d6", - "name": "Unauthorized", - "nameLocation": "8110:12:29", - "parameters": { - "id": 24805, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24804, - "mutability": "mutable", - "name": "user", - "nameLocation": "8131:4:29", - "nodeType": "VariableDeclaration", - "scope": 24806, - "src": "8123:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 24803, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "8123:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "8122:14:29" - } - }, - { - "id": 24811, - "nodeType": "ErrorDefinition", - "src": "8369:39:29", - "nodes": [], - "documentation": { - "id": 24807, - "nodeType": "StructuredDocumentation", - "src": "8143:221:29", - "text": "@notice Thrown when one or more of the identity commitments to be inserted is invalid.\n @param index The index in the array of identity commitments where the invalid commitment was\n found." - }, - "errorSelector": "31e63ea0", - "name": "InvalidCommitment", - "nameLocation": "8375:17:29", - "parameters": { - "id": 24810, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24809, - "mutability": "mutable", - "name": "index", - "nameLocation": "8401:5:29", - "nodeType": "VariableDeclaration", - "scope": 24811, - "src": "8393:13:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24808, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "8393:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "8392:15:29" - } - }, - { - "id": 24814, - "nodeType": "ErrorDefinition", - "src": "8509:31:29", - "nodes": [], - "documentation": { - "id": 24812, - "nodeType": "StructuredDocumentation", - "src": "8414:90:29", - "text": "@notice Thrown when the provided proof cannot be verified for the accompanying inputs." - }, - "errorSelector": "1e716a8b", - "name": "ProofValidationFailure", - "nameLocation": "8515:22:29", - "parameters": { - "id": 24813, - "nodeType": "ParameterList", - "parameters": [], - "src": "8537:2:29" - } - }, - { - "id": 24821, - "nodeType": "ErrorDefinition", - "src": "8801:62:29", - "nodes": [], - "documentation": { - "id": 24815, - "nodeType": "StructuredDocumentation", - "src": "8546:250:29", - "text": "@notice Thrown when the provided root is not the very latest root.\n @param providedRoot The root that was provided as the `preRoot` for a transaction.\n @param latestRoot The actual latest root at the time of the transaction." - }, - "errorSelector": "a85f9db2", - "name": "NotLatestRoot", - "nameLocation": "8807:13:29", - "parameters": { - "id": 24820, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24817, - "mutability": "mutable", - "name": "providedRoot", - "nameLocation": "8829:12:29", - "nodeType": "VariableDeclaration", - "scope": 24821, - "src": "8821:20:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24816, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "8821:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24819, - "mutability": "mutable", - "name": "latestRoot", - "nameLocation": "8851:10:29", - "nodeType": "VariableDeclaration", - "scope": 24821, - "src": "8843:18:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24818, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "8843:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "8820:42:29" - } - }, - { - "id": 24824, - "nodeType": "ErrorDefinition", - "src": "8945:20:29", - "nodes": [], - "documentation": { - "id": 24822, - "nodeType": "StructuredDocumentation", - "src": "8869:71:29", - "text": "@notice Thrown when attempting to validate a root that has expired." - }, - "errorSelector": "3ae7359e", - "name": "ExpiredRoot", - "nameLocation": "8951:11:29", - "parameters": { - "id": 24823, - "nodeType": "ParameterList", - "parameters": [], - "src": "8962:2:29" - } - }, - { - "id": 24827, - "nodeType": "ErrorDefinition", - "src": "9091:24:29", - "nodes": [], - "documentation": { - "id": 24825, - "nodeType": "StructuredDocumentation", - "src": "8971:115:29", - "text": "@notice Thrown when attempting to validate a root that has yet to be added to the root\n history." - }, - "errorSelector": "ddae3b71", - "name": "NonExistentRoot", - "nameLocation": "9097:15:29", - "parameters": { - "id": 24826, - "nodeType": "ParameterList", - "parameters": [], - "src": "9112:2:29" - } - }, - { - "id": 24830, - "nodeType": "ErrorDefinition", - "src": "9220:50:29", - "nodes": [], - "documentation": { - "id": 24828, - "nodeType": "StructuredDocumentation", - "src": "9121:94:29", - "text": "@notice Thrown when attempting to send a transaction to the state bridge proxy that fails." - }, - "errorSelector": "ca278835", - "name": "StateBridgeProxySendRootMultichainFailure", - "nameLocation": "9226:41:29", - "parameters": { - "id": 24829, - "nodeType": "ParameterList", - "parameters": [], - "src": "9267:2:29" - } - }, - { - "id": 24833, - "nodeType": "ErrorDefinition", - "src": "9364:34:29", - "nodes": [], - "documentation": { - "id": 24831, - "nodeType": "StructuredDocumentation", - "src": "9276:83:29", - "text": "@notice Thrown when attempting to enable the bridge when it is already enabled." - }, - "errorSelector": "963a8d4f", - "name": "StateBridgeAlreadyEnabled", - "nameLocation": "9370:25:29", - "parameters": { - "id": 24832, - "nodeType": "ParameterList", - "parameters": [], - "src": "9395:2:29" - } - }, - { - "id": 24836, - "nodeType": "ErrorDefinition", - "src": "9494:35:29", - "nodes": [], - "documentation": { - "id": 24834, - "nodeType": "StructuredDocumentation", - "src": "9404:85:29", - "text": "@notice Thrown when attempting to disable the bridge when it is already disabled." - }, - "errorSelector": "c6b90a44", - "name": "StateBridgeAlreadyDisabled", - "nameLocation": "9500:26:29", - "parameters": { - "id": 24835, - "nodeType": "ParameterList", - "parameters": [], - "src": "9526:2:29" - } - }, - { - "id": 24839, - "nodeType": "ErrorDefinition", - "src": "9633:39:29", - "nodes": [], - "documentation": { - "id": 24837, - "nodeType": "StructuredDocumentation", - "src": "9535:93:29", - "text": "@notice Thrown when attempting to set the state bridge proxy address to the zero address." - }, - "errorSelector": "5aacddde", - "name": "InvalidStateBridgeProxyAddress", - "nameLocation": "9639:30:29", - "parameters": { - "id": 24838, - "nodeType": "ParameterList", - "parameters": [], - "src": "9669:2:29" - } - }, - { - "id": 24844, - "nodeType": "ErrorDefinition", - "src": "9793:40:29", - "nodes": [], - "documentation": { - "id": 24840, - "nodeType": "StructuredDocumentation", - "src": "9678:110:29", - "text": "@notice Thrown when Semaphore tree depth is not supported.\n @param depth Passed tree depth." - }, - "errorSelector": "8833b8c0", - "name": "UnsupportedTreeDepth", - "nameLocation": "9799:20:29", - "parameters": { - "id": 24843, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24842, - "mutability": "mutable", - "name": "depth", - "nameLocation": "9826:5:29", - "nodeType": "VariableDeclaration", - "scope": 24844, - "src": "9820:11:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - }, - "typeName": { - "id": 24841, - "name": "uint8", - "nodeType": "ElementaryTypeName", - "src": "9820:5:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "visibility": "internal" - } - ], - "src": "9819:13:29" - } - }, - { - "id": 24852, - "nodeType": "FunctionDefinition", - "src": "10133:281:29", - "nodes": [], - "body": { - "id": 24851, - "nodeType": "Block", - "src": "10147:267:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 24848, - "name": "_disableInitializers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 21496, - "src": "10385:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 24849, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "10385:22:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24850, - "nodeType": "ExpressionStatement", - "src": "10385:22:29" - } - ] - }, - "documentation": { - "id": 24845, - "nodeType": "StructuredDocumentation", - "src": "10092:36:29", - "text": "@notice Constructs the contract." - }, - "implemented": true, - "kind": "constructor", - "modifiers": [], - "name": "", - "nameLocation": "-1:-1:-1", - "parameters": { - "id": 24846, - "nodeType": "ParameterList", - "parameters": [], - "src": "10144:2:29" - }, - "returnParameters": { - "id": 24847, - "nodeType": "ParameterList", - "parameters": [], - "src": "10147:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "public" - }, - { - "id": 24926, - "nodeType": "FunctionDefinition", - "src": "11753:1099:29", - "nodes": [], - "body": { - "id": 24925, - "nodeType": "Block", - "src": "12091:761:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 24876, - "name": "__delegateInit", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24939, - "src": "12176:14:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 24877, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "12176:16:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24878, - "nodeType": "ExpressionStatement", - "src": "12176:16:29" - }, - { - "condition": { - "id": 24883, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "12207:49:29", - "subExpression": { - "arguments": [ - { - "id": 24881, - "name": "_treeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24855, - "src": "12245:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - ], - "expression": { - "id": 24879, - "name": "SemaphoreTreeDepthValidator", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 41077, - "src": "12208:27:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_SemaphoreTreeDepthValidator_$41077_$", - "typeString": "type(library SemaphoreTreeDepthValidator)" - } - }, - "id": 24880, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "12236:8:29", - "memberName": "validate", - "nodeType": "MemberAccess", - "referencedDeclaration": 41076, - "src": "12208:36:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_pure$_t_uint8_$returns$_t_bool_$", - "typeString": "function (uint8) pure returns (bool)" - } - }, - "id": 24882, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "12208:48:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 24889, - "nodeType": "IfStatement", - "src": "12203:119:29", - "trueBody": { - "id": 24888, - "nodeType": "Block", - "src": "12258:64:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "id": 24885, - "name": "_treeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24855, - "src": "12300:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - ], - "id": 24884, - "name": "UnsupportedTreeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24844, - "src": "12279:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_uint8_$returns$__$", - "typeString": "function (uint8) pure" - } - }, - "id": 24886, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "12279:32:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24887, - "nodeType": "RevertStatement", - "src": "12272:39:29" - } - ] - } - }, - { - "expression": { - "id": 24892, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24890, - "name": "treeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24761, - "src": "12389:9:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24891, - "name": "_treeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24855, - "src": "12401:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "src": "12389:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "id": 24893, - "nodeType": "ExpressionStatement", - "src": "12389:22:29" - }, - { - "expression": { - "id": 24896, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24894, - "name": "rootHistoryExpiry", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24729, - "src": "12421:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "hexValue": "31", - "id": 24895, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "12441:7:29", - "subdenomination": "hours", - "typeDescriptions": { - "typeIdentifier": "t_rational_3600_by_1", - "typeString": "int_const 3600" - }, - "value": "1" - }, - "src": "12421:27:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 24897, - "nodeType": "ExpressionStatement", - "src": "12421:27:29" - }, - { - "expression": { - "id": 24900, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24898, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "12458:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24899, - "name": "initialRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24857, - "src": "12472:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "12458:25:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 24901, - "nodeType": "ExpressionStatement", - "src": "12458:25:29" - }, - { - "expression": { - "id": 24904, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24902, - "name": "batchInsertionVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24744, - "src": "12493:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24903, - "name": "_batchInsertionVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24860, - "src": "12519:24:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "src": "12493:50:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "id": 24905, - "nodeType": "ExpressionStatement", - "src": "12493:50:29" - }, - { - "expression": { - "id": 24908, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24906, - "name": "identityUpdateVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24748, - "src": "12553:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24907, - "name": "_batchUpdateVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24863, - "src": "12579:21:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "src": "12553:47:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "id": 24909, - "nodeType": "ExpressionStatement", - "src": "12553:47:29" - }, - { - "expression": { - "id": 24912, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24910, - "name": "semaphoreVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24752, - "src": "12610:17:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24911, - "name": "_semaphoreVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24866, - "src": "12630:18:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "src": "12610:38:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "id": 24913, - "nodeType": "ExpressionStatement", - "src": "12610:38:29" - }, - { - "expression": { - "id": 24916, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24914, - "name": "_stateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24755, - "src": "12658:24:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24915, - "name": "initialStateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24870, - "src": "12685:30:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "12658:57:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "id": 24917, - "nodeType": "ExpressionStatement", - "src": "12658:57:29" - }, - { - "expression": { - "id": 24920, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 24918, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "12725:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 24919, - "name": "_enableStateBridge", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24868, - "src": "12749:18:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "src": "12725:42:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 24921, - "nodeType": "ExpressionStatement", - "src": "12725:42:29" - }, - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 24922, - "name": "__setInitialized", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 41030, - "src": "12827:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 24923, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "12827:18:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24924, - "nodeType": "ExpressionStatement", - "src": "12827:18:29" - } - ] - }, - "documentation": { - "id": 24853, - "nodeType": "StructuredDocumentation", - "src": "10420:1328:29", - "text": "@notice Initializes the contract.\n @dev Must be called exactly once.\n @dev This is marked `reinitializer()` to allow for updated initialisation steps when working\n with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed)\n initialisations allowed, so decide carefully when to use them. Many cases can safely be\n replaced by use of setters.\n @param _treeDepth The depth of the MerkeTree\n @param initialRoot The initial value for the `latestRoot` in the contract. When deploying\n this should be set to the root of the empty tree.\n @param _batchInsertionVerifiers The verifier lookup table for batch insertions.\n @param _batchUpdateVerifiers The verifier lookup table for batch updates.\n @param _semaphoreVerifier The verifier to use for semaphore protocol proofs.\n @param _enableStateBridge Whether or not the state bridge should be enabled when\n initialising the identity manager.\n @param initialStateBridgeProxyAddress The initial state bridge proxy address to use.\n @custom:reverts string If called more than once at the same initalisation number.\n @custom:reverts UnsupportedTreeDepth If passed tree depth is not amoung defined values." - }, - "functionSelector": "f2ebe631", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "arguments": [ - { - "hexValue": "31", - "id": 24873, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "12088:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_1_by_1", - "typeString": "int_const 1" - }, - "value": "1" - } - ], - "id": 24874, - "kind": "modifierInvocation", - "modifierName": { - "id": 24872, - "name": "reinitializer", - "nameLocations": [ - "12074:13:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21450, - "src": "12074:13:29" - }, - "nodeType": "ModifierInvocation", - "src": "12074:16:29" - } - ], - "name": "initialize", - "nameLocation": "11762:10:29", - "parameters": { - "id": 24871, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24855, - "mutability": "mutable", - "name": "_treeDepth", - "nameLocation": "11788:10:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "11782:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - }, - "typeName": { - "id": 24854, - "name": "uint8", - "nodeType": "ElementaryTypeName", - "src": "11782:5:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24857, - "mutability": "mutable", - "name": "initialRoot", - "nameLocation": "11816:11:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "11808:19:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24856, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "11808:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24860, - "mutability": "mutable", - "name": "_batchInsertionVerifiers", - "nameLocation": "11857:24:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "11837:44:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - }, - "typeName": { - "id": 24859, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24858, - "name": "VerifierLookupTable", - "nameLocations": [ - "11837:19:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26691, - "src": "11837:19:29" - }, - "referencedDeclaration": 26691, - "src": "11837:19:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24863, - "mutability": "mutable", - "name": "_batchUpdateVerifiers", - "nameLocation": "11911:21:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "11891:41:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - }, - "typeName": { - "id": 24862, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24861, - "name": "VerifierLookupTable", - "nameLocations": [ - "11891:19:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26691, - "src": "11891:19:29" - }, - "referencedDeclaration": 26691, - "src": "11891:19:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24866, - "mutability": "mutable", - "name": "_semaphoreVerifier", - "nameLocation": "11961:18:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "11942:37:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - }, - "typeName": { - "id": 24865, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 24864, - "name": "ISemaphoreVerifier", - "nameLocations": [ - "11942:18:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24290, - "src": "11942:18:29" - }, - "referencedDeclaration": 24290, - "src": "11942:18:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24868, - "mutability": "mutable", - "name": "_enableStateBridge", - "nameLocation": "11994:18:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "11989:23:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 24867, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "11989:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24870, - "mutability": "mutable", - "name": "initialStateBridgeProxyAddress", - "nameLocation": "12030:30:29", - "nodeType": "VariableDeclaration", - "scope": 24926, - "src": "12022:38:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 24869, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "12022:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "11772:294:29" - }, - "returnParameters": { - "id": 24875, - "nodeType": "ParameterList", - "parameters": [], - "src": "12091:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "public" - }, - { - "id": 24939, - "nodeType": "FunctionDefinition", - "src": "13186:127:29", - "nodes": [], - "body": { - "id": 24938, - "nodeType": "Block", - "src": "13246:67:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 24932, - "name": "__Ownable_init", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 20852, - "src": "13256:14:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 24933, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "13256:16:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24934, - "nodeType": "ExpressionStatement", - "src": "13256:16:29" - }, - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 24935, - "name": "__UUPSUpgradeable_init", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 21533, - "src": "13282:22:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 24936, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "13282:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24937, - "nodeType": "ExpressionStatement", - "src": "13282:24:29" - } - ] - }, - "documentation": { - "id": 24927, - "nodeType": "StructuredDocumentation", - "src": "12858:323:29", - "text": "@notice Responsible for initialising all of the supertypes of this contract.\n @dev Must be called exactly once.\n @dev When adding new superclasses, ensure that any initialization that they need to perform\n is accounted for here.\n @custom:reverts string If called more than once." - }, - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 24930, - "kind": "modifierInvocation", - "modifierName": { - "id": 24929, - "name": "onlyInitializing", - "nameLocations": [ - "13229:16:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21460, - "src": "13229:16:29" - }, - "nodeType": "ModifierInvocation", - "src": "13229:16:29" - } - ], - "name": "__delegateInit", - "nameLocation": "13195:14:29", - "parameters": { - "id": 24928, - "nodeType": "ParameterList", - "parameters": [], - "src": "13209:2:29" - }, - "returnParameters": { - "id": 24931, - "nodeType": "ParameterList", - "parameters": [], - "src": "13246:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "internal" - }, - { - "id": 25106, - "nodeType": "FunctionDefinition", - "src": "15922:3385:29", - "nodes": [], - "body": { - "id": 25105, - "nodeType": "Block", - "src": "16177:3130:29", - "nodes": [], - "statements": [ - { - "condition": { - "id": 24965, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "16258:30:29", - "subExpression": { - "arguments": [ - { - "id": 24963, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24946, - "src": "16280:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 24962, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "16259:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 24964, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "16259:29:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 24973, - "nodeType": "IfStatement", - "src": "16254:123:29", - "trueBody": { - "id": 24972, - "nodeType": "Block", - "src": "16290:87:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 24967, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "16328:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 24968, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "16349:7:29", - "memberName": "PreRoot", - "nodeType": "MemberAccess", - "referencedDeclaration": 24776, - "src": "16328:28:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "id": 24969, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24946, - "src": "16358:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 24966, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "16311:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 24970, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "16311:55:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24971, - "nodeType": "RevertStatement", - "src": "16304:62:29" - } - ] - } - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 24976, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 24974, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24946, - "src": "16390:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "id": 24975, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "16401:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "16390:22:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 24983, - "nodeType": "IfStatement", - "src": "16386:95:29", - "trueBody": { - "id": 24982, - "nodeType": "Block", - "src": "16414:67:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "id": 24978, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24946, - "src": "16449:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 24979, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "16458:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 24977, - "name": "NotLatestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24821, - "src": "16435:13:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_uint256_$_t_uint256_$returns$__$", - "typeString": "function (uint256,uint256) pure" - } - }, - "id": 24980, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "16435:35:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24981, - "nodeType": "RevertStatement", - "src": "16428:42:29" - } - ] - } - }, - { - "condition": { - "id": 24987, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "16869:31:29", - "subExpression": { - "arguments": [ - { - "id": 24985, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24953, - "src": "16891:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 24984, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "16870:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 24986, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "16870:30:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 24995, - "nodeType": "IfStatement", - "src": "16865:126:29", - "trueBody": { - "id": 24994, - "nodeType": "Block", - "src": "16902:89:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 24989, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "16940:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 24990, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "16961:8:29", - "memberName": "PostRoot", - "nodeType": "MemberAccess", - "referencedDeclaration": 24778, - "src": "16940:29:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "id": 24991, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24953, - "src": "16971:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 24988, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "16923:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 24992, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "16923:57:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24993, - "nodeType": "RevertStatement", - "src": "16916:64:29" - } - ] - } - }, - { - "expression": { - "arguments": [ - { - "id": 24997, - "name": "identityCommitments", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24951, - "src": "17125:19:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - ], - "id": 24996, - "name": "validateIdentityCommitmentsForRegistration", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25682, - "src": "17082:42:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_array$_t_uint256_$dyn_calldata_ptr_$returns$__$", - "typeString": "function (uint256[] calldata) view" - } - }, - "id": 24998, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "17082:63:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 24999, - "nodeType": "ExpressionStatement", - "src": "17082:63:29" - }, - { - "assignments": [ - 25001 - ], - "declarations": [ - { - "constant": false, - "id": 25001, - "mutability": "mutable", - "name": "inputHash", - "nameLocation": "17245:9:29", - "nodeType": "VariableDeclaration", - "scope": 25105, - "src": "17237:17:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - }, - "typeName": { - "id": 25000, - "name": "bytes32", - "nodeType": "ElementaryTypeName", - "src": "17237:7:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "visibility": "internal" - } - ], - "id": 25008, - "initialValue": { - "arguments": [ - { - "id": 25003, - "name": "startIndex", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24948, - "src": "17309:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - } - }, - { - "id": 25004, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24946, - "src": "17321:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25005, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24953, - "src": "17330:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25006, - "name": "identityCommitments", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24951, - "src": "17340:19:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - ], - "id": 25002, - "name": "calculateIdentityRegistrationInputHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25341, - "src": "17257:38:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint32_$_t_uint256_$_t_uint256_$_t_array$_t_uint256_$dyn_calldata_ptr_$returns$_t_bytes32_$", - "typeString": "function (uint32,uint256,uint256,uint256[] calldata) view returns (bytes32)" - } - }, - "id": 25007, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "17257:112:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "17237:132:29" - }, - { - "assignments": [ - 25010 - ], - "declarations": [ - { - "constant": false, - "id": 25010, - "mutability": "mutable", - "name": "reducedElement", - "nameLocation": "17601:14:29", - "nodeType": "VariableDeclaration", - "scope": 25105, - "src": "17593:22:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25009, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "17593:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25017, - "initialValue": { - "arguments": [ - { - "arguments": [ - { - "id": 25014, - "name": "inputHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25001, - "src": "17663:9:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - ], - "id": 25013, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "17655:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_uint256_$", - "typeString": "type(uint256)" - }, - "typeName": { - "id": 25012, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "17655:7:29", - "typeDescriptions": {} - } - }, - "id": 25015, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "17655:18:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25011, - "name": "reduceInputElementInSnarkScalarField", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25808, - "src": "17618:36:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$", - "typeString": "function (uint256) pure returns (uint256)" - } - }, - "id": 25016, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "17618:56:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "17593:81:29" - }, - { - "assignments": [ - 25020 - ], - "declarations": [ - { - "constant": false, - "id": 25020, - "mutability": "mutable", - "name": "insertionVerifier", - "nameLocation": "17772:17:29", - "nodeType": "VariableDeclaration", - "scope": 25105, - "src": "17758:31:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - }, - "typeName": { - "id": 25019, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25018, - "name": "ITreeVerifier", - "nameLocations": [ - "17758:13:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26728, - "src": "17758:13:29" - }, - "referencedDeclaration": 26728, - "src": "17758:13:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - } - }, - "visibility": "internal" - } - ], - "id": 25026, - "initialValue": { - "arguments": [ - { - "expression": { - "id": 25023, - "name": "identityCommitments", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24951, - "src": "17843:19:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - }, - "id": 25024, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "17863:6:29", - "memberName": "length", - "nodeType": "MemberAccess", - "src": "17843:26:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "expression": { - "id": 25021, - "name": "batchInsertionVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24744, - "src": "17804:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "id": 25022, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "17828:14:29", - "memberName": "getVerifierFor", - "nodeType": "MemberAccess", - "referencedDeclaration": 26600, - "src": "17804:38:29", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$_t_uint256_$returns$_t_contract$_ITreeVerifier_$26728_$", - "typeString": "function (uint256) view external returns (contract ITreeVerifier)" - } - }, - "id": 25025, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "17804:66:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "17758:112:29" - }, - { - "clauses": [ - { - "block": { - "id": 25088, - "nodeType": "Block", - "src": "18237:699:29", - "statements": [ - { - "condition": { - "id": 25065, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "18325:15:29", - "subExpression": { - "id": 25064, - "name": "verifierResult", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25062, - "src": "18326:14:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25070, - "nodeType": "IfStatement", - "src": "18321:85:29", - "trueBody": { - "id": 25069, - "nodeType": "Block", - "src": "18342:64:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25066, - "name": "ProofValidationFailure", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24814, - "src": "18367:22:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25067, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "18367:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25068, - "nodeType": "RevertStatement", - "src": "18360:31:29" - } - ] - } - }, - { - "expression": { - "id": 25073, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25071, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "18574:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25072, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24953, - "src": "18588:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "18574:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25074, - "nodeType": "ExpressionStatement", - "src": "18574:22:29" - }, - { - "expression": { - "id": 25083, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "baseExpression": { - "id": 25075, - "name": "rootHistory", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24726, - "src": "18742:11:29", - "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", - "typeString": "mapping(uint256 => uint128)" - } - }, - "id": 25077, - "indexExpression": { - "id": 25076, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24946, - "src": "18754:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": true, - "nodeType": "IndexAccess", - "src": "18742:20:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "arguments": [ - { - "expression": { - "id": 25080, - "name": "block", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -4, - "src": "18773:5:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_block", - "typeString": "block" - } - }, - "id": 25081, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "18779:9:29", - "memberName": "timestamp", - "nodeType": "MemberAccess", - "src": "18773:15:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25079, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "18765:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_uint128_$", - "typeString": "type(uint128)" - }, - "typeName": { - "id": 25078, - "name": "uint128", - "nodeType": "ElementaryTypeName", - "src": "18765:7:29", - "typeDescriptions": {} - } - }, - "id": 25082, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "18765:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "src": "18742:47:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "id": 25084, - "nodeType": "ExpressionStatement", - "src": "18742:47:29" - }, - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25085, - "name": "sendRootToStateBridge", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25472, - "src": "18902:21:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 25086, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "18902:23:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25087, - "nodeType": "ExpressionStatement", - "src": "18902:23:29" - } - ] - }, - "errorName": "", - "id": 25089, - "nodeType": "TryCatchClause", - "parameters": { - "id": 25063, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25062, - "mutability": "mutable", - "name": "verifierResult", - "nameLocation": "18221:14:29", - "nodeType": "VariableDeclaration", - "scope": 25089, - "src": "18216:19:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25061, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "18216:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "18215:21:29" - }, - "src": "18207:729:29" - }, - { - "block": { - "id": 25097, - "nodeType": "Block", - "src": "18974:100:29", - "statements": [ - { - "documentation": "This is not the revert we're looking for.", - "expression": { - "arguments": [ - { - "id": 25094, - "name": "errString", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25091, - "src": "19053:9:29", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string memory" - } - ], - "id": 25093, - "name": "revert", - "nodeType": "Identifier", - "overloadedDeclarations": [ - -19, - -19 - ], - "referencedDeclaration": -19, - "src": "19046:6:29", - "typeDescriptions": { - "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", - "typeString": "function (string memory) pure" - } - }, - "id": 25095, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "19046:17:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25096, - "nodeType": "ExpressionStatement", - "src": "19046:17:29" - } - ] - }, - "errorName": "Error", - "id": 25098, - "nodeType": "TryCatchClause", - "parameters": { - "id": 25092, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25091, - "mutability": "mutable", - "name": "errString", - "nameLocation": "18963:9:29", - "nodeType": "VariableDeclaration", - "scope": 25098, - "src": "18949:23:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string" - }, - "typeName": { - "id": 25090, - "name": "string", - "nodeType": "ElementaryTypeName", - "src": "18949:6:29", - "typeDescriptions": { - "typeIdentifier": "t_string_storage_ptr", - "typeString": "string" - } - }, - "visibility": "internal" - } - ], - "src": "18948:25:29" - }, - "src": "18937:137:29" - }, - { - "block": { - "id": 25102, - "nodeType": "Block", - "src": "19081:220:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25099, - "name": "ProofValidationFailure", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24814, - "src": "19266:22:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25100, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "19266:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25101, - "nodeType": "RevertStatement", - "src": "19259:31:29" - } - ] - }, - "errorName": "", - "id": 25103, - "nodeType": "TryCatchClause", - "src": "19075:226:29" - } - ], - "externalCall": { - "arguments": [ - { - "components": [ - { - "baseExpression": { - "id": 25029, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "17983:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25031, - "indexExpression": { - "hexValue": "30", - "id": 25030, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "17998:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "17983:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25032, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18002:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25034, - "indexExpression": { - "hexValue": "31", - "id": 25033, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18017:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_1_by_1", - "typeString": "int_const 1" - }, - "value": "1" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18002:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25035, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "17982:38:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - }, - { - "components": [ - { - "components": [ - { - "baseExpression": { - "id": 25036, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18036:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25038, - "indexExpression": { - "hexValue": "32", - "id": 25037, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18051:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_2_by_1", - "typeString": "int_const 2" - }, - "value": "2" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18036:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25039, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18055:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25041, - "indexExpression": { - "hexValue": "33", - "id": 25040, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18070:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_3_by_1", - "typeString": "int_const 3" - }, - "value": "3" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18055:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25042, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "18035:38:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - }, - { - "components": [ - { - "baseExpression": { - "id": 25043, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18076:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25045, - "indexExpression": { - "hexValue": "34", - "id": 25044, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18091:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_4_by_1", - "typeString": "int_const 4" - }, - "value": "4" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18076:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25046, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18095:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25048, - "indexExpression": { - "hexValue": "35", - "id": 25047, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18110:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_5_by_1", - "typeString": "int_const 5" - }, - "value": "5" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18095:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25049, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "18075:38:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - } - ], - "id": 25050, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "18034:80:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", - "typeString": "uint256[2] memory[2] memory" - } - }, - { - "components": [ - { - "baseExpression": { - "id": 25051, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18129:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25053, - "indexExpression": { - "hexValue": "36", - "id": 25052, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18144:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_6_by_1", - "typeString": "int_const 6" - }, - "value": "6" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18129:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25054, - "name": "insertionProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24944, - "src": "18148:14:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25056, - "indexExpression": { - "hexValue": "37", - "id": 25055, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "18163:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_7_by_1", - "typeString": "int_const 7" - }, - "value": "7" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "18148:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25057, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "18128:38:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - }, - { - "components": [ - { - "id": 25058, - "name": "reducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25010, - "src": "18181:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25059, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "18180:16:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", - "typeString": "uint256[1] memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - }, - { - "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", - "typeString": "uint256[2] memory[2] memory" - }, - { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - }, - { - "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", - "typeString": "uint256[1] memory" - } - ], - "expression": { - "id": 25027, - "name": "insertionVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25020, - "src": "17939:17:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - } - }, - "id": 25028, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "17957:11:29", - "memberName": "verifyProof", - "nodeType": "MemberAccess", - "referencedDeclaration": 26727, - "src": "17939:29:29", - "typeDescriptions": { - "typeIdentifier": "t_function_external_nonpayable$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr_$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_uint256_$1_memory_ptr_$returns$_t_bool_$", - "typeString": "function (uint256[2] memory,uint256[2] memory[2] memory,uint256[2] memory,uint256[1] memory) external returns (bool)" - } - }, - "id": 25060, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "17939:267:29", - "tryCall": true, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25104, - "nodeType": "TryStatement", - "src": "17935:1366:29" - } - ] - }, - "documentation": { - "id": 24940, - "nodeType": "StructuredDocumentation", - "src": "14489:1428:29", - "text": "@param startIndex The position in the tree at which the insertions were made.\n @param identityCommitments The identities that were inserted into the tree starting at\n `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be\n elements of the field `Kr`.\n @param postRoot The root obtained after inserting all of `identityCommitments` into the tree\n described by `preRoot`. Must be an element of the field `Kr`.\n @custom:reverts Unauthorized If the message sender is not authorised to add identities.\n @custom:reverts InvalidCommitment If one or more of the provided commitments is invalid.\n @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root.\n @custom:reverts ProofValidationFailure If `insertionProof` cannot be verified using the\n provided inputs.\n @custom:reverts UnreducedElement If any of the `preRoot`, `postRoot` and\n `identityCommitments` is not an element of the field `Kr`. It describes the\n type and value of the unreduced element.\n @custom:reverts VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known\n verifier.\n @custom:reverts VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum\n batch size." - }, - "functionSelector": "2217b211", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 24956, - "kind": "modifierInvocation", - "modifierName": { - "id": 24955, - "name": "onlyProxy", - "nameLocations": [ - "16141:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "16141:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "16141:9:29" - }, - { - "id": 24958, - "kind": "modifierInvocation", - "modifierName": { - "id": 24957, - "name": "onlyInitialized", - "nameLocations": [ - "16151:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "16151:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "16151:15:29" - }, - { - "id": 24960, - "kind": "modifierInvocation", - "modifierName": { - "id": 24959, - "name": "onlyOwner", - "nameLocations": [ - "16167:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "16167:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "16167:9:29" - } - ], - "name": "registerIdentities", - "nameLocation": "15931:18:29", - "parameters": { - "id": 24954, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 24944, - "mutability": "mutable", - "name": "insertionProof", - "nameLocation": "15979:14:29", - "nodeType": "VariableDeclaration", - "scope": 25106, - "src": "15959:34:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8]" - }, - "typeName": { - "baseType": { - "id": 24941, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "15959:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 24943, - "length": { - "hexValue": "38", - "id": 24942, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "15967:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_8_by_1", - "typeString": "int_const 8" - }, - "value": "8" - }, - "nodeType": "ArrayTypeName", - "src": "15959:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_storage_ptr", - "typeString": "uint256[8]" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24946, - "mutability": "mutable", - "name": "preRoot", - "nameLocation": "16011:7:29", - "nodeType": "VariableDeclaration", - "scope": 25106, - "src": "16003:15:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24945, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "16003:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24948, - "mutability": "mutable", - "name": "startIndex", - "nameLocation": "16035:10:29", - "nodeType": "VariableDeclaration", - "scope": 25106, - "src": "16028:17:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - }, - "typeName": { - "id": 24947, - "name": "uint32", - "nodeType": "ElementaryTypeName", - "src": "16028:6:29", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24951, - "mutability": "mutable", - "name": "identityCommitments", - "nameLocation": "16074:19:29", - "nodeType": "VariableDeclaration", - "scope": 25106, - "src": "16055:38:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[]" - }, - "typeName": { - "baseType": { - "id": 24949, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "16055:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 24950, - "nodeType": "ArrayTypeName", - "src": "16055:9:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", - "typeString": "uint256[]" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 24953, - "mutability": "mutable", - "name": "postRoot", - "nameLocation": "16111:8:29", - "nodeType": "VariableDeclaration", - "scope": 25106, - "src": "16103:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 24952, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "16103:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "15949:176:29" - }, - "returnParameters": { - "id": 24961, - "nodeType": "ParameterList", - "parameters": [], - "src": "16177:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25140, - "nodeType": "FunctionDefinition", - "src": "21567:672:29", - "nodes": [], - "body": { - "id": 25139, - "nodeType": "Block", - "src": "21796:443:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 25129, - "name": "removedIdentities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25117, - "src": "21972:17:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - ], - "id": 25128, - "name": "validateIdentityCommitmentsForRemoval", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25778, - "src": "21934:37:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr_$returns$__$", - "typeString": "function (struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata) view" - } - }, - "id": 25130, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "21934:56:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25131, - "nodeType": "ExpressionStatement", - "src": "21934:56:29" - }, - { - "expression": { - "arguments": [ - { - "id": 25133, - "name": "removalProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25111, - "src": "22181:12:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - { - "id": 25134, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25113, - "src": "22195:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25135, - "name": "removedIdentities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25117, - "src": "22204:17:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - { - "id": 25136, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25119, - "src": "22223:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25132, - "name": "updateIdentities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25305, - "src": "22164:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$_t_array$_t_uint256_$8_calldata_ptr_$_t_uint256_$_t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr_$_t_uint256_$returns$__$", - "typeString": "function (uint256[8] calldata,uint256,struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata,uint256)" - } - }, - "id": 25137, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "22164:68:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25138, - "nodeType": "ExpressionStatement", - "src": "22164:68:29" - } - ] - }, - "documentation": { - "id": 25107, - "nodeType": "StructuredDocumentation", - "src": "20216:1346:29", - "text": "@param removedIdentities The identities that were removed from the tree. As they each hold\n their own leaf index, these need not be contiguous. All of the commitments must be\n elements of the field `Kr`.\n @param postRoot The root obtained after removing all of `removedIdentities` from the tree\n described by `preRoot`. Must be an element of the field `Kr`.\n @custom:reverts Unauthorized If the message sender is not authorised to remove identities.\n @custom:reverts InvalidCommitment If one or more of the provided identities is invalid.\n @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root.\n @custom:reverts ProofValidationFailure If `removalProof` cannot be verified using the\n provided inputs.\n @custom:reverts UnreducedElement If any of the `preRoot`, `postRoot` and\n `removedIdentities` is not an element of the field `Kr`. It describes the\n type and value of the unreduced element.\n @custom:reverts VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known\n verifier.\n @custom:reverts VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum\n batch size." - }, - "functionSelector": "b1390908", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25122, - "kind": "modifierInvocation", - "modifierName": { - "id": 25121, - "name": "onlyProxy", - "nameLocations": [ - "21760:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "21760:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "21760:9:29" - }, - { - "id": 25124, - "kind": "modifierInvocation", - "modifierName": { - "id": 25123, - "name": "onlyInitialized", - "nameLocations": [ - "21770:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "21770:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "21770:15:29" - }, - { - "id": 25126, - "kind": "modifierInvocation", - "modifierName": { - "id": 25125, - "name": "onlyOwner", - "nameLocations": [ - "21786:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "21786:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "21786:9:29" - } - ], - "name": "removeIdentities", - "nameLocation": "21576:16:29", - "parameters": { - "id": 25120, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25111, - "mutability": "mutable", - "name": "removalProof", - "nameLocation": "21622:12:29", - "nodeType": "VariableDeclaration", - "scope": 25140, - "src": "21602:32:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8]" - }, - "typeName": { - "baseType": { - "id": 25108, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "21602:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25110, - "length": { - "hexValue": "38", - "id": 25109, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "21610:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_8_by_1", - "typeString": "int_const 8" - }, - "value": "8" - }, - "nodeType": "ArrayTypeName", - "src": "21602:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_storage_ptr", - "typeString": "uint256[8]" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25113, - "mutability": "mutable", - "name": "preRoot", - "nameLocation": "21652:7:29", - "nodeType": "VariableDeclaration", - "scope": 25140, - "src": "21644:15:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25112, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "21644:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25117, - "mutability": "mutable", - "name": "removedIdentities", - "nameLocation": "21695:17:29", - "nodeType": "VariableDeclaration", - "scope": 25140, - "src": "21669:43:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - }, - "typeName": { - "baseType": { - "id": 25115, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25114, - "name": "IdentityUpdate", - "nameLocations": [ - "21669:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "21669:14:29" - }, - "referencedDeclaration": 24775, - "src": "21669:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "id": 25116, - "nodeType": "ArrayTypeName", - "src": "21669:16:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_storage_$dyn_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25119, - "mutability": "mutable", - "name": "postRoot", - "nameLocation": "21730:8:29", - "nodeType": "VariableDeclaration", - "scope": 25140, - "src": "21722:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25118, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "21722:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "21592:152:29" - }, - "returnParameters": { - "id": 25127, - "nodeType": "ParameterList", - "parameters": [], - "src": "21796:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25305, - "nodeType": "FunctionDefinition", - "src": "24400:2949:29", - "nodes": [], - "body": { - "id": 25304, - "nodeType": "Block", - "src": "24628:2721:29", - "nodes": [], - "statements": [ - { - "condition": { - "id": 25165, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "24709:30:29", - "subExpression": { - "arguments": [ - { - "id": 25163, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25147, - "src": "24731:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25162, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "24710:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 25164, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "24710:29:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25173, - "nodeType": "IfStatement", - "src": "24705:123:29", - "trueBody": { - "id": 25172, - "nodeType": "Block", - "src": "24741:87:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 25167, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "24779:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 25168, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "24800:7:29", - "memberName": "PreRoot", - "nodeType": "MemberAccess", - "referencedDeclaration": 24776, - "src": "24779:28:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "id": 25169, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25147, - "src": "24809:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25166, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "24762:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 25170, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "24762:55:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25171, - "nodeType": "RevertStatement", - "src": "24755:62:29" - } - ] - } - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25176, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25174, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25147, - "src": "24841:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "id": 25175, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "24852:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "24841:22:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25183, - "nodeType": "IfStatement", - "src": "24837:95:29", - "trueBody": { - "id": 25182, - "nodeType": "Block", - "src": "24865:67:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "id": 25178, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25147, - "src": "24900:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25179, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "24909:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25177, - "name": "NotLatestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24821, - "src": "24886:13:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_uint256_$_t_uint256_$returns$__$", - "typeString": "function (uint256,uint256) pure" - } - }, - "id": 25180, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "24886:35:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25181, - "nodeType": "RevertStatement", - "src": "24879:42:29" - } - ] - } - }, - { - "condition": { - "id": 25187, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "25007:31:29", - "subExpression": { - "arguments": [ - { - "id": 25185, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25153, - "src": "25029:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25184, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "25008:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 25186, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25008:30:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25195, - "nodeType": "IfStatement", - "src": "25003:126:29", - "trueBody": { - "id": 25194, - "nodeType": "Block", - "src": "25040:89:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 25189, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "25078:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 25190, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "25099:8:29", - "memberName": "PostRoot", - "nodeType": "MemberAccess", - "referencedDeclaration": 24778, - "src": "25078:29:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "id": 25191, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25153, - "src": "25109:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25188, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "25061:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 25192, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25061:57:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25193, - "nodeType": "RevertStatement", - "src": "25054:64:29" - } - ] - } - }, - { - "expression": { - "arguments": [ - { - "id": 25197, - "name": "updatedIdentities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25151, - "src": "25238:17:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - ], - "id": 25196, - "name": "validateIdentitiesInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25739, - "src": "25206:31:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr_$returns$__$", - "typeString": "function (struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata) view" - } - }, - "id": 25198, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25206:50:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25199, - "nodeType": "ExpressionStatement", - "src": "25206:50:29" - }, - { - "assignments": [ - 25201 - ], - "declarations": [ - { - "constant": false, - "id": 25201, - "mutability": "mutable", - "name": "inputHash", - "nameLocation": "25352:9:29", - "nodeType": "VariableDeclaration", - "scope": 25304, - "src": "25344:17:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - }, - "typeName": { - "id": 25200, - "name": "bytes32", - "nodeType": "ElementaryTypeName", - "src": "25344:7:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "visibility": "internal" - } - ], - "id": 25207, - "initialValue": { - "arguments": [ - { - "id": 25203, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25147, - "src": "25397:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25204, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25153, - "src": "25406:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25205, - "name": "updatedIdentities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25151, - "src": "25416:17:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - ], - "id": 25202, - "name": "calculateIdentityUpdateInputHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25423, - "src": "25364:32:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$_t_uint256_$_t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr_$returns$_t_bytes32_$", - "typeString": "function (uint256,uint256,struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata) view returns (bytes32)" - } - }, - "id": 25206, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25364:70:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "25344:90:29" - }, - { - "assignments": [ - 25209 - ], - "declarations": [ - { - "constant": false, - "id": 25209, - "mutability": "mutable", - "name": "reducedInputHash", - "nameLocation": "25641:16:29", - "nodeType": "VariableDeclaration", - "scope": 25304, - "src": "25633:24:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25208, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "25633:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25216, - "initialValue": { - "arguments": [ - { - "arguments": [ - { - "id": 25213, - "name": "inputHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25201, - "src": "25705:9:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - ], - "id": 25212, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "25697:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_uint256_$", - "typeString": "type(uint256)" - }, - "typeName": { - "id": 25211, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "25697:7:29", - "typeDescriptions": {} - } - }, - "id": 25214, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25697:18:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25210, - "name": "reduceInputElementInSnarkScalarField", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25808, - "src": "25660:36:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$", - "typeString": "function (uint256) pure returns (uint256)" - } - }, - "id": 25215, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25660:56:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "25633:83:29" - }, - { - "assignments": [ - 25219 - ], - "declarations": [ - { - "constant": false, - "id": 25219, - "mutability": "mutable", - "name": "updateVerifier", - "nameLocation": "25814:14:29", - "nodeType": "VariableDeclaration", - "scope": 25304, - "src": "25800:28:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - }, - "typeName": { - "id": 25218, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25217, - "name": "ITreeVerifier", - "nameLocations": [ - "25800:13:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26728, - "src": "25800:13:29" - }, - "referencedDeclaration": 26728, - "src": "25800:13:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - } - }, - "visibility": "internal" - } - ], - "id": 25225, - "initialValue": { - "arguments": [ - { - "expression": { - "id": 25222, - "name": "updatedIdentities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25151, - "src": "25882:17:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25223, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "25900:6:29", - "memberName": "length", - "nodeType": "MemberAccess", - "src": "25882:24:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "expression": { - "id": 25220, - "name": "identityUpdateVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24748, - "src": "25843:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "id": 25221, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "25867:14:29", - "memberName": "getVerifierFor", - "nodeType": "MemberAccess", - "referencedDeclaration": 26600, - "src": "25843:38:29", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$_t_uint256_$returns$_t_contract$_ITreeVerifier_$26728_$", - "typeString": "function (uint256) view external returns (contract ITreeVerifier)" - } - }, - "id": 25224, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "25843:64:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "25800:107:29" - }, - { - "clauses": [ - { - "block": { - "id": 25287, - "nodeType": "Block", - "src": "26279:699:29", - "statements": [ - { - "condition": { - "id": 25264, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "26367:15:29", - "subExpression": { - "id": 25263, - "name": "verifierResult", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25261, - "src": "26368:14:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25269, - "nodeType": "IfStatement", - "src": "26363:85:29", - "trueBody": { - "id": 25268, - "nodeType": "Block", - "src": "26384:64:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25265, - "name": "ProofValidationFailure", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24814, - "src": "26409:22:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25266, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "26409:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25267, - "nodeType": "RevertStatement", - "src": "26402:31:29" - } - ] - } - }, - { - "expression": { - "id": 25272, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25270, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "26616:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25271, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25153, - "src": "26630:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "26616:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25273, - "nodeType": "ExpressionStatement", - "src": "26616:22:29" - }, - { - "expression": { - "id": 25282, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "baseExpression": { - "id": 25274, - "name": "rootHistory", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24726, - "src": "26784:11:29", - "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", - "typeString": "mapping(uint256 => uint128)" - } - }, - "id": 25276, - "indexExpression": { - "id": 25275, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25147, - "src": "26796:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": true, - "nodeType": "IndexAccess", - "src": "26784:20:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "arguments": [ - { - "expression": { - "id": 25279, - "name": "block", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -4, - "src": "26815:5:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_block", - "typeString": "block" - } - }, - "id": 25280, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "26821:9:29", - "memberName": "timestamp", - "nodeType": "MemberAccess", - "src": "26815:15:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25278, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "26807:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_uint128_$", - "typeString": "type(uint128)" - }, - "typeName": { - "id": 25277, - "name": "uint128", - "nodeType": "ElementaryTypeName", - "src": "26807:7:29", - "typeDescriptions": {} - } - }, - "id": 25281, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "26807:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "src": "26784:47:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "id": 25283, - "nodeType": "ExpressionStatement", - "src": "26784:47:29" - }, - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25284, - "name": "sendRootToStateBridge", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25472, - "src": "26944:21:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 25285, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "26944:23:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25286, - "nodeType": "ExpressionStatement", - "src": "26944:23:29" - } - ] - }, - "errorName": "", - "id": 25288, - "nodeType": "TryCatchClause", - "parameters": { - "id": 25262, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25261, - "mutability": "mutable", - "name": "verifierResult", - "nameLocation": "26263:14:29", - "nodeType": "VariableDeclaration", - "scope": 25288, - "src": "26258:19:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25260, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "26258:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "26257:21:29" - }, - "src": "26249:729:29" - }, - { - "block": { - "id": 25296, - "nodeType": "Block", - "src": "27016:100:29", - "statements": [ - { - "documentation": "This is not the revert we're looking for.", - "expression": { - "arguments": [ - { - "id": 25293, - "name": "errString", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25290, - "src": "27095:9:29", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string memory" - } - ], - "id": 25292, - "name": "revert", - "nodeType": "Identifier", - "overloadedDeclarations": [ - -19, - -19 - ], - "referencedDeclaration": -19, - "src": "27088:6:29", - "typeDescriptions": { - "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", - "typeString": "function (string memory) pure" - } - }, - "id": 25294, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "27088:17:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25295, - "nodeType": "ExpressionStatement", - "src": "27088:17:29" - } - ] - }, - "errorName": "Error", - "id": 25297, - "nodeType": "TryCatchClause", - "parameters": { - "id": 25291, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25290, - "mutability": "mutable", - "name": "errString", - "nameLocation": "27005:9:29", - "nodeType": "VariableDeclaration", - "scope": 25297, - "src": "26991:23:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string" - }, - "typeName": { - "id": 25289, - "name": "string", - "nodeType": "ElementaryTypeName", - "src": "26991:6:29", - "typeDescriptions": { - "typeIdentifier": "t_string_storage_ptr", - "typeString": "string" - } - }, - "visibility": "internal" - } - ], - "src": "26990:25:29" - }, - "src": "26979:137:29" - }, - { - "block": { - "id": 25301, - "nodeType": "Block", - "src": "27123:220:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25298, - "name": "ProofValidationFailure", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24814, - "src": "27308:22:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25299, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "27308:24:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25300, - "nodeType": "RevertStatement", - "src": "27301:31:29" - } - ] - }, - "errorName": "", - "id": 25302, - "nodeType": "TryCatchClause", - "src": "27117:226:29" - } - ], - "externalCall": { - "arguments": [ - { - "components": [ - { - "baseExpression": { - "id": 25228, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26047:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25230, - "indexExpression": { - "hexValue": "30", - "id": 25229, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26059:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26047:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25231, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26063:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25233, - "indexExpression": { - "hexValue": "31", - "id": 25232, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26075:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_1_by_1", - "typeString": "int_const 1" - }, - "value": "1" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26063:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25234, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "26046:32:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - }, - { - "components": [ - { - "components": [ - { - "baseExpression": { - "id": 25235, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26094:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25237, - "indexExpression": { - "hexValue": "32", - "id": 25236, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26106:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_2_by_1", - "typeString": "int_const 2" - }, - "value": "2" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26094:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25238, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26110:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25240, - "indexExpression": { - "hexValue": "33", - "id": 25239, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26122:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_3_by_1", - "typeString": "int_const 3" - }, - "value": "3" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26110:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25241, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "26093:32:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - }, - { - "components": [ - { - "baseExpression": { - "id": 25242, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26128:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25244, - "indexExpression": { - "hexValue": "34", - "id": 25243, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26140:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_4_by_1", - "typeString": "int_const 4" - }, - "value": "4" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26128:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25245, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26144:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25247, - "indexExpression": { - "hexValue": "35", - "id": 25246, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26156:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_5_by_1", - "typeString": "int_const 5" - }, - "value": "5" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26144:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25248, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "26127:32:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - } - ], - "id": 25249, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "26092:68:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", - "typeString": "uint256[2] memory[2] memory" - } - }, - { - "components": [ - { - "baseExpression": { - "id": 25250, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26175:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25252, - "indexExpression": { - "hexValue": "36", - "id": 25251, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26187:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_6_by_1", - "typeString": "int_const 6" - }, - "value": "6" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26175:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "baseExpression": { - "id": 25253, - "name": "updateProof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25145, - "src": "26191:11:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - "id": 25255, - "indexExpression": { - "hexValue": "37", - "id": 25254, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "26203:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_7_by_1", - "typeString": "int_const 7" - }, - "value": "7" - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "26191:14:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25256, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "26174:32:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - } - }, - { - "components": [ - { - "id": 25257, - "name": "reducedInputHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25209, - "src": "26221:16:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25258, - "isConstant": false, - "isInlineArray": true, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "26220:18:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", - "typeString": "uint256[1] memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - }, - { - "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", - "typeString": "uint256[2] memory[2] memory" - }, - { - "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", - "typeString": "uint256[2] memory" - }, - { - "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", - "typeString": "uint256[1] memory" - } - ], - "expression": { - "id": 25226, - "name": "updateVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25219, - "src": "26006:14:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ITreeVerifier_$26728", - "typeString": "contract ITreeVerifier" - } - }, - "id": 25227, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "26021:11:29", - "memberName": "verifyProof", - "nodeType": "MemberAccess", - "referencedDeclaration": 26727, - "src": "26006:26:29", - "typeDescriptions": { - "typeIdentifier": "t_function_external_nonpayable$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr_$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_uint256_$1_memory_ptr_$returns$_t_bool_$", - "typeString": "function (uint256[2] memory,uint256[2] memory[2] memory,uint256[2] memory,uint256[1] memory) external returns (bool)" - } - }, - "id": 25259, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "26006:242:29", - "tryCall": true, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25303, - "nodeType": "TryStatement", - "src": "26002:1341:29" - } - ] - }, - "documentation": { - "id": 25141, - "nodeType": "StructuredDocumentation", - "src": "23330:1065:29", - "text": "@param updatedIdentities The identities that were updated in the tree. As they each hold\n their own leaf index, these need not be contiguous. All of the commitments must be\n elements of the field `Kr`.\n @param postRoot The root obtained after removing all of `removedIdentities` from the tree\n described by `preRoot`. Must be an element of the field `Kr`.\n @custom:reverts Unauthorized If the message sender is not authorised to update identities.\n @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root.\n @custom:reverts ProofValidationFailure If `removalProof` cannot be verified using the\n provided inputs.\n @custom:reverts UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not\n an element of the field `Kr`. It describes the type and value of the\n unreduced element.\n @custom:reverts NoSuchVerifier If the batch sizes doesn't match a known verifier." - }, - "functionSelector": "4bc511e6", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25156, - "kind": "modifierInvocation", - "modifierName": { - "id": 25155, - "name": "onlyProxy", - "nameLocations": [ - "24592:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "24592:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "24592:9:29" - }, - { - "id": 25158, - "kind": "modifierInvocation", - "modifierName": { - "id": 25157, - "name": "onlyInitialized", - "nameLocations": [ - "24602:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "24602:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "24602:15:29" - }, - { - "id": 25160, - "kind": "modifierInvocation", - "modifierName": { - "id": 25159, - "name": "onlyOwner", - "nameLocations": [ - "24618:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "24618:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "24618:9:29" - } - ], - "name": "updateIdentities", - "nameLocation": "24409:16:29", - "parameters": { - "id": 25154, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25145, - "mutability": "mutable", - "name": "updateProof", - "nameLocation": "24455:11:29", - "nodeType": "VariableDeclaration", - "scope": 25305, - "src": "24435:31:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8]" - }, - "typeName": { - "baseType": { - "id": 25142, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "24435:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25144, - "length": { - "hexValue": "38", - "id": 25143, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "24443:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_8_by_1", - "typeString": "int_const 8" - }, - "value": "8" - }, - "nodeType": "ArrayTypeName", - "src": "24435:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_storage_ptr", - "typeString": "uint256[8]" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25147, - "mutability": "mutable", - "name": "preRoot", - "nameLocation": "24484:7:29", - "nodeType": "VariableDeclaration", - "scope": 25305, - "src": "24476:15:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25146, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "24476:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25151, - "mutability": "mutable", - "name": "updatedIdentities", - "nameLocation": "24527:17:29", - "nodeType": "VariableDeclaration", - "scope": 25305, - "src": "24501:43:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - }, - "typeName": { - "baseType": { - "id": 25149, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25148, - "name": "IdentityUpdate", - "nameLocations": [ - "24501:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "24501:14:29" - }, - "referencedDeclaration": 24775, - "src": "24501:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "id": 25150, - "nodeType": "ArrayTypeName", - "src": "24501:16:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_storage_$dyn_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25153, - "mutability": "mutable", - "name": "postRoot", - "nameLocation": "24562:8:29", - "nodeType": "VariableDeclaration", - "scope": 25305, - "src": "24554:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25152, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "24554:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "24425:151:29" - }, - "returnParameters": { - "id": 25161, - "nodeType": "ParameterList", - "parameters": [], - "src": "24628:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25341, - "nodeType": "FunctionDefinition", - "src": "28480:413:29", - "nodes": [], - "body": { - "id": 25340, - "nodeType": "Block", - "src": "28729:164:29", - "nodes": [], - "statements": [ - { - "assignments": [ - 25325 - ], - "declarations": [ - { - "constant": false, - "id": 25325, - "mutability": "mutable", - "name": "bytesToHash", - "nameLocation": "28752:11:29", - "nodeType": "VariableDeclaration", - "scope": 25340, - "src": "28739:24:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes" - }, - "typeName": { - "id": 25324, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "28739:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - }, - "visibility": "internal" - } - ], - "id": 25333, - "initialValue": { - "arguments": [ - { - "id": 25328, - "name": "startIndex", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25308, - "src": "28795:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - } - }, - { - "id": 25329, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25310, - "src": "28807:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25330, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25312, - "src": "28816:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25331, - "name": "identityCommitments", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25315, - "src": "28826:19:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - ], - "expression": { - "id": 25326, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -1, - "src": "28778:3:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 25327, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "28782:12:29", - "memberName": "encodePacked", - "nodeType": "MemberAccess", - "src": "28778:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", - "typeString": "function () pure returns (bytes memory)" - } - }, - "id": 25332, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "28778:68:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "28739:107:29" - }, - { - "expression": { - "id": 25338, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25334, - "name": "hash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25322, - "src": "28857:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "arguments": [ - { - "id": 25336, - "name": "bytesToHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25325, - "src": "28874:11:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "id": 25335, - "name": "keccak256", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -8, - "src": "28864:9:29", - "typeDescriptions": { - "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", - "typeString": "function (bytes memory) pure returns (bytes32)" - } - }, - "id": 25337, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "28864:22:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "src": "28857:29:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "id": 25339, - "nodeType": "ExpressionStatement", - "src": "28857:29:29" - } - ] - }, - "documentation": { - "id": 25306, - "nodeType": "StructuredDocumentation", - "src": "27608:867:29", - "text": "@notice Calculates the input hash for the identity registration verifier.\n @dev Implements the computation described below.\n @param startIndex The index in the tree from which inserting started.\n @param preRoot The root value of the tree before these insertions were made.\n @param postRoot The root value of the tree after these insertsions were made.\n @param identityCommitments The identities that were added to the tree to produce `postRoot`.\n @return hash The input hash calculated as described below.\n We keccak hash all input to save verification gas. Inputs are arranged as follows:\n StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1]\n 32\t || 256 || 256 || 256 || 256 || ... || 256 bits" - }, - "functionSelector": "8c76a909", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25318, - "kind": "modifierInvocation", - "modifierName": { - "id": 25317, - "name": "onlyProxy", - "nameLocations": [ - "28680:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "28680:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "28680:9:29" - }, - { - "id": 25320, - "kind": "modifierInvocation", - "modifierName": { - "id": 25319, - "name": "onlyInitialized", - "nameLocations": [ - "28690:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "28690:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "28690:15:29" - } - ], - "name": "calculateIdentityRegistrationInputHash", - "nameLocation": "28489:38:29", - "parameters": { - "id": 25316, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25308, - "mutability": "mutable", - "name": "startIndex", - "nameLocation": "28544:10:29", - "nodeType": "VariableDeclaration", - "scope": 25341, - "src": "28537:17:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - }, - "typeName": { - "id": 25307, - "name": "uint32", - "nodeType": "ElementaryTypeName", - "src": "28537:6:29", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25310, - "mutability": "mutable", - "name": "preRoot", - "nameLocation": "28572:7:29", - "nodeType": "VariableDeclaration", - "scope": 25341, - "src": "28564:15:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25309, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "28564:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25312, - "mutability": "mutable", - "name": "postRoot", - "nameLocation": "28597:8:29", - "nodeType": "VariableDeclaration", - "scope": 25341, - "src": "28589:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25311, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "28589:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25315, - "mutability": "mutable", - "name": "identityCommitments", - "nameLocation": "28634:19:29", - "nodeType": "VariableDeclaration", - "scope": 25341, - "src": "28615:38:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[]" - }, - "typeName": { - "baseType": { - "id": 25313, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "28615:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25314, - "nodeType": "ArrayTypeName", - "src": "28615:9:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", - "typeString": "uint256[]" - } - }, - "visibility": "internal" - } - ], - "src": "28527:132:29" - }, - "returnParameters": { - "id": 25323, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25322, - "mutability": "mutable", - "name": "hash", - "nameLocation": "28723:4:29", - "nodeType": "VariableDeclaration", - "scope": 25341, - "src": "28715:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - }, - "typeName": { - "id": 25321, - "name": "bytes32", - "nodeType": "ElementaryTypeName", - "src": "28715:7:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "visibility": "internal" - } - ], - "src": "28714:14:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25423, - "nodeType": "FunctionDefinition", - "src": "29877:720:29", - "nodes": [], - "body": { - "id": 25422, - "nodeType": "Block", - "src": "30091:506:29", - "nodes": [], - "statements": [ - { - "assignments": [ - 25360 - ], - "declarations": [ - { - "constant": false, - "id": 25360, - "mutability": "mutable", - "name": "identityBytes", - "nameLocation": "30114:13:29", - "nodeType": "VariableDeclaration", - "scope": 25422, - "src": "30101:26:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes" - }, - "typeName": { - "id": 25359, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "30101:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - }, - "visibility": "internal" - } - ], - "id": 25365, - "initialValue": { - "arguments": [ - { - "hexValue": "30", - "id": 25363, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "30140:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - } - ], - "id": 25362, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "NewExpression", - "src": "30130:9:29", - "typeDescriptions": { - "typeIdentifier": "t_function_objectcreation_pure$_t_uint256_$returns$_t_bytes_memory_ptr_$", - "typeString": "function (uint256) pure returns (bytes memory)" - }, - "typeName": { - "id": 25361, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "30134:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - } - }, - "id": 25364, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "30130:12:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "30101:41:29" - }, - { - "body": { - "id": 25405, - "nodeType": "Block", - "src": "30200:264:29", - "statements": [ - { - "assignments": [ - 25379 - ], - "declarations": [ - { - "constant": false, - "id": 25379, - "mutability": "mutable", - "name": "ident", - "nameLocation": "30236:5:29", - "nodeType": "VariableDeclaration", - "scope": 25405, - "src": "30214:27:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - }, - "typeName": { - "id": 25378, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25377, - "name": "IdentityUpdate", - "nameLocations": [ - "30214:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "30214:14:29" - }, - "referencedDeclaration": 24775, - "src": "30214:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "visibility": "internal" - } - ], - "id": 25383, - "initialValue": { - "baseExpression": { - "id": 25380, - "name": "identities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25350, - "src": "30244:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25382, - "indexExpression": { - "id": 25381, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25367, - "src": "30255:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "30244:13:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "30214:43:29" - }, - { - "assignments": [ - 25385 - ], - "declarations": [ - { - "constant": false, - "id": 25385, - "mutability": "mutable", - "name": "newBytes", - "nameLocation": "30284:8:29", - "nodeType": "VariableDeclaration", - "scope": 25405, - "src": "30271:21:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes" - }, - "typeName": { - "id": 25384, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "30271:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - }, - "visibility": "internal" - } - ], - "id": 25395, - "initialValue": { - "arguments": [ - { - "expression": { - "id": 25388, - "name": "ident", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25379, - "src": "30328:5:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25389, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "30334:9:29", - "memberName": "leafIndex", - "nodeType": "MemberAccess", - "referencedDeclaration": 24770, - "src": "30328:15:29", - "typeDescriptions": { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - } - }, - { - "expression": { - "id": 25390, - "name": "ident", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25379, - "src": "30345:5:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25391, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "30351:13:29", - "memberName": "oldCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24772, - "src": "30345:19:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "expression": { - "id": 25392, - "name": "ident", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25379, - "src": "30366:5:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25393, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "30372:13:29", - "memberName": "newCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24774, - "src": "30366:19:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint32", - "typeString": "uint32" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "expression": { - "id": 25386, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -1, - "src": "30311:3:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 25387, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "30315:12:29", - "memberName": "encodePacked", - "nodeType": "MemberAccess", - "src": "30311:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", - "typeString": "function () pure returns (bytes memory)" - } - }, - "id": 25394, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "30311:75:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "30271:115:29" - }, - { - "expression": { - "id": 25403, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25396, - "name": "identityBytes", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25360, - "src": "30400:13:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "arguments": [ - { - "id": 25400, - "name": "identityBytes", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25360, - "src": "30429:13:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - { - "id": 25401, - "name": "newBytes", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25385, - "src": "30444:8:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - }, - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "expression": { - "id": 25398, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "30416:5:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_bytes_storage_ptr_$", - "typeString": "type(bytes storage pointer)" - }, - "typeName": { - "id": 25397, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "30416:5:29", - "typeDescriptions": {} - } - }, - "id": 25399, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "30422:6:29", - "memberName": "concat", - "nodeType": "MemberAccess", - "src": "30416:12:29", - "typeDescriptions": { - "typeIdentifier": "t_function_bytesconcat_pure$__$returns$_t_bytes_memory_ptr_$", - "typeString": "function () pure returns (bytes memory)" - } - }, - "id": 25402, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "30416:37:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "src": "30400:53:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "id": 25404, - "nodeType": "ExpressionStatement", - "src": "30400:53:29" - } - ] - }, - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25373, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25370, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25367, - "src": "30172:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "<", - "rightExpression": { - "expression": { - "id": 25371, - "name": "identities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25350, - "src": "30176:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25372, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "30187:6:29", - "memberName": "length", - "nodeType": "MemberAccess", - "src": "30176:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "30172:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25406, - "initializationExpression": { - "assignments": [ - 25367 - ], - "declarations": [ - { - "constant": false, - "id": 25367, - "mutability": "mutable", - "name": "i", - "nameLocation": "30165:1:29", - "nodeType": "VariableDeclaration", - "scope": 25406, - "src": "30157:9:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25366, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "30157:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25369, - "initialValue": { - "hexValue": "30", - "id": 25368, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "30169:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "nodeType": "VariableDeclarationStatement", - "src": "30157:13:29" - }, - "loopExpression": { - "expression": { - "id": 25375, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "++", - "prefix": true, - "src": "30195:3:29", - "subExpression": { - "id": 25374, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25367, - "src": "30197:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25376, - "nodeType": "ExpressionStatement", - "src": "30195:3:29" - }, - "nodeType": "ForStatement", - "src": "30152:312:29" - }, - { - "assignments": [ - 25408 - ], - "declarations": [ - { - "constant": false, - "id": 25408, - "mutability": "mutable", - "name": "bytesToHash", - "nameLocation": "30486:11:29", - "nodeType": "VariableDeclaration", - "scope": 25422, - "src": "30473:24:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes" - }, - "typeName": { - "id": 25407, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "30473:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - }, - "visibility": "internal" - } - ], - "id": 25415, - "initialValue": { - "arguments": [ - { - "id": 25411, - "name": "preRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25344, - "src": "30517:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25412, - "name": "postRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25346, - "src": "30526:8:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25413, - "name": "identityBytes", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25360, - "src": "30536:13:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "expression": { - "id": 25409, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -1, - "src": "30500:3:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 25410, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "30504:12:29", - "memberName": "encodePacked", - "nodeType": "MemberAccess", - "src": "30500:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", - "typeString": "function () pure returns (bytes memory)" - } - }, - "id": 25414, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "30500:50:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "30473:77:29" - }, - { - "expression": { - "id": 25420, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25416, - "name": "hash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25357, - "src": "30561:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "arguments": [ - { - "id": 25418, - "name": "bytesToHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25408, - "src": "30578:11:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "id": 25417, - "name": "keccak256", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -8, - "src": "30568:9:29", - "typeDescriptions": { - "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", - "typeString": "function (bytes memory) pure returns (bytes32)" - } - }, - "id": 25419, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "30568:22:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "src": "30561:29:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "id": 25421, - "nodeType": "ExpressionStatement", - "src": "30561:29:29" - } - ] - }, - "documentation": { - "id": 25342, - "nodeType": "StructuredDocumentation", - "src": "28899:973:29", - "text": "@notice Calculates the input hash for the identity update verifier.\n @dev Implements the computation described below.\n @param preRoot The root value of the tree before the updates were made.\n @param postRoot The root value of the tree after the udpates were made.\n @param identities The identity structures providing the identity data.\n @return hash The input hash calculated as described below.\n We keccak hash all input to save verification gas. The inputs are arranged as follows:\n preRoot || postRoot || id[0].leafIndex || id[0].oldCommitment || id[0].newCommitment || ... || id[n].leafIndex || id[n].oldCommitment || id[n].newCommitment\n 256 || 256 || 32 || 256 || 256 || ... || 32 || 256 || 256\n where:\n - `id[n] == identities[n]`\n - `n == batchSize - 1`" - }, - "functionSelector": "09edcb9c", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25353, - "kind": "modifierInvocation", - "modifierName": { - "id": 25352, - "name": "onlyProxy", - "nameLocations": [ - "30042:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "30042:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "30042:9:29" - }, - { - "id": 25355, - "kind": "modifierInvocation", - "modifierName": { - "id": 25354, - "name": "onlyInitialized", - "nameLocations": [ - "30052:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "30052:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "30052:15:29" - } - ], - "name": "calculateIdentityUpdateInputHash", - "nameLocation": "29886:32:29", - "parameters": { - "id": 25351, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25344, - "mutability": "mutable", - "name": "preRoot", - "nameLocation": "29936:7:29", - "nodeType": "VariableDeclaration", - "scope": 25423, - "src": "29928:15:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25343, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "29928:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25346, - "mutability": "mutable", - "name": "postRoot", - "nameLocation": "29961:8:29", - "nodeType": "VariableDeclaration", - "scope": 25423, - "src": "29953:16:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25345, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "29953:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 25350, - "mutability": "mutable", - "name": "identities", - "nameLocation": "30005:10:29", - "nodeType": "VariableDeclaration", - "scope": 25423, - "src": "29979:36:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - }, - "typeName": { - "baseType": { - "id": 25348, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25347, - "name": "IdentityUpdate", - "nameLocations": [ - "29979:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "29979:14:29" - }, - "referencedDeclaration": 24775, - "src": "29979:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "id": 25349, - "nodeType": "ArrayTypeName", - "src": "29979:16:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_storage_$dyn_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - } - }, - "visibility": "internal" - } - ], - "src": "29918:103:29" - }, - "returnParameters": { - "id": 25358, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25357, - "mutability": "mutable", - "name": "hash", - "nameLocation": "30085:4:29", - "nodeType": "VariableDeclaration", - "scope": 25423, - "src": "30077:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - }, - "typeName": { - "id": 25356, - "name": "bytes32", - "nodeType": "ElementaryTypeName", - "src": "30077:7:29", - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "visibility": "internal" - } - ], - "src": "30076:14:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25436, - "nodeType": "FunctionDefinition", - "src": "30725:126:29", - "nodes": [], - "body": { - "id": 25435, - "nodeType": "Block", - "src": "30816:35:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 25433, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "30833:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "functionReturnParameters": 25432, - "id": 25434, - "nodeType": "Return", - "src": "30826:18:29" - } - ] - }, - "documentation": { - "id": 25424, - "nodeType": "StructuredDocumentation", - "src": "30603:117:29", - "text": "@notice Allows a caller to query the latest root.\n @return root The value of the latest tree root." - }, - "functionSelector": "d7b0fef1", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25427, - "kind": "modifierInvocation", - "modifierName": { - "id": 25426, - "name": "onlyProxy", - "nameLocations": [ - "30767:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "30767:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "30767:9:29" - }, - { - "id": 25429, - "kind": "modifierInvocation", - "modifierName": { - "id": 25428, - "name": "onlyInitialized", - "nameLocations": [ - "30777:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "30777:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "30777:15:29" - } - ], - "name": "latestRoot", - "nameLocation": "30734:10:29", - "parameters": { - "id": 25425, - "nodeType": "ParameterList", - "parameters": [], - "src": "30744:2:29" - }, - "returnParameters": { - "id": 25432, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25431, - "mutability": "mutable", - "name": "root", - "nameLocation": "30810:4:29", - "nodeType": "VariableDeclaration", - "scope": 25436, - "src": "30802:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25430, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "30802:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "30801:14:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25472, - "nodeType": "FunctionDefinition", - "src": "31001:498:29", - "nodes": [], - "body": { - "id": 25471, - "nodeType": "Block", - "src": "31077:422:29", - "nodes": [], - "statements": [ - { - "condition": { - "commonType": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "id": 25451, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25444, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "31091:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "BinaryOperation", - "operator": "&&", - "rightExpression": { - "commonType": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "id": 25450, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25445, - "name": "_stateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24755, - "src": "31116:24:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "arguments": [ - { - "hexValue": "30", - "id": 25448, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "31152:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - } - ], - "id": 25447, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "31144:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 25446, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "31144:7:29", - "typeDescriptions": {} - } - }, - "id": 25449, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "31144:10:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "31116:38:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "src": "31091:63:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25470, - "nodeType": "IfStatement", - "src": "31087:406:29", - "trueBody": { - "id": 25469, - "nodeType": "Block", - "src": "31156:337:29", - "statements": [ - { - "assignments": [ - 25453, - null - ], - "declarations": [ - { - "constant": false, - "id": 25453, - "mutability": "mutable", - "name": "success", - "nameLocation": "31176:7:29", - "nodeType": "VariableDeclaration", - "scope": 25469, - "src": "31171:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25452, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "31171:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - }, - null - ], - "id": 25462, - "initialValue": { - "arguments": [ - { - "arguments": [ - { - "hexValue": "73656e64526f6f744d756c7469636861696e2875696e7432353629", - "id": 25458, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "31259:29:29", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_393170cfb505ae74021b4d876fa7c0db8583f806f8b98b118b452a068d301872", - "typeString": "literal_string \"sendRootMultichain(uint256)\"" - }, - "value": "sendRootMultichain(uint256)" - }, - { - "id": 25459, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "31290:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_stringliteral_393170cfb505ae74021b4d876fa7c0db8583f806f8b98b118b452a068d301872", - "typeString": "literal_string \"sendRootMultichain(uint256)\"" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "expression": { - "id": 25456, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -1, - "src": "31235:3:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 25457, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "31239:19:29", - "memberName": "encodeWithSignature", - "nodeType": "MemberAccess", - "src": "31235:23:29", - "typeDescriptions": { - "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", - "typeString": "function (string memory) pure returns (bytes memory)" - } - }, - "id": 25460, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "31235:67:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "expression": { - "id": 25454, - "name": "_stateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24755, - "src": "31188:24:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "id": 25455, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "31213:4:29", - "memberName": "call", - "nodeType": "MemberAccess", - "src": "31188:29:29", - "typeDescriptions": { - "typeIdentifier": "t_function_barecall_payable$_t_bytes_memory_ptr_$returns$_t_bool_$_t_bytes_memory_ptr_$", - "typeString": "function (bytes memory) payable returns (bool,bytes memory)" - } - }, - "id": 25461, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "31188:128:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$_t_bool_$_t_bytes_memory_ptr_$", - "typeString": "tuple(bool,bytes memory)" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "31170:146:29" - }, - { - "condition": { - "id": 25464, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "31422:8:29", - "subExpression": { - "id": 25463, - "name": "success", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25453, - "src": "31423:7:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25468, - "nodeType": "IfStatement", - "src": "31418:64:29", - "trueBody": { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25465, - "name": "StateBridgeProxySendRootMultichainFailure", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24830, - "src": "31439:41:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25466, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "31439:43:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25467, - "nodeType": "RevertStatement", - "src": "31432:50:29" - } - } - ] - } - } - ] - }, - "documentation": { - "id": 25437, - "nodeType": "StructuredDocumentation", - "src": "30857:139:29", - "text": "@notice Sends the latest root to the state bridge.\n @dev Only sends if the state bridge address is not the zero address." - }, - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25440, - "kind": "modifierInvocation", - "modifierName": { - "id": 25439, - "name": "onlyProxy", - "nameLocations": [ - "31051:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "31051:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "31051:9:29" - }, - { - "id": 25442, - "kind": "modifierInvocation", - "modifierName": { - "id": 25441, - "name": "onlyInitialized", - "nameLocations": [ - "31061:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "31061:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "31061:15:29" - } - ], - "name": "sendRootToStateBridge", - "nameLocation": "31010:21:29", - "parameters": { - "id": 25438, - "nodeType": "ParameterList", - "parameters": [], - "src": "31031:2:29" - }, - "returnParameters": { - "id": 25443, - "nodeType": "ParameterList", - "parameters": [], - "src": "31077:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "internal" - }, - { - "id": 25485, - "nodeType": "FunctionDefinition", - "src": "31672:205:29", - "nodes": [], - "body": { - "id": 25484, - "nodeType": "Block", - "src": "31829:48:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 25482, - "name": "_stateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24755, - "src": "31846:24:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "functionReturnParameters": 25481, - "id": 25483, - "nodeType": "Return", - "src": "31839:31:29" - } - ] - }, - "documentation": { - "id": 25473, - "nodeType": "StructuredDocumentation", - "src": "31505:162:29", - "text": "@notice Allows a caller to query the address of the current stateBridgeProxy.\n @return proxy The address of the currently used stateBridgeProxy" - }, - "functionSelector": "b6621a3d", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25476, - "kind": "modifierInvocation", - "modifierName": { - "id": 25475, - "name": "onlyProxy", - "nameLocations": [ - "31759:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "31759:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "31759:9:29" - }, - { - "id": 25478, - "kind": "modifierInvocation", - "modifierName": { - "id": 25477, - "name": "onlyInitialized", - "nameLocations": [ - "31777:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "31777:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "31777:15:29" - } - ], - "name": "stateBridgeProxyAddress", - "nameLocation": "31681:23:29", - "parameters": { - "id": 25474, - "nodeType": "ParameterList", - "parameters": [], - "src": "31704:2:29" - }, - "returnParameters": { - "id": 25481, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25480, - "mutability": "mutable", - "name": "proxy", - "nameLocation": "31818:5:29", - "nodeType": "VariableDeclaration", - "scope": 25485, - "src": "31810:13:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 25479, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "31810:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "31809:15:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25520, - "nodeType": "FunctionDefinition", - "src": "32106:439:29", - "nodes": [], - "body": { - "id": 25519, - "nodeType": "Block", - "src": "32273:272:29", - "nodes": [], - "statements": [ - { - "condition": { - "commonType": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "id": 25502, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25497, - "name": "newStateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25488, - "src": "32287:26:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "arguments": [ - { - "hexValue": "30", - "id": 25500, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "32325:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - } - ], - "id": 25499, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "32317:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 25498, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "32317:7:29", - "typeDescriptions": {} - } - }, - "id": 25501, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "32317:10:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "32287:40:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25507, - "nodeType": "IfStatement", - "src": "32283:110:29", - "trueBody": { - "id": 25506, - "nodeType": "Block", - "src": "32329:64:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25503, - "name": "InvalidStateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24839, - "src": "32350:30:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25504, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "32350:32:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25505, - "nodeType": "RevertStatement", - "src": "32343:39:29" - } - ] - } - }, - { - "condition": { - "id": 25509, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "32407:22:29", - "subExpression": { - "id": 25508, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "32408:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25514, - "nodeType": "IfStatement", - "src": "32403:72:29", - "trueBody": { - "id": 25513, - "nodeType": "Block", - "src": "32431:44:29", - "statements": [ - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25510, - "name": "enableStateBridge", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25543, - "src": "32445:17:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", - "typeString": "function ()" - } - }, - "id": 25511, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "32445:19:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25512, - "nodeType": "ExpressionStatement", - "src": "32445:19:29" - } - ] - } - }, - { - "expression": { - "id": 25517, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25515, - "name": "_stateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24755, - "src": "32485:24:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25516, - "name": "newStateBridgeProxyAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25488, - "src": "32512:26:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "32485:53:29", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "id": 25518, - "nodeType": "ExpressionStatement", - "src": "32485:53:29" - } - ] - }, - "documentation": { - "id": 25486, - "nodeType": "StructuredDocumentation", - "src": "31883:218:29", - "text": "@notice Allows a caller to upgrade the stateBridgeProxy.\n @dev Only the owner of the contract can call this function.\n @param newStateBridgeProxyAddress The address of the new stateBridgeProxy" - }, - "functionSelector": "8939472e", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25491, - "kind": "modifierInvocation", - "modifierName": { - "id": 25490, - "name": "onlyProxy", - "nameLocations": [ - "32217:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "32217:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "32217:9:29" - }, - { - "id": 25493, - "kind": "modifierInvocation", - "modifierName": { - "id": 25492, - "name": "onlyInitialized", - "nameLocations": [ - "32235:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "32235:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "32235:15:29" - }, - { - "id": 25495, - "kind": "modifierInvocation", - "modifierName": { - "id": 25494, - "name": "onlyOwner", - "nameLocations": [ - "32259:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "32259:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "32259:9:29" - } - ], - "name": "setStateBridgeProxyAddress", - "nameLocation": "32115:26:29", - "parameters": { - "id": 25489, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25488, - "mutability": "mutable", - "name": "newStateBridgeProxyAddress", - "nameLocation": "32150:26:29", - "nodeType": "VariableDeclaration", - "scope": 25520, - "src": "32142:34:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 25487, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "32142:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "32141:36:29" - }, - "returnParameters": { - "id": 25496, - "nodeType": "ParameterList", - "parameters": [], - "src": "32273:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25543, - "nodeType": "FunctionDefinition", - "src": "32661:242:29", - "nodes": [], - "body": { - "id": 25542, - "nodeType": "Block", - "src": "32741:162:29", - "nodes": [], - "statements": [ - { - "condition": { - "id": 25531, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "32755:22:29", - "subExpression": { - "id": 25530, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "32756:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "falseBody": { - "id": 25540, - "nodeType": "Block", - "src": "32838:59:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25537, - "name": "StateBridgeAlreadyEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24833, - "src": "32859:25:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25538, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "32859:27:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25539, - "nodeType": "RevertStatement", - "src": "32852:34:29" - } - ] - }, - "id": 25541, - "nodeType": "IfStatement", - "src": "32751:146:29", - "trueBody": { - "id": 25536, - "nodeType": "Block", - "src": "32779:53:29", - "statements": [ - { - "expression": { - "id": 25534, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25532, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "32793:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "hexValue": "74727565", - "id": 25533, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "bool", - "lValueRequested": false, - "nodeType": "Literal", - "src": "32817:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "value": "true" - }, - "src": "32793:28:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25535, - "nodeType": "ExpressionStatement", - "src": "32793:28:29" - } - ] - } - } - ] - }, - "documentation": { - "id": 25521, - "nodeType": "StructuredDocumentation", - "src": "32551:105:29", - "text": "@notice Enables the state bridge.\n @dev Only the owner of the contract can call this function." - }, - "functionSelector": "61ea6a8d", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25524, - "kind": "modifierInvocation", - "modifierName": { - "id": 25523, - "name": "onlyProxy", - "nameLocations": [ - "32705:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "32705:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "32705:9:29" - }, - { - "id": 25526, - "kind": "modifierInvocation", - "modifierName": { - "id": 25525, - "name": "onlyInitialized", - "nameLocations": [ - "32715:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "32715:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "32715:15:29" - }, - { - "id": 25528, - "kind": "modifierInvocation", - "modifierName": { - "id": 25527, - "name": "onlyOwner", - "nameLocations": [ - "32731:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "32731:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "32731:9:29" - } - ], - "name": "enableStateBridge", - "nameLocation": "32670:17:29", - "parameters": { - "id": 25522, - "nodeType": "ParameterList", - "parameters": [], - "src": "32687:2:29" - }, - "returnParameters": { - "id": 25529, - "nodeType": "ParameterList", - "parameters": [], - "src": "32741:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25565, - "nodeType": "FunctionDefinition", - "src": "33020:244:29", - "nodes": [], - "body": { - "id": 25564, - "nodeType": "Block", - "src": "33101:163:29", - "nodes": [], - "statements": [ - { - "condition": { - "id": 25553, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "33115:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "falseBody": { - "id": 25562, - "nodeType": "Block", - "src": "33198:60:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25559, - "name": "StateBridgeAlreadyDisabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24836, - "src": "33219:26:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25560, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "33219:28:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25561, - "nodeType": "RevertStatement", - "src": "33212:35:29" - } - ] - }, - "id": 25563, - "nodeType": "IfStatement", - "src": "33111:147:29", - "trueBody": { - "id": 25558, - "nodeType": "Block", - "src": "33138:54:29", - "statements": [ - { - "expression": { - "id": 25556, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25554, - "name": "_isStateBridgeEnabled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24758, - "src": "33152:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "hexValue": "66616c7365", - "id": 25555, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "bool", - "lValueRequested": false, - "nodeType": "Literal", - "src": "33176:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "value": "false" - }, - "src": "33152:29:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25557, - "nodeType": "ExpressionStatement", - "src": "33152:29:29" - } - ] - } - } - ] - }, - "documentation": { - "id": 25544, - "nodeType": "StructuredDocumentation", - "src": "32909:106:29", - "text": "@notice Disables the state bridge.\n @dev Only the owner of the contract can call this function." - }, - "functionSelector": "a26b810e", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25547, - "kind": "modifierInvocation", - "modifierName": { - "id": 25546, - "name": "onlyProxy", - "nameLocations": [ - "33065:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "33065:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "33065:9:29" - }, - { - "id": 25549, - "kind": "modifierInvocation", - "modifierName": { - "id": 25548, - "name": "onlyInitialized", - "nameLocations": [ - "33075:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "33075:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "33075:15:29" - }, - { - "id": 25551, - "kind": "modifierInvocation", - "modifierName": { - "id": 25550, - "name": "onlyOwner", - "nameLocations": [ - "33091:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "33091:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "33091:9:29" - } - ], - "name": "disableStateBridge", - "nameLocation": "33029:18:29", - "parameters": { - "id": 25545, - "nodeType": "ParameterList", - "parameters": [], - "src": "33047:2:29" - }, - "returnParameters": { - "id": 25552, - "nodeType": "ParameterList", - "parameters": [], - "src": "33101:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25622, - "nodeType": "FunctionDefinition", - "src": "33760:576:29", - "nodes": [], - "body": { - "id": 25621, - "nodeType": "Block", - "src": "33926:410:29", - "nodes": [], - "statements": [ - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25580, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25578, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25568, - "src": "33940:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "id": 25579, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "33948:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "33940:19:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "falseBody": { - "id": 25619, - "nodeType": "Block", - "src": "34029:301:29", - "statements": [ - { - "assignments": [ - 25589 - ], - "declarations": [ - { - "constant": false, - "id": 25589, - "mutability": "mutable", - "name": "rootTimestamp", - "nameLocation": "34051:13:29", - "nodeType": "VariableDeclaration", - "scope": 25619, - "src": "34043:21:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - }, - "typeName": { - "id": 25588, - "name": "uint128", - "nodeType": "ElementaryTypeName", - "src": "34043:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "visibility": "internal" - } - ], - "id": 25593, - "initialValue": { - "baseExpression": { - "id": 25590, - "name": "rootHistory", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24726, - "src": "34067:11:29", - "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", - "typeString": "mapping(uint256 => uint128)" - } - }, - "id": 25592, - "indexExpression": { - "id": 25591, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25568, - "src": "34079:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "34067:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "34043:41:29" - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - }, - "id": 25596, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25594, - "name": "rootTimestamp", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25589, - "src": "34103:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "hexValue": "30", - "id": 25595, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "34120:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "src": "34103:18:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25601, - "nodeType": "IfStatement", - "src": "34099:78:29", - "trueBody": { - "id": 25600, - "nodeType": "Block", - "src": "34123:54:29", - "statements": [ - { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25597, - "name": "NO_SUCH_ROOT", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24793, - "src": "34148:12:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_RootInfo_$24768_memory_ptr_$", - "typeString": "function () pure returns (struct WorldIDIdentityManagerImplV1.RootInfo memory)" - } - }, - "id": 25598, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "34148:14:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo memory" - } - }, - "functionReturnParameters": 25577, - "id": 25599, - "nodeType": "Return", - "src": "34141:21:29" - } - ] - } - }, - { - "assignments": [ - 25603 - ], - "declarations": [ - { - "constant": false, - "id": 25603, - "mutability": "mutable", - "name": "isValid", - "nameLocation": "34196:7:29", - "nodeType": "VariableDeclaration", - "scope": 25619, - "src": "34191:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25602, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "34191:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "id": 25612, - "initialValue": { - "id": 25611, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "34206:54:29", - "subExpression": { - "components": [ - { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25609, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25607, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "expression": { - "id": 25604, - "name": "block", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -4, - "src": "34208:5:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_block", - "typeString": "block" - } - }, - "id": 25605, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "34214:9:29", - "memberName": "timestamp", - "nodeType": "MemberAccess", - "src": "34208:15:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "-", - "rightExpression": { - "id": 25606, - "name": "rootTimestamp", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25589, - "src": "34226:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "src": "34208:31:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": ">", - "rightExpression": { - "id": 25608, - "name": "rootHistoryExpiry", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24729, - "src": "34242:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "34208:51:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - } - ], - "id": 25610, - "isConstant": false, - "isInlineArray": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "34207:53:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "34191:69:29" - }, - { - "expression": { - "arguments": [ - { - "id": 25614, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25568, - "src": "34290:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 25615, - "name": "rootTimestamp", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25589, - "src": "34296:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - { - "id": 25616, - "name": "isValid", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25603, - "src": "34311:7:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - }, - { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - ], - "id": 25613, - "name": "RootInfo", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24768, - "src": "34281:8:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_struct$_RootInfo_$24768_storage_ptr_$", - "typeString": "type(struct WorldIDIdentityManagerImplV1.RootInfo storage pointer)" - } - }, - "id": 25617, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "structConstructorCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "34281:38:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo memory" - } - }, - "functionReturnParameters": 25577, - "id": 25618, - "nodeType": "Return", - "src": "34274:45:29" - } - ] - }, - "id": 25620, - "nodeType": "IfStatement", - "src": "33936:394:29", - "trueBody": { - "id": 25587, - "nodeType": "Block", - "src": "33961:62:29", - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 25582, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "33991:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "hexValue": "30", - "id": 25583, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "34004:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - { - "hexValue": "74727565", - "id": 25584, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "bool", - "lValueRequested": false, - "nodeType": "Literal", - "src": "34007:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "value": "true" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - ], - "id": 25581, - "name": "RootInfo", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24768, - "src": "33982:8:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_struct$_RootInfo_$24768_storage_ptr_$", - "typeString": "type(struct WorldIDIdentityManagerImplV1.RootInfo storage pointer)" - } - }, - "id": 25585, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "structConstructorCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "33982:30:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo memory" - } - }, - "functionReturnParameters": 25577, - "id": 25586, - "nodeType": "Return", - "src": "33975:37:29" - } - ] - } - } - ] - }, - "documentation": { - "id": 25566, - "nodeType": "StructuredDocumentation", - "src": "33270:485:29", - "text": "@notice Allows a caller to query the root history for information about a given root.\n @dev Should be used sparingly as the query can be quite expensive.\n @param root The root for which you are querying information.\n @return rootInfo The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist.\n Note that if the queried root is the current, the timestamp will be invalid as the\n root has not been superseded." - }, - "functionSelector": "3f7c178d", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25571, - "kind": "modifierInvocation", - "modifierName": { - "id": 25570, - "name": "onlyProxy", - "nameLocations": [ - "33845:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "33845:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "33845:9:29" - }, - { - "id": 25573, - "kind": "modifierInvocation", - "modifierName": { - "id": 25572, - "name": "onlyInitialized", - "nameLocations": [ - "33863:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "33863:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "33863:15:29" - } - ], - "name": "queryRoot", - "nameLocation": "33769:9:29", - "parameters": { - "id": 25569, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25568, - "mutability": "mutable", - "name": "root", - "nameLocation": "33787:4:29", - "nodeType": "VariableDeclaration", - "scope": 25622, - "src": "33779:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25567, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "33779:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "33778:14:29" - }, - "returnParameters": { - "id": 25577, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25576, - "mutability": "mutable", - "name": "rootInfo", - "nameLocation": "33912:8:29", - "nodeType": "VariableDeclaration", - "scope": 25622, - "src": "33896:24:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo" - }, - "typeName": { - "id": 25575, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25574, - "name": "RootInfo", - "nameLocations": [ - "33896:8:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24768, - "src": "33896:8:29" - }, - "referencedDeclaration": 24768, - "src": "33896:8:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_RootInfo_$24768_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.RootInfo" - } - }, - "visibility": "internal" - } - ], - "src": "33895:26:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25682, - "nodeType": "FunctionDefinition", - "src": "35005:658:29", - "nodes": [], - "body": { - "id": 25681, - "nodeType": "Block", - "src": "35147:516:29", - "nodes": [], - "statements": [ - { - "assignments": [ - 25630 - ], - "declarations": [ - { - "constant": false, - "id": 25630, - "mutability": "mutable", - "name": "previousIsZero", - "nameLocation": "35162:14:29", - "nodeType": "VariableDeclaration", - "scope": 25681, - "src": "35157:19:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25629, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "35157:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "id": 25632, - "initialValue": { - "hexValue": "66616c7365", - "id": 25631, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "bool", - "lValueRequested": false, - "nodeType": "Literal", - "src": "35179:5:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "value": "false" - }, - "nodeType": "VariableDeclarationStatement", - "src": "35157:27:29" - }, - { - "body": { - "id": 25679, - "nodeType": "Block", - "src": "35252:405:29", - "statements": [ - { - "assignments": [ - 25645 - ], - "declarations": [ - { - "constant": false, - "id": 25645, - "mutability": "mutable", - "name": "commitment", - "nameLocation": "35274:10:29", - "nodeType": "VariableDeclaration", - "scope": 25679, - "src": "35266:18:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25644, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "35266:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25649, - "initialValue": { - "baseExpression": { - "id": 25646, - "name": "identityCommitments", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25626, - "src": "35287:19:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - }, - "id": 25648, - "indexExpression": { - "id": 25647, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25634, - "src": "35307:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "35287:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "35266:43:29" - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "id": 25654, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25650, - "name": "previousIsZero", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25630, - "src": "35327:14:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "BinaryOperation", - "operator": "&&", - "rightExpression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25653, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25651, - "name": "commitment", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25645, - "src": "35345:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "id": 25652, - "name": "EMPTY_LEAF", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24736, - "src": "35359:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "35345:24:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "src": "35327:42:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25660, - "nodeType": "IfStatement", - "src": "35323:108:29", - "trueBody": { - "id": 25659, - "nodeType": "Block", - "src": "35371:60:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "id": 25656, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25634, - "src": "35414:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25655, - "name": "InvalidCommitment", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24811, - "src": "35396:17:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_uint256_$returns$__$", - "typeString": "function (uint256) pure" - } - }, - "id": 25657, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "35396:20:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25658, - "nodeType": "RevertStatement", - "src": "35389:27:29" - } - ] - } - }, - { - "condition": { - "id": 25664, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "35448:33:29", - "subExpression": { - "arguments": [ - { - "id": 25662, - "name": "commitment", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25645, - "src": "35470:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25661, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "35449:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 25663, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "35449:32:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25672, - "nodeType": "IfStatement", - "src": "35444:148:29", - "trueBody": { - "id": 25671, - "nodeType": "Block", - "src": "35483:109:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 25666, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "35525:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 25667, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "35546:18:29", - "memberName": "IdentityCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24777, - "src": "35525:39:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "id": 25668, - "name": "commitment", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25645, - "src": "35566:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25665, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "35508:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 25669, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "35508:69:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25670, - "nodeType": "RevertStatement", - "src": "35501:76:29" - } - ] - } - }, - { - "expression": { - "id": 25677, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25673, - "name": "previousIsZero", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25630, - "src": "35605:14:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25676, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25674, - "name": "commitment", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25645, - "src": "35622:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "id": 25675, - "name": "EMPTY_LEAF", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24736, - "src": "35636:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "35622:24:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "src": "35605:41:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25678, - "nodeType": "ExpressionStatement", - "src": "35605:41:29" - } - ] - }, - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25640, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25637, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25634, - "src": "35215:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "<", - "rightExpression": { - "expression": { - "id": 25638, - "name": "identityCommitments", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25626, - "src": "35219:19:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[] calldata" - } - }, - "id": 25639, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "35239:6:29", - "memberName": "length", - "nodeType": "MemberAccess", - "src": "35219:26:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "35215:30:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25680, - "initializationExpression": { - "assignments": [ - 25634 - ], - "declarations": [ - { - "constant": false, - "id": 25634, - "mutability": "mutable", - "name": "i", - "nameLocation": "35208:1:29", - "nodeType": "VariableDeclaration", - "scope": 25680, - "src": "35200:9:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25633, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "35200:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25636, - "initialValue": { - "hexValue": "30", - "id": 25635, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "35212:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "nodeType": "VariableDeclarationStatement", - "src": "35200:13:29" - }, - "loopExpression": { - "expression": { - "id": 25642, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "++", - "prefix": true, - "src": "35247:3:29", - "subExpression": { - "id": 25641, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25634, - "src": "35249:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25643, - "nodeType": "ExpressionStatement", - "src": "35247:3:29" - }, - "nodeType": "ForStatement", - "src": "35195:462:29" - } - ] - }, - "documentation": { - "id": 25623, - "nodeType": "StructuredDocumentation", - "src": "34342:658:29", - "text": "@notice Validates an array of identity commitments, reverting if it finds one that is\n invalid or has not been reduced.\n @dev Identities are not valid if an identity is a non-zero element that occurs after a zero\n element in the array.\n @param identityCommitments The array of identity commitments to be validated.\n @custom:reverts Reverts with `InvalidCommitment` if one or more of the provided commitments\n is invalid.\n @custom:reverts Reverts with `UnreducedElement` if one or more of the provided commitments\n is not in reduced form." - }, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "validateIdentityCommitmentsForRegistration", - "nameLocation": "35014:42:29", - "parameters": { - "id": 25627, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25626, - "mutability": "mutable", - "name": "identityCommitments", - "nameLocation": "35076:19:29", - "nodeType": "VariableDeclaration", - "scope": 25682, - "src": "35057:38:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", - "typeString": "uint256[]" - }, - "typeName": { - "baseType": { - "id": 25624, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "35057:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25625, - "nodeType": "ArrayTypeName", - "src": "35057:9:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", - "typeString": "uint256[]" - } - }, - "visibility": "internal" - } - ], - "src": "35056:40:29" - }, - "returnParameters": { - "id": 25628, - "nodeType": "ParameterList", - "parameters": [], - "src": "35147:0:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "internal" - }, - { - "id": 25739, - "nodeType": "FunctionDefinition", - "src": "36043:710:29", - "nodes": [], - "body": { - "id": 25738, - "nodeType": "Block", - "src": "36172:581:29", - "nodes": [], - "statements": [ - { - "body": { - "id": 25736, - "nodeType": "Block", - "src": "36230:517:29", - "statements": [ - { - "assignments": [ - 25703 - ], - "declarations": [ - { - "constant": false, - "id": 25703, - "mutability": "mutable", - "name": "identity", - "nameLocation": "36266:8:29", - "nodeType": "VariableDeclaration", - "scope": 25736, - "src": "36244:30:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - }, - "typeName": { - "id": 25702, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25701, - "name": "IdentityUpdate", - "nameLocations": [ - "36244:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "36244:14:29" - }, - "referencedDeclaration": 24775, - "src": "36244:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "visibility": "internal" - } - ], - "id": 25707, - "initialValue": { - "baseExpression": { - "id": 25704, - "name": "identities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25687, - "src": "36277:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25706, - "indexExpression": { - "id": 25705, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25691, - "src": "36288:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "36277:13:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "36244:46:29" - }, - { - "condition": { - "id": 25712, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "36308:45:29", - "subExpression": { - "arguments": [ - { - "expression": { - "id": 25709, - "name": "identity", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25703, - "src": "36330:8:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25710, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "36339:13:29", - "memberName": "oldCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24772, - "src": "36330:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25708, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "36309:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 25711, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "36309:44:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25721, - "nodeType": "IfStatement", - "src": "36304:210:29", - "trueBody": { - "id": 25720, - "nodeType": "Block", - "src": "36355:159:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 25714, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "36418:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 25715, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "36439:18:29", - "memberName": "IdentityCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24777, - "src": "36418:39:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "expression": { - "id": 25716, - "name": "identity", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25703, - "src": "36459:8:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25717, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "36468:13:29", - "memberName": "oldCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24772, - "src": "36459:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25713, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "36380:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 25718, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "36380:119:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25719, - "nodeType": "RevertStatement", - "src": "36373:126:29" - } - ] - } - }, - { - "condition": { - "id": 25726, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "!", - "prefix": true, - "src": "36531:45:29", - "subExpression": { - "arguments": [ - { - "expression": { - "id": 25723, - "name": "identity", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25703, - "src": "36553:8:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25724, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "36562:13:29", - "memberName": "newCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24774, - "src": "36553:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25722, - "name": "isInputInReducedForm", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25795, - "src": "36532:20:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 25725, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "36532:44:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25735, - "nodeType": "IfStatement", - "src": "36527:210:29", - "trueBody": { - "id": 25734, - "nodeType": "Block", - "src": "36578:159:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "expression": { - "id": 25728, - "name": "UnreducedElementType", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24779, - "src": "36641:20:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_enum$_UnreducedElementType_$24779_$", - "typeString": "type(enum WorldIDIdentityManagerImplV1.UnreducedElementType)" - } - }, - "id": 25729, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "36662:18:29", - "memberName": "IdentityCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24777, - "src": "36641:39:29", - "typeDescriptions": { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - } - }, - { - "expression": { - "id": 25730, - "name": "identity", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25703, - "src": "36682:8:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25731, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "36691:13:29", - "memberName": "newCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24774, - "src": "36682:22:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_enum$_UnreducedElementType_$24779", - "typeString": "enum WorldIDIdentityManagerImplV1.UnreducedElementType" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25727, - "name": "UnreducedElement", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24801, - "src": "36603:16:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_enum$_UnreducedElementType_$24779_$_t_uint256_$returns$__$", - "typeString": "function (enum WorldIDIdentityManagerImplV1.UnreducedElementType,uint256) pure" - } - }, - "id": 25732, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "36603:119:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25733, - "nodeType": "RevertStatement", - "src": "36596:126:29" - } - ] - } - } - ] - }, - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25697, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25694, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25691, - "src": "36202:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "<", - "rightExpression": { - "expression": { - "id": 25695, - "name": "identities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25687, - "src": "36206:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25696, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "36217:6:29", - "memberName": "length", - "nodeType": "MemberAccess", - "src": "36206:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "36202:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25737, - "initializationExpression": { - "assignments": [ - 25691 - ], - "declarations": [ - { - "constant": false, - "id": 25691, - "mutability": "mutable", - "name": "i", - "nameLocation": "36195:1:29", - "nodeType": "VariableDeclaration", - "scope": 25737, - "src": "36187:9:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25690, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "36187:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25693, - "initialValue": { - "hexValue": "30", - "id": 25692, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "36199:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "nodeType": "VariableDeclarationStatement", - "src": "36187:13:29" - }, - "loopExpression": { - "expression": { - "id": 25699, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "++", - "prefix": true, - "src": "36225:3:29", - "subExpression": { - "id": 25698, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25691, - "src": "36227:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25700, - "nodeType": "ExpressionStatement", - "src": "36225:3:29" - }, - "nodeType": "ForStatement", - "src": "36182:565:29" - } - ] - }, - "documentation": { - "id": 25683, - "nodeType": "StructuredDocumentation", - "src": "35669:331:29", - "text": "@notice Validates the array of identities for each of the old and new commitments being in\n reduced form.\n @param identities The array of (old, new) identity pairs with their indices to validate.\n @custom:reverts UnreducedElement If one or more of the provided commitments is not in" - }, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "validateIdentitiesInReducedForm", - "nameLocation": "36052:31:29", - "parameters": { - "id": 25688, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25687, - "mutability": "mutable", - "name": "identities", - "nameLocation": "36110:10:29", - "nodeType": "VariableDeclaration", - "scope": 25739, - "src": "36084:36:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - }, - "typeName": { - "baseType": { - "id": 25685, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25684, - "name": "IdentityUpdate", - "nameLocations": [ - "36084:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "36084:14:29" - }, - "referencedDeclaration": 24775, - "src": "36084:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "id": 25686, - "nodeType": "ArrayTypeName", - "src": "36084:16:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_storage_$dyn_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - } - }, - "visibility": "internal" - } - ], - "src": "36083:38:29" - }, - "returnParameters": { - "id": 25689, - "nodeType": "ParameterList", - "parameters": [], - "src": "36172:0:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "internal" - }, - { - "id": 25778, - "nodeType": "FunctionDefinition", - "src": "37202:390:29", - "nodes": [], - "body": { - "id": 25777, - "nodeType": "Block", - "src": "37337:255:29", - "nodes": [], - "statements": [ - { - "body": { - "id": 25775, - "nodeType": "Block", - "src": "37395:191:29", - "statements": [ - { - "assignments": [ - 25760 - ], - "declarations": [ - { - "constant": false, - "id": 25760, - "mutability": "mutable", - "name": "commitmentValue", - "nameLocation": "37431:15:29", - "nodeType": "VariableDeclaration", - "scope": 25775, - "src": "37409:37:29", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - }, - "typeName": { - "id": 25759, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25758, - "name": "IdentityUpdate", - "nameLocations": [ - "37409:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "37409:14:29" - }, - "referencedDeclaration": 24775, - "src": "37409:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "visibility": "internal" - } - ], - "id": 25764, - "initialValue": { - "baseExpression": { - "id": 25761, - "name": "identities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25744, - "src": "37449:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25763, - "indexExpression": { - "id": 25762, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25748, - "src": "37460:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "37449:13:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "37409:53:29" - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25768, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "expression": { - "id": 25765, - "name": "commitmentValue", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25760, - "src": "37480:15:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_memory_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate memory" - } - }, - "id": 25766, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "37496:13:29", - "memberName": "newCommitment", - "nodeType": "MemberAccess", - "referencedDeclaration": 24774, - "src": "37480:29:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "hexValue": "30", - "id": 25767, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "37513:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "src": "37480:34:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25774, - "nodeType": "IfStatement", - "src": "37476:100:29", - "trueBody": { - "id": 25773, - "nodeType": "Block", - "src": "37516:60:29", - "statements": [ - { - "errorCall": { - "arguments": [ - { - "id": 25770, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25748, - "src": "37559:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 25769, - "name": "InvalidCommitment", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24811, - "src": "37541:17:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$_t_uint256_$returns$__$", - "typeString": "function (uint256) pure" - } - }, - "id": 25771, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "37541:20:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25772, - "nodeType": "RevertStatement", - "src": "37534:27:29" - } - ] - } - } - ] - }, - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25754, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25751, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25748, - "src": "37367:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "<", - "rightExpression": { - "expression": { - "id": 25752, - "name": "identities", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25744, - "src": "37371:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate calldata[] calldata" - } - }, - "id": 25753, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "37382:6:29", - "memberName": "length", - "nodeType": "MemberAccess", - "src": "37371:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "37367:21:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25776, - "initializationExpression": { - "assignments": [ - 25748 - ], - "declarations": [ - { - "constant": false, - "id": 25748, - "mutability": "mutable", - "name": "i", - "nameLocation": "37360:1:29", - "nodeType": "VariableDeclaration", - "scope": 25776, - "src": "37352:9:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25747, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "37352:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 25750, - "initialValue": { - "hexValue": "30", - "id": 25749, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "37364:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "nodeType": "VariableDeclarationStatement", - "src": "37352:13:29" - }, - "loopExpression": { - "expression": { - "id": 25756, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "UnaryOperation", - "operator": "++", - "prefix": true, - "src": "37390:3:29", - "subExpression": { - "id": 25755, - "name": "i", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25748, - "src": "37392:1:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25757, - "nodeType": "ExpressionStatement", - "src": "37390:3:29" - }, - "nodeType": "ForStatement", - "src": "37347:239:29" - } - ] - }, - "documentation": { - "id": 25740, - "nodeType": "StructuredDocumentation", - "src": "36759:438:29", - "text": "@notice Vaslidates an array of identity commitments as part of identity removal.\n @dev Identities are not valid for identity removal if the provided commitment value is\n non-zero.\n @param identities The array of identity commitments to be validated.\n @custom:reverts InvalidCommitment If one or more of the provided commitments is invalid due\n to being non-zero." - }, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "validateIdentityCommitmentsForRemoval", - "nameLocation": "37211:37:29", - "parameters": { - "id": 25745, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25744, - "mutability": "mutable", - "name": "identities", - "nameLocation": "37275:10:29", - "nodeType": "VariableDeclaration", - "scope": 25778, - "src": "37249:36:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_calldata_ptr_$dyn_calldata_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - }, - "typeName": { - "baseType": { - "id": 25742, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25741, - "name": "IdentityUpdate", - "nameLocations": [ - "37249:14:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24775, - "src": "37249:14:29" - }, - "referencedDeclaration": 24775, - "src": "37249:14:29", - "typeDescriptions": { - "typeIdentifier": "t_struct$_IdentityUpdate_$24775_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate" - } - }, - "id": 25743, - "nodeType": "ArrayTypeName", - "src": "37249:16:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_struct$_IdentityUpdate_$24775_storage_$dyn_storage_ptr", - "typeString": "struct WorldIDIdentityManagerImplV1.IdentityUpdate[]" - } - }, - "visibility": "internal" - } - ], - "src": "37248:38:29" - }, - "returnParameters": { - "id": 25746, - "nodeType": "ParameterList", - "parameters": [], - "src": "37337:0:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "internal" - }, - { - "id": 25795, - "nodeType": "FunctionDefinition", - "src": "37923:224:29", - "nodes": [], - "body": { - "id": 25794, - "nodeType": "Block", - "src": "38097:50:29", - "nodes": [], - "statements": [ - { - "expression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25792, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25790, - "name": "input", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25781, - "src": "38114:5:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "<", - "rightExpression": { - "id": 25791, - "name": "SNARK_SCALAR_FIELD", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24740, - "src": "38122:18:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "38114:26:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "functionReturnParameters": 25789, - "id": 25793, - "nodeType": "Return", - "src": "38107:33:29" - } - ] - }, - "documentation": { - "id": 25779, - "nodeType": "StructuredDocumentation", - "src": "37598:320:29", - "text": "@notice Checks if the provided `input` is in reduced form within the field `Fr`.\n @dev `r` in this case is given by `SNARK_SCALAR_FIELD`.\n @param input The input to check for being in reduced form.\n @return isInReducedForm Returns `true` if `input` is in reduced form, `false` otherwise." - }, - "functionSelector": "34923152", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25784, - "kind": "modifierInvocation", - "modifierName": { - "id": 25783, - "name": "onlyProxy", - "nameLocations": [ - "38020:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "38020:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "38020:9:29" - }, - { - "id": 25786, - "kind": "modifierInvocation", - "modifierName": { - "id": 25785, - "name": "onlyInitialized", - "nameLocations": [ - "38038:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "38038:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "38038:15:29" - } - ], - "name": "isInputInReducedForm", - "nameLocation": "37932:20:29", - "parameters": { - "id": 25782, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25781, - "mutability": "mutable", - "name": "input", - "nameLocation": "37961:5:29", - "nodeType": "VariableDeclaration", - "scope": 25795, - "src": "37953:13:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25780, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "37953:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "37952:15:29" - }, - "returnParameters": { - "id": 25789, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25788, - "mutability": "mutable", - "name": "isInReducedForm", - "nameLocation": "38076:15:29", - "nodeType": "VariableDeclaration", - "scope": 25795, - "src": "38071:20:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25787, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "38071:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "38070:22:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25808, - "nodeType": "FunctionDefinition", - "src": "38453:192:29", - "nodes": [], - "body": { - "id": 25807, - "nodeType": "Block", - "src": "38595:50:29", - "nodes": [], - "statements": [ - { - "expression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25805, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25803, - "name": "input", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25798, - "src": "38612:5:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "%", - "rightExpression": { - "id": 25804, - "name": "SNARK_SCALAR_FIELD", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24740, - "src": "38620:18:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "38612:26:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "functionReturnParameters": 25802, - "id": 25806, - "nodeType": "Return", - "src": "38605:33:29" - } - ] - }, - "documentation": { - "id": 25796, - "nodeType": "StructuredDocumentation", - "src": "38153:295:29", - "text": "@notice Reduces the `input` element into the finite field `Fr` using the modulo operation.\n @dev `r` in this case is given by `SNARK_SCALAR_FIELD`.\n @param input The number to reduce into `Fr`.\n @return elem The value of `input` reduced to be an element of `Fr`." - }, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "reduceInputElementInSnarkScalarField", - "nameLocation": "38462:36:29", - "parameters": { - "id": 25799, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25798, - "mutability": "mutable", - "name": "input", - "nameLocation": "38507:5:29", - "nodeType": "VariableDeclaration", - "scope": 25808, - "src": "38499:13:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25797, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "38499:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "38498:15:29" - }, - "returnParameters": { - "id": 25802, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25801, - "mutability": "mutable", - "name": "elem", - "nameLocation": "38585:4:29", - "nodeType": "VariableDeclaration", - "scope": 25808, - "src": "38577:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25800, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "38577:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "38576:14:29" - }, - "scope": 26045, - "stateMutability": "pure", - "virtual": true, - "visibility": "internal" - }, - { - "id": 25853, - "nodeType": "FunctionDefinition", - "src": "39100:631:29", - "nodes": [], - "body": { - "id": 25852, - "nodeType": "Block", - "src": "39251:480:29", - "nodes": [], - "statements": [ - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25822, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25820, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25811, - "src": "39265:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "id": 25821, - "name": "_latestRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24721, - "src": "39273:11:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "39265:19:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25849, - "nodeType": "IfStatement", - "src": "39261:442:29", - "trueBody": { - "id": 25848, - "nodeType": "Block", - "src": "39286:417:29", - "statements": [ - { - "assignments": [ - 25824 - ], - "declarations": [ - { - "constant": false, - "id": 25824, - "mutability": "mutable", - "name": "rootTimestamp", - "nameLocation": "39308:13:29", - "nodeType": "VariableDeclaration", - "scope": 25848, - "src": "39300:21:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - }, - "typeName": { - "id": 25823, - "name": "uint128", - "nodeType": "ElementaryTypeName", - "src": "39300:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "visibility": "internal" - } - ], - "id": 25828, - "initialValue": { - "baseExpression": { - "id": 25825, - "name": "rootHistory", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24726, - "src": "39324:11:29", - "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", - "typeString": "mapping(uint256 => uint128)" - } - }, - "id": 25827, - "indexExpression": { - "id": 25826, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25811, - "src": "39336:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "nodeType": "IndexAccess", - "src": "39324:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "39300:41:29" - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25834, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25832, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "expression": { - "id": 25829, - "name": "block", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -4, - "src": "39420:5:29", - "typeDescriptions": { - "typeIdentifier": "t_magic_block", - "typeString": "block" - } - }, - "id": 25830, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "39426:9:29", - "memberName": "timestamp", - "nodeType": "MemberAccess", - "src": "39420:15:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "-", - "rightExpression": { - "id": 25831, - "name": "rootTimestamp", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25824, - "src": "39438:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "src": "39420:31:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": ">", - "rightExpression": { - "id": 25833, - "name": "rootHistoryExpiry", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24729, - "src": "39454:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "39420:51:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25839, - "nodeType": "IfStatement", - "src": "39416:110:29", - "trueBody": { - "id": 25838, - "nodeType": "Block", - "src": "39473:53:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25835, - "name": "ExpiredRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24824, - "src": "39498:11:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25836, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "39498:13:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25837, - "nodeType": "RevertStatement", - "src": "39491:20:29" - } - ] - } - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - }, - "id": 25842, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25840, - "name": "rootTimestamp", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25824, - "src": "39616:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint128", - "typeString": "uint128" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "hexValue": "30", - "id": 25841, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "39633:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "src": "39616:18:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25847, - "nodeType": "IfStatement", - "src": "39612:81:29", - "trueBody": { - "id": 25846, - "nodeType": "Block", - "src": "39636:57:29", - "statements": [ - { - "errorCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 25843, - "name": "NonExistentRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24827, - "src": "39661:15:29", - "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 25844, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "39661:17:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25845, - "nodeType": "RevertStatement", - "src": "39654:24:29" - } - ] - } - } - ] - } - }, - { - "expression": { - "hexValue": "74727565", - "id": 25850, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "bool", - "lValueRequested": false, - "nodeType": "Literal", - "src": "39720:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "value": "true" - }, - "functionReturnParameters": 25819, - "id": 25851, - "nodeType": "Return", - "src": "39713:11:29" - } - ] - }, - "documentation": { - "id": 25809, - "nodeType": "StructuredDocumentation", - "src": "38651:444:29", - "text": "@notice Checks if a given root value is valid and has been added to the root history.\n @dev Reverts with `ExpiredRoot` if the root has expired, and `NonExistentRoot` if the root\n is not in the root history.\n @param root The root of a given identity group.\n @custom:reverts ExpiredRoot If the root is not valid due to being expired.\n @custom:reverts NonExistentRoot If the root does not exist." - }, - "functionSelector": "8b6c56c6", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25814, - "kind": "modifierInvocation", - "modifierName": { - "id": 25813, - "name": "onlyProxy", - "nameLocations": [ - "39190:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "39190:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "39190:9:29" - }, - { - "id": 25816, - "kind": "modifierInvocation", - "modifierName": { - "id": 25815, - "name": "onlyInitialized", - "nameLocations": [ - "39208:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "39208:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "39208:15:29" - } - ], - "name": "checkValidRoot", - "nameLocation": "39109:14:29", - "parameters": { - "id": 25812, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25811, - "mutability": "mutable", - "name": "root", - "nameLocation": "39132:4:29", - "nodeType": "VariableDeclaration", - "scope": 25853, - "src": "39124:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25810, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "39124:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "39123:14:29" - }, - "returnParameters": { - "id": 25819, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25818, - "mutability": "mutable", - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "VariableDeclaration", - "scope": 25853, - "src": "39241:4:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 25817, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "39241:4:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "39240:6:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25869, - "nodeType": "FunctionDefinition", - "src": "39964:236:29", - "nodes": [], - "body": { - "id": 25868, - "nodeType": "Block", - "src": "40144:56:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 25865, - "name": "batchInsertionVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24744, - "src": "40169:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - ], - "id": 25864, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "40161:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 25863, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "40161:7:29", - "typeDescriptions": {} - } - }, - "id": 25866, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "40161:32:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "functionReturnParameters": 25862, - "id": 25867, - "nodeType": "Return", - "src": "40154:39:29" - } - ] - }, - "documentation": { - "id": 25854, - "nodeType": "StructuredDocumentation", - "src": "39737:222:29", - "text": "@notice Gets the address for the lookup table of merkle tree verifiers used for identity\n registrations.\n @return addr The addresss of the contract being used as the verifier lookup table." - }, - "functionSelector": "8fc22e9f", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25857, - "kind": "modifierInvocation", - "modifierName": { - "id": 25856, - "name": "onlyProxy", - "nameLocations": [ - "40075:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "40075:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "40075:9:29" - }, - { - "id": 25859, - "kind": "modifierInvocation", - "modifierName": { - "id": 25858, - "name": "onlyInitialized", - "nameLocations": [ - "40093:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "40093:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "40093:15:29" - } - ], - "name": "getRegisterIdentitiesVerifierLookupTableAddress", - "nameLocation": "39973:47:29", - "parameters": { - "id": 25855, - "nodeType": "ParameterList", - "parameters": [], - "src": "40020:2:29" - }, - "returnParameters": { - "id": 25862, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25861, - "mutability": "mutable", - "name": "addr", - "nameLocation": "40134:4:29", - "nodeType": "VariableDeclaration", - "scope": 25869, - "src": "40126:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 25860, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "40126:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "40125:14:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25887, - "nodeType": "FunctionDefinition", - "src": "40528:226:29", - "nodes": [], - "body": { - "id": 25886, - "nodeType": "Block", - "src": "40703:51:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 25884, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25882, - "name": "batchInsertionVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24744, - "src": "40713:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25883, - "name": "newTable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25873, - "src": "40739:8:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "src": "40713:34:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "id": 25885, - "nodeType": "ExpressionStatement", - "src": "40713:34:29" - } - ] - }, - "documentation": { - "id": 25870, - "nodeType": "StructuredDocumentation", - "src": "40206:317:29", - "text": "@notice Sets the address for the lookup table of merkle tree verifiers used for identity\n registrations.\n @dev Only the owner of the contract can call this function.\n @param newTable The new verifier lookup table to be used for verifying identity\n registrations." - }, - "functionSelector": "2f059fca", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25876, - "kind": "modifierInvocation", - "modifierName": { - "id": 25875, - "name": "onlyProxy", - "nameLocations": [ - "40647:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "40647:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "40647:9:29" - }, - { - "id": 25878, - "kind": "modifierInvocation", - "modifierName": { - "id": 25877, - "name": "onlyInitialized", - "nameLocations": [ - "40665:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "40665:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "40665:15:29" - }, - { - "id": 25880, - "kind": "modifierInvocation", - "modifierName": { - "id": 25879, - "name": "onlyOwner", - "nameLocations": [ - "40689:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "40689:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "40689:9:29" - } - ], - "name": "setRegisterIdentitiesVerifierLookupTable", - "nameLocation": "40537:40:29", - "parameters": { - "id": 25874, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25873, - "mutability": "mutable", - "name": "newTable", - "nameLocation": "40598:8:29", - "nodeType": "VariableDeclaration", - "scope": 25887, - "src": "40578:28:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - }, - "typeName": { - "id": 25872, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25871, - "name": "VerifierLookupTable", - "nameLocations": [ - "40578:19:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26691, - "src": "40578:19:29" - }, - "referencedDeclaration": 26691, - "src": "40578:19:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "visibility": "internal" - } - ], - "src": "40577:30:29" - }, - "returnParameters": { - "id": 25881, - "nodeType": "ParameterList", - "parameters": [], - "src": "40703:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25903, - "nodeType": "FunctionDefinition", - "src": "41048:232:29", - "nodes": [], - "body": { - "id": 25902, - "nodeType": "Block", - "src": "41224:56:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 25899, - "name": "identityUpdateVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24748, - "src": "41249:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - ], - "id": 25898, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "41241:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 25897, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "41241:7:29", - "typeDescriptions": {} - } - }, - "id": 25900, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "41241:32:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "functionReturnParameters": 25896, - "id": 25901, - "nodeType": "Return", - "src": "41234:39:29" - } - ] - }, - "documentation": { - "id": 25888, - "nodeType": "StructuredDocumentation", - "src": "40760:283:29", - "text": "@notice Gets the address for the lookup table of merkle tree verifiers used for identity\n updates.\n @dev The update verifier is also used for member removals.\n @return addr The addresss of the contract being used as the verifier lookup table." - }, - "functionSelector": "4ffbdde5", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25891, - "kind": "modifierInvocation", - "modifierName": { - "id": 25890, - "name": "onlyProxy", - "nameLocations": [ - "41155:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "41155:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "41155:9:29" - }, - { - "id": 25893, - "kind": "modifierInvocation", - "modifierName": { - "id": 25892, - "name": "onlyInitialized", - "nameLocations": [ - "41173:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "41173:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "41173:15:29" - } - ], - "name": "getIdentityUpdateVerifierLookupTableAddress", - "nameLocation": "41057:43:29", - "parameters": { - "id": 25889, - "nodeType": "ParameterList", - "parameters": [], - "src": "41100:2:29" - }, - "returnParameters": { - "id": 25896, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25895, - "mutability": "mutable", - "name": "addr", - "nameLocation": "41214:4:29", - "nodeType": "VariableDeclaration", - "scope": 25903, - "src": "41206:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 25894, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "41206:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "41205:14:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25921, - "nodeType": "FunctionDefinition", - "src": "41670:222:29", - "nodes": [], - "body": { - "id": 25920, - "nodeType": "Block", - "src": "41841:51:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 25918, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25916, - "name": "identityUpdateVerifiers", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24748, - "src": "41851:23:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25917, - "name": "newTable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25907, - "src": "41877:8:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "src": "41851:34:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "id": 25919, - "nodeType": "ExpressionStatement", - "src": "41851:34:29" - } - ] - }, - "documentation": { - "id": 25904, - "nodeType": "StructuredDocumentation", - "src": "41286:379:29", - "text": "@notice Sets the address for the lookup table of merkle tree verifiers to be used for\n verification of identity updates.\n @dev Only the owner of the contract can call this function.\n @dev The update verifier is also used for member removals.\n @param newTable The new lookup table instance to be used for verifying identity updates." - }, - "functionSelector": "6b056600", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25910, - "kind": "modifierInvocation", - "modifierName": { - "id": 25909, - "name": "onlyProxy", - "nameLocations": [ - "41785:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "41785:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "41785:9:29" - }, - { - "id": 25912, - "kind": "modifierInvocation", - "modifierName": { - "id": 25911, - "name": "onlyInitialized", - "nameLocations": [ - "41803:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "41803:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "41803:15:29" - }, - { - "id": 25914, - "kind": "modifierInvocation", - "modifierName": { - "id": 25913, - "name": "onlyOwner", - "nameLocations": [ - "41827:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "41827:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "41827:9:29" - } - ], - "name": "setIdentityUpdateVerifierLookupTable", - "nameLocation": "41679:36:29", - "parameters": { - "id": 25908, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25907, - "mutability": "mutable", - "name": "newTable", - "nameLocation": "41736:8:29", - "nodeType": "VariableDeclaration", - "scope": 25921, - "src": "41716:28:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - }, - "typeName": { - "id": 25906, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25905, - "name": "VerifierLookupTable", - "nameLocations": [ - "41716:19:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26691, - "src": "41716:19:29" - }, - "referencedDeclaration": 26691, - "src": "41716:19:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_VerifierLookupTable_$26691", - "typeString": "contract VerifierLookupTable" - } - }, - "visibility": "internal" - } - ], - "src": "41715:30:29" - }, - "returnParameters": { - "id": 25915, - "nodeType": "ParameterList", - "parameters": [], - "src": "41841:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25937, - "nodeType": "FunctionDefinition", - "src": "42076:210:29", - "nodes": [], - "body": { - "id": 25936, - "nodeType": "Block", - "src": "42236:50:29", - "nodes": [], - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 25933, - "name": "semaphoreVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24752, - "src": "42261:17:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - ], - "id": 25932, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "42253:7:29", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 25931, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "42253:7:29", - "typeDescriptions": {} - } - }, - "id": 25934, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "42253:26:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "functionReturnParameters": 25930, - "id": 25935, - "nodeType": "Return", - "src": "42246:33:29" - } - ] - }, - "documentation": { - "id": 25922, - "nodeType": "StructuredDocumentation", - "src": "41898:173:29", - "text": "@notice Gets the address of the verifier used for verification of semaphore proofs.\n @return addr The addresss of the contract being used as the verifier." - }, - "functionSelector": "f2038f95", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25925, - "kind": "modifierInvocation", - "modifierName": { - "id": 25924, - "name": "onlyProxy", - "nameLocations": [ - "42167:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "42167:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "42167:9:29" - }, - { - "id": 25927, - "kind": "modifierInvocation", - "modifierName": { - "id": 25926, - "name": "onlyInitialized", - "nameLocations": [ - "42185:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "42185:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "42185:15:29" - } - ], - "name": "getSemaphoreVerifierAddress", - "nameLocation": "42085:27:29", - "parameters": { - "id": 25923, - "nodeType": "ParameterList", - "parameters": [], - "src": "42112:2:29" - }, - "returnParameters": { - "id": 25930, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25929, - "mutability": "mutable", - "name": "addr", - "nameLocation": "42226:4:29", - "nodeType": "VariableDeclaration", - "scope": 25937, - "src": "42218:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 25928, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "42218:7:29", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "42217:14:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25955, - "nodeType": "FunctionDefinition", - "src": "42589:205:29", - "nodes": [], - "body": { - "id": 25954, - "nodeType": "Block", - "src": "42746:48:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 25952, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25950, - "name": "semaphoreVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24752, - "src": "42756:17:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25951, - "name": "newVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25941, - "src": "42776:11:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "src": "42756:31:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "id": 25953, - "nodeType": "ExpressionStatement", - "src": "42756:31:29" - } - ] - }, - "documentation": { - "id": 25938, - "nodeType": "StructuredDocumentation", - "src": "42292:292:29", - "text": "@notice Sets the address for the semaphore verifier to be used for verification of\n semaphore proofs.\n @dev Only the owner of the contract can call this function.\n @param newVerifier The new verifier instance to be used for verifying semaphore proofs." - }, - "functionSelector": "0e3a12f3", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25944, - "kind": "modifierInvocation", - "modifierName": { - "id": 25943, - "name": "onlyProxy", - "nameLocations": [ - "42690:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "42690:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "42690:9:29" - }, - { - "id": 25946, - "kind": "modifierInvocation", - "modifierName": { - "id": 25945, - "name": "onlyInitialized", - "nameLocations": [ - "42708:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "42708:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "42708:15:29" - }, - { - "id": 25948, - "kind": "modifierInvocation", - "modifierName": { - "id": 25947, - "name": "onlyOwner", - "nameLocations": [ - "42732:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "42732:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "42732:9:29" - } - ], - "name": "setSemaphoreVerifier", - "nameLocation": "42598:20:29", - "parameters": { - "id": 25942, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25941, - "mutability": "mutable", - "name": "newVerifier", - "nameLocation": "42638:11:29", - "nodeType": "VariableDeclaration", - "scope": 25955, - "src": "42619:30:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - }, - "typeName": { - "id": 25940, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 25939, - "name": "ISemaphoreVerifier", - "nameLocations": [ - "42619:18:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 24290, - "src": "42619:18:29" - }, - "referencedDeclaration": 24290, - "src": "42619:18:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "visibility": "internal" - } - ], - "src": "42618:32:29" - }, - "returnParameters": { - "id": 25949, - "nodeType": "ParameterList", - "parameters": [], - "src": "42746:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 25968, - "nodeType": "FunctionDefinition", - "src": "42970:200:29", - "nodes": [], - "body": { - "id": 25967, - "nodeType": "Block", - "src": "43129:41:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 25965, - "name": "rootHistoryExpiry", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24729, - "src": "43146:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "functionReturnParameters": 25964, - "id": 25966, - "nodeType": "Return", - "src": "43139:24:29" - } - ] - }, - "documentation": { - "id": 25956, - "nodeType": "StructuredDocumentation", - "src": "42800:165:29", - "text": "@notice Gets the current amount of time used to expire roots in the history.\n @return expiryTime The amount of time it takes for a root to expire." - }, - "functionSelector": "43f974cb", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25959, - "kind": "modifierInvocation", - "modifierName": { - "id": 25958, - "name": "onlyProxy", - "nameLocations": [ - "43054:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "43054:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "43054:9:29" - }, - { - "id": 25961, - "kind": "modifierInvocation", - "modifierName": { - "id": 25960, - "name": "onlyInitialized", - "nameLocations": [ - "43072:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "43072:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "43072:15:29" - } - ], - "name": "getRootHistoryExpiry", - "nameLocation": "42979:20:29", - "parameters": { - "id": 25957, - "nodeType": "ParameterList", - "parameters": [], - "src": "42999:2:29" - }, - "returnParameters": { - "id": 25964, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25963, - "mutability": "mutable", - "name": "expiryTime", - "nameLocation": "43113:10:29", - "nodeType": "VariableDeclaration", - "scope": 25968, - "src": "43105:18:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25962, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "43105:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "43104:20:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 25994, - "nodeType": "FunctionDefinition", - "src": "43402:293:29", - "nodes": [], - "body": { - "id": 25993, - "nodeType": "Block", - "src": "43550:145:29", - "nodes": [], - "statements": [ - { - "condition": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 25982, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 25980, - "name": "newExpiryTime", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25971, - "src": "43564:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "hexValue": "30", - "id": 25981, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "43581:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - }, - "src": "43564:18:29", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 25988, - "nodeType": "IfStatement", - "src": "43560:86:29", - "trueBody": { - "id": 25987, - "nodeType": "Block", - "src": "43584:62:29", - "statements": [ - { - "expression": { - "arguments": [ - { - "hexValue": "4578706972792074696d652063616e6e6f74206265207a65726f2e", - "id": 25984, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "43605:29:29", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_42d9ce1b1906fc6a6660b96b1a1887b9fefffe587f75da117e471256324ca69d", - "typeString": "literal_string \"Expiry time cannot be zero.\"" - }, - "value": "Expiry time cannot be zero." - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_stringliteral_42d9ce1b1906fc6a6660b96b1a1887b9fefffe587f75da117e471256324ca69d", - "typeString": "literal_string \"Expiry time cannot be zero.\"" - } - ], - "id": 25983, - "name": "revert", - "nodeType": "Identifier", - "overloadedDeclarations": [ - -19, - -19 - ], - "referencedDeclaration": -19, - "src": "43598:6:29", - "typeDescriptions": { - "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", - "typeString": "function (string memory) pure" - } - }, - "id": 25985, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "43598:37:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 25986, - "nodeType": "ExpressionStatement", - "src": "43598:37:29" - } - ] - } - }, - { - "expression": { - "id": 25991, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 25989, - "name": "rootHistoryExpiry", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24729, - "src": "43655:17:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 25990, - "name": "newExpiryTime", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25971, - "src": "43675:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "43655:33:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25992, - "nodeType": "ExpressionStatement", - "src": "43655:33:29" - } - ] - }, - "documentation": { - "id": 25969, - "nodeType": "StructuredDocumentation", - "src": "43176:221:29", - "text": "@notice Sets the time to wait before expiring a root from the root history.\n @dev Only the owner of the contract can call this function.\n @param newExpiryTime The new time to use to expire roots." - }, - "functionSelector": "c70aa727", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25974, - "kind": "modifierInvocation", - "modifierName": { - "id": 25973, - "name": "onlyProxy", - "nameLocations": [ - "43494:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "43494:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "43494:9:29" - }, - { - "id": 25976, - "kind": "modifierInvocation", - "modifierName": { - "id": 25975, - "name": "onlyInitialized", - "nameLocations": [ - "43512:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "43512:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "43512:15:29" - }, - { - "id": 25978, - "kind": "modifierInvocation", - "modifierName": { - "id": 25977, - "name": "onlyOwner", - "nameLocations": [ - "43536:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 20871, - "src": "43536:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "43536:9:29" - } - ], - "name": "setRootHistoryExpiry", - "nameLocation": "43411:20:29", - "parameters": { - "id": 25972, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 25971, - "mutability": "mutable", - "name": "newExpiryTime", - "nameLocation": "43440:13:29", - "nodeType": "VariableDeclaration", - "scope": 25994, - "src": "43432:21:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 25970, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "43432:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "43431:23:29" - }, - "returnParameters": { - "id": 25979, - "nodeType": "ParameterList", - "parameters": [], - "src": "43550:0:29" - }, - "scope": 26045, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "public" - }, - { - "id": 26007, - "nodeType": "FunctionDefinition", - "src": "43839:192:29", - "nodes": [], - "body": { - "id": 26006, - "nodeType": "Block", - "src": "43998:33:29", - "nodes": [], - "statements": [ - { - "expression": { - "id": 26004, - "name": "treeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24761, - "src": "44015:9:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "functionReturnParameters": 26003, - "id": 26005, - "nodeType": "Return", - "src": "44008:16:29" - } - ] - }, - "documentation": { - "id": 25995, - "nodeType": "StructuredDocumentation", - "src": "43701:133:29", - "text": "@notice Gets the Semaphore tree depth the contract was initialized with.\n @return initializedTreeDepth Tree depth." - }, - "functionSelector": "8e5cdd50", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 25998, - "kind": "modifierInvocation", - "modifierName": { - "id": 25997, - "name": "onlyProxy", - "nameLocations": [ - "43915:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "43915:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "43915:9:29" - }, - { - "id": 26000, - "kind": "modifierInvocation", - "modifierName": { - "id": 25999, - "name": "onlyInitialized", - "nameLocations": [ - "43933:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "43933:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "43933:15:29" - } - ], - "name": "getTreeDepth", - "nameLocation": "43848:12:29", - "parameters": { - "id": 25996, - "nodeType": "ParameterList", - "parameters": [], - "src": "43860:2:29" - }, - "returnParameters": { - "id": 26003, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 26002, - "mutability": "mutable", - "name": "initializedTreeDepth", - "nameLocation": "43972:20:29", - "nodeType": "VariableDeclaration", - "scope": 26007, - "src": "43966:26:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - }, - "typeName": { - "id": 26001, - "name": "uint8", - "nodeType": "ElementaryTypeName", - "src": "43966:5:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - }, - "visibility": "internal" - } - ], - "src": "43965:28:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - }, - { - "id": 26044, - "nodeType": "FunctionDefinition", - "src": "44866:428:29", - "nodes": [], - "body": { - "id": 26043, - "nodeType": "Block", - "src": "45094:200:29", - "nodes": [], - "statements": [ - { - "condition": { - "arguments": [ - { - "id": 26028, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26010, - "src": "45123:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 26027, - "name": "checkValidRoot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 25853, - "src": "45108:14:29", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$_t_uint256_$returns$_t_bool_$", - "typeString": "function (uint256) view returns (bool)" - } - }, - "id": 26029, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "45108:20:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 26042, - "nodeType": "IfStatement", - "src": "45104:184:29", - "trueBody": { - "id": 26041, - "nodeType": "Block", - "src": "45130:158:29", - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 26033, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26010, - "src": "45191:4:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 26034, - "name": "nullifierHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26014, - "src": "45197:13:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 26035, - "name": "signalHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26012, - "src": "45212:10:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 26036, - "name": "externalNullifierHash", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26016, - "src": "45224:21:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "id": 26037, - "name": "proof", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26020, - "src": "45247:5:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - } - }, - { - "id": 26038, - "name": "treeDepth", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24761, - "src": "45254:9:29", - "typeDescriptions": { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8] calldata" - }, - { - "typeIdentifier": "t_uint8", - "typeString": "uint8" - } - ], - "expression": { - "id": 26030, - "name": "semaphoreVerifier", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 24752, - "src": "45144:17:29", - "typeDescriptions": { - "typeIdentifier": "t_contract$_ISemaphoreVerifier_$24290", - "typeString": "contract ISemaphoreVerifier" - } - }, - "id": 26032, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "45162:11:29", - "memberName": "verifyProof", - "nodeType": "MemberAccess", - "referencedDeclaration": 24289, - "src": "45144:29:29", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$_t_uint256_$_t_uint256_$_t_uint256_$_t_uint256_$_t_array$_t_uint256_$8_memory_ptr_$_t_uint256_$returns$__$", - "typeString": "function (uint256,uint256,uint256,uint256,uint256[8] memory,uint256) view external" - } - }, - "id": 26039, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "45144:133:29", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 26040, - "nodeType": "ExpressionStatement", - "src": "45144:133:29" - } - ] - } - } - ] - }, - "baseFunctions": [ - 26747 - ], - "documentation": { - "id": 26008, - "nodeType": "StructuredDocumentation", - "src": "44290:571:29", - "text": "@notice A verifier for the semaphore protocol.\n @dev Note that a double-signaling check is not included here, and should be carried by the\n caller.\n @param root The of the Merkle tree\n @param signalHash A keccak256 hash of the Semaphore signal\n @param nullifierHash The nullifier hash\n @param externalNullifierHash A keccak256 hash of the external nullifier\n @param proof The zero-knowledge proof\n @custom:reverts string If the zero-knowledge proof cannot be verified for the public inputs." - }, - "functionSelector": "354ca120", - "implemented": true, - "kind": "function", - "modifiers": [ - { - "id": 26023, - "kind": "modifierInvocation", - "modifierName": { - "id": 26022, - "name": "onlyProxy", - "nameLocations": [ - "45068:9:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 21569, - "src": "45068:9:29" - }, - "nodeType": "ModifierInvocation", - "src": "45068:9:29" - }, - { - "id": 26025, - "kind": "modifierInvocation", - "modifierName": { - "id": 26024, - "name": "onlyInitialized", - "nameLocations": [ - "45078:15:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 41042, - "src": "45078:15:29" - }, - "nodeType": "ModifierInvocation", - "src": "45078:15:29" - } - ], - "name": "verifyProof", - "nameLocation": "44875:11:29", - "parameters": { - "id": 26021, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 26010, - "mutability": "mutable", - "name": "root", - "nameLocation": "44904:4:29", - "nodeType": "VariableDeclaration", - "scope": 26044, - "src": "44896:12:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 26009, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "44896:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 26012, - "mutability": "mutable", - "name": "signalHash", - "nameLocation": "44926:10:29", - "nodeType": "VariableDeclaration", - "scope": 26044, - "src": "44918:18:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 26011, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "44918:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 26014, - "mutability": "mutable", - "name": "nullifierHash", - "nameLocation": "44954:13:29", - "nodeType": "VariableDeclaration", - "scope": 26044, - "src": "44946:21:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 26013, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "44946:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 26016, - "mutability": "mutable", - "name": "externalNullifierHash", - "nameLocation": "44985:21:29", - "nodeType": "VariableDeclaration", - "scope": 26044, - "src": "44977:29:29", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 26015, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "44977:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 26020, - "mutability": "mutable", - "name": "proof", - "nameLocation": "45036:5:29", - "nodeType": "VariableDeclaration", - "scope": 26044, - "src": "45016:25:29", - "stateVariable": false, - "storageLocation": "calldata", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", - "typeString": "uint256[8]" - }, - "typeName": { - "baseType": { - "id": 26017, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "45016:7:29", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 26019, - "length": { - "hexValue": "38", - "id": 26018, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "45024:1:29", - "typeDescriptions": { - "typeIdentifier": "t_rational_8_by_1", - "typeString": "int_const 8" - }, - "value": "8" - }, - "nodeType": "ArrayTypeName", - "src": "45016:10:29", - "typeDescriptions": { - "typeIdentifier": "t_array$_t_uint256_$8_storage_ptr", - "typeString": "uint256[8]" - } - }, - "visibility": "internal" - } - ], - "src": "44886:161:29" - }, - "returnParameters": { - "id": 26026, - "nodeType": "ParameterList", - "parameters": [], - "src": "45094:0:29" - }, - "scope": 26045, - "stateMutability": "view", - "virtual": true, - "visibility": "public" - } - ], - "abstract": false, - "baseContracts": [ - { - "baseName": { - "id": 24715, - "name": "WorldIDImpl", - "nameLocations": [ - "876:11:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26507, - "src": "876:11:29" - }, - "id": 24716, - "nodeType": "InheritanceSpecifier", - "src": "876:11:29" - }, - { - "baseName": { - "id": 24717, - "name": "IWorldID", - "nameLocations": [ - "889:8:29" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26748, - "src": "889:8:29" - }, - "id": 24718, - "nodeType": "InheritanceSpecifier", - "src": "889:8:29" - } - ], - "canonicalName": "WorldIDIdentityManagerImplV1", - "contractDependencies": [], - "contractKind": "contract", - "documentation": { - "id": 24714, - "nodeType": "StructuredDocumentation", - "src": "464:371:29", - "text": "@title WorldID Identity Manager Implementation Version 1\n @author Worldcoin\n @notice An implementation of a batch-based identity manager for the WorldID protocol.\n @dev The manager is based on the principle of verifying externally-created Zero Knowledge Proofs\n to perform the insertions.\n @dev This is the implementation delegated to by a proxy." - }, - "fullyImplemented": true, - "linearizedBaseContracts": [ - 26045, - 26748, - 26507, - 41048, - 21651, - 21336, - 20967, - 20957, - 21977, - 21515 - ], - "name": "WorldIDIdentityManagerImplV1", - "nameLocation": "844:28:29", - "scope": 26046, - "usedErrors": [ - 24801, - 24806, - 24811, - 24814, - 24821, - 24824, - 24827, - 24830, - 24833, - 24836, - 24839, - 24844, - 41019 - ] - } - ], - "license": "MIT" - }, - "id": 29 -} \ No newline at end of file diff --git a/sol/WorldIDIdentityManagerImplV2.json b/sol/WorldIDIdentityManagerImplV2.json new file mode 100644 index 00000000..e8eaf181 --- /dev/null +++ b/sol/WorldIDIdentityManagerImplV2.json @@ -0,0 +1,6052 @@ +{ + "abi": [ + { + "inputs": [], + "name": "CannotRenounceOwnership", + "type": "error" + }, + { + "inputs": [], + "name": "ExpiredRoot", + "type": "error" + }, + { + "inputs": [], + "name": "ImplementationNotInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "InvalidCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidStateBridgeAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MismatchedInputLengths", + "type": "error" + }, + { + "inputs": [], + "name": "NonExistentRoot", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "providedRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "latestRoot", + "type": "uint256" + } + ], + "name": "NotLatestRoot", + "type": "error" + }, + { + "inputs": [], + "name": "ProofValidationFailure", + "type": "error" + }, + { + "inputs": [], + "name": "StateBridgeAlreadyDisabled", + "type": "error" + }, + { + "inputs": [], + "name": "StateBridgeAlreadyEnabled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum WorldIDIdentityManagerImplV1.UnreducedElementType", + "name": "elementType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "element", + "type": "uint256" + } + ], + "name": "UnreducedElement", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "depth", + "type": "uint8" + } + ], + "name": "UnsupportedTreeDepth", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum WorldIDIdentityManagerImplV1.Dependency", + "name": "kind", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "DependencyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOperator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "name": "IdentityOperatorChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldExpiryTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256" + } + ], + "name": "RootHistoryExpirySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bool", + "name": "isEnabled", + "type": "bool" + } + ], + "name": "StateBridgeStateChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "enum WorldIDIdentityManagerImplV1.TreeChange", + "name": "kind", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "TreeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256" + } + ], + "name": "WorldIDIdentityManagerImplInitialized", + "type": "event" + }, + { + "inputs": [], + "name": "NO_SUCH_ROOT", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "rootInfo", + "type": "tuple" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + } + ], + "name": "calculateIdentityDeletionInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + } + ], + "name": "calculateIdentityRegistrationInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + } + ], + "name": "calculateIdentityUpdateInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "deletionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "deleteIdentities", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getDeleteIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getIdentityUpdateVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRegisterIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRootHistoryExpiry", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSemaphoreVerifierAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTreeDepth", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "identityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchInsertionVerifiers", + "type": "address" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + }, + { + "internalType": "contract ISemaphoreVerifier", + "name": "_semaphoreVerifier", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + } + ], + "name": "initializeV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "name": "queryRoot", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "insertionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "registerIdentities", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "name": "requireValidRoot", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "name": "setDeleteIdentitiesVerifierLookupTable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newIdentityOperator", + "type": "address" + } + ], + "name": "setIdentityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "name": "setIdentityUpdateVerifierLookupTable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "name": "setRegisterIdentitiesVerifierLookupTable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256" + } + ], + "name": "setRootHistoryExpiry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ISemaphoreVerifier", + "name": "newVerifier", + "type": "address" + } + ], + "name": "setSemaphoreVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "updateProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "updateIdentities", + "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" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "signalHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalNullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256[8]", + "name": "proof", + "type": "uint256[8]" + } + ], + "name": "verifyProof", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": { + "object": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051613e706200027e6000396000818161064e0152818161069701528181610775015281816107b501528181610b8d01528181610bcd0152818161100401528181611044015281816110fb0152818161113b015281816111e701528181611227015281816113270152818161136701528181611577015281816115b701528181611669015281816116a9015281816117ff0152818161183f015281816118ca0152818161190a01528181611985015281816119c501528181611a5c01528181611b0c01528181611b4c01528181611c9b01528181611cdb01528181611da701528181611de701528181611eaa01528181611eea01528181611f8101528181611fc1015281816120570152818161209701528181612177015281816121b70152818161226c015281816122ac0152818161248d015281816124cd015281816125e401528181612624015281816126b1015281816126f101528181612787015281816127c70152818161285b0152818161289b01528181612a8101528181612ac101528181612d3e0152612d7e0152613e706000f3fe6080604052600436106101f95760003560e01c8063715018a61161010d578063aa4a729e116100a0578063e30c39781161006f578063e30c3978146105bc578063f134b6ca146105da578063f2038f95146105ef578063f2358e1d14610604578063f2fde38b1461062457600080fd5b8063aa4a729e14610547578063b843b4e514610567578063c70aa72714610587578063d7b0fef1146105a757600080fd5b80638da5cb5b116100dc5780638da5cb5b146104cd5780638e5cdd50146104eb5780638fc22e9f14610512578063a7bba5821461052757600080fd5b8063715018a61461046357806379ba50971461047857806386ec599a1461048d5780638c76a909146104ad57600080fd5b806338c87065116101905780634f1ef2861161015f5780634f1ef286146103c25780634ffbdde5146103d557806352d1902d146103ea578063561f204b146103ff5780636b0566001461044357600080fd5b806338c87065146103135780633e8919b6146103335780633f7c178d1461036057806343f974cb146103ad57600080fd5b80632f059fca116101cc5780632f059fca1461028057806331e4e992146102a0578063354ca120146102d35780633659cfe6146102f357600080fd5b80630e3a12f3146101fe5780632217b2111461022057806323cfdba51461024057806329b6eca914610260575b600080fd5b34801561020a57600080fd5b5061021e610219366004613375565b610644565b005b34801561022c57600080fd5b5061021e61023b366004613404565b61076b565b34801561024c57600080fd5b5061021e61025b3660046134c3565b610b83565b34801561026c57600080fd5b5061021e61027b366004613375565b610f4c565b34801561028c57600080fd5b5061021e61029b366004613375565b610ffa565b3480156102ac57600080fd5b506102c06102bb36600461353c565b6110ef565b6040519081526020015b60405180910390f35b3480156102df57600080fd5b5061021e6102ee3660046135a3565b6111dd565b3480156102ff57600080fd5b5061021e61030e366004613375565b61131d565b34801561031f57600080fd5b5061021e61032e3660046135e2565b6113e5565b34801561033f57600080fd5b5061034861156b565b6040516001600160a01b0390911681526020016102ca565b34801561036c57600080fd5b5061038061037b366004613650565b611642565b60408051825181526020808401516001600160801b031690820152918101511515908201526060016102ca565b3480156103b957600080fd5b506102c06117f3565b61021e6103d03660046136ac565b6118c0565b3480156103e157600080fd5b50610348611979565b3480156103f657600080fd5b506102c0611a4f565b34801561040b57600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610380565b34801561044f57600080fd5b5061021e61045e366004613375565b611b02565b34801561046f57600080fd5b5061021e611bf7565b34801561048457600080fd5b5061021e611c18565b34801561049957600080fd5b506102c06104a8366004613758565b611c8f565b3480156104b957600080fd5b506102c06104c8366004613805565b611d9b565b3480156104d957600080fd5b506033546001600160a01b0316610348565b3480156104f757600080fd5b50610500611e9e565b60405160ff90911681526020016102ca565b34801561051e57600080fd5b50610348611f75565b34801561053357600080fd5b50610348610542366004613375565b61204b565b34801561055357600080fd5b5061021e610562366004613375565b61216d565b34801561057357600080fd5b5061021e61058236600461386d565b612262565b34801561059357600080fd5b5061021e6105a2366004613650565b612483565b3480156105b357600080fd5b506102c06125d8565b3480156105c857600080fd5b506065546001600160a01b0316610348565b3480156105e657600080fd5b506103486126a5565b3480156105fb57600080fd5b5061034861277b565b34801561061057600080fd5b5061021e61061f366004613650565b612851565b34801561063057600080fd5b5061021e61063f366004613375565b61298e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106955760405162461bcd60e51b815260040161068c90613930565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106c76129ff565b6001600160a01b0316146106ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661071057604051630103019560e11b815260040160405180910390fd5b610718612a1b565b61013380546001600160a01b038381166001600160a01b03198316811790935516908160045b6040517fd194b8423e9cb3c7cbebbbc3fe7f79dc2cbe0b40e03270d975abff491504c7b190600090a45050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107b35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107e56129ff565b6001600160a01b03161461080b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661082e57604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b0316331461085c5760405163472511eb60e11b815233600482015260240161068c565b61012e54851461088e5761012e5460405163542fced960e11b815261068c918791600401918252602082015260400190565b600061089d8587848787611d9b565b905060006108cb7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013154604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa15801561091b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093f91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c60006008811061096e5761096e613a07565b602002013581526020018c60016008811061098b5761098b613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f6004600881106109db576109db613a07565b602002013581526020018f6005600881106109f8576109f8613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610a2c57610a2c613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610a629493929190613a40565b6020604051808303816000875af1925050508015610a9d575060408051601f3d908101601f19168201909252610a9a91810190613ae7565b60015b610afd57610aa9613b09565b806308c379a003610ae25750610abd613b24565b80610ac85750610ae4565b8060405162461bcd60e51b815260040161068c9190613bd2565b505b604051631e716a8b60e01b815260040160405180910390fd5b80610b1b57604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600089815261012f6020526040812080546001600160801b031916426001600160801b031617905585906040518b907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a4505b505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bcb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610bfd6129ff565b6001600160a01b031614610c235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16610c4657604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314610c745760405163472511eb60e11b815233600482015260240161068c565b61012e548214610ca65761012e5460405163542fced960e11b815261068c918491600401918252602082015260400190565b6000610cb5858585858a6110ef565b90506000610ce37f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013554604051638a283fc360e01b815263ffffffff8a1660048201529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c600060088110610d8b57610d8b613a07565b602002013581526020018c600160088110610da857610da8613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f600460088110610df857610df8613a07565b602002013581526020018f600560088110610e1557610e15613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610e4957610e49613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610e7f9493929190613a40565b6020604051808303816000875af1925050508015610eba575060408051601f3d908101601f19168201909252610eb791810190613ae7565b60015b610ec657610aa9613b09565b80610ee457604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600086815261012f6020526040902080546001600160801b031916426001600160801b031617905584600160405188907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b600054600290610100900460ff16158015610f6e575060005460ff8083169116105b610f8a5760405162461bcd60e51b815260040161068c90613c05565b6000805461013580546001600160a01b0319166001600160a01b03861617905561ff001961010060ff851661ffff19909316831717169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110425760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166110746129ff565b6001600160a01b03161461109a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166110bd57604051630103019560e11b815260040160405180910390fd5b6110c5612a1b565b61013180546001600160a01b038381166001600160a01b031983168117909355169081600161073e565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036111395760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661116b6129ff565b6001600160a01b0316146111915760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166111b457604051630103019560e11b815260040160405180910390fd5b604051600483028088833781810195865260209095019390935250506040909101902092915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112255760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112576129ff565b6001600160a01b03161461127d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166112a057604051630103019560e11b815260040160405180910390fd5b6112a985612851565b6101335461013454604051634d65479560e11b81526001600160a01b0390921691639aca8f2a916112f191899188918a9189918991600160a81b900460ff1690600401613c53565b60006040518083038186803b15801561130957600080fd5b505afa158015610b78573d6000803e3d6000fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113655760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166113976129ff565b6001600160a01b0316146113bd5760405162461bcd60e51b815260040161068c9061397c565b6113c681612a77565b604080516000808252602082019092526113e291839190612b1f565b50565b600054600190610100900460ff16158015611407575060005460ff8083169116105b6114235760405162461bcd60e51b815260040161068c90613c05565b6000805461ffff191660ff83161761010017905561143f612c8f565b61144886612cbe565b61146a57604051630220cee360e61b815260ff8716600482015260240161068c565b610134805460ff60a81b1916600160a81b60ff891602179055610e106101305561012e85905561013180546001600160a01b03199081166001600160a01b0387811691909117909255610132805482168684161790556101338054821685841617905560335461012d80549190931691161790556114e6612ce5565b6040805160ff88168152602081018790527fd1bcc66c061c32a21f569d138c2dadef4a38a0636309881954af5f44010ec1d8910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036115b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166115e76129ff565b6001600160a01b03161461160d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661163057604051630103019560e11b815260040160405180910390fd5b50610135546001600160a01b03165b90565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116a75760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166116d96129ff565b6001600160a01b0316146116ff5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661172257604051630103019560e11b815260040160405180910390fd5b61012e5482036117515750506040805160608101825261012e5481526000602082015260019181019190915290565b600082815261012f60205260408120546001600160801b0316908190036117ac5760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b610130546000906117c66001600160801b03841642613c8f565b604080516060810182528781526001600160801b039095166020860152911015908301525090505b919050565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361183d5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661186f6129ff565b6001600160a01b0316146118955760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166118b857604051630103019560e11b815260040160405180910390fd5b506101305490565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119085760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661193a6129ff565b6001600160a01b0316146119605760405162461bcd60e51b815260040161068c9061397c565b61196982612a77565b61197582826001612b1f565b5050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119c35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166119f56129ff565b6001600160a01b031614611a1b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611a3e57604051630103019560e11b815260040160405180910390fd5b50610132546001600160a01b031690565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611aef5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161068c565b50600080516020613df483398151915290565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b4a5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b7c6129ff565b6001600160a01b031614611ba25760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611bc557604051630103019560e11b815260040160405180910390fd5b611bcd612a1b565b61013280546001600160a01b038381166001600160a01b031983168117909355169081600361073e565b611bff612a1b565b6040516377aeb0ad60e01b815260040160405180910390fd5b60655433906001600160a01b03168114611c865760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161068c565b6113e281612d1b565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611cd95760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d0b6129ff565b6001600160a01b031614611d315760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611d5457604051630103019560e11b815260040160405180910390fd5b60008989898989898989604051602001611d75989796959493929190613cd9565b60408051601f1981840301815291905280516020909101209a9950505050505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611de55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611e176129ff565b6001600160a01b031614611e3d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611e6057604051630103019560e11b815260040160405180910390fd5b60008686868686604051602001611e7b959493929190613d3d565b60408051601f198184030181529190528051602090910120979650505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611ee85760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611f1a6129ff565b6001600160a01b031614611f405760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611f6357604051630103019560e11b815260040160405180910390fd5b5061013454600160a81b900460ff1690565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611fbf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ff16129ff565b6001600160a01b0316146120175760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661203a57604051630103019560e11b815260040160405180910390fd5b50610131546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120955760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120c76129ff565b6001600160a01b0316146120ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661211057604051630103019560e11b815260040160405180910390fd5b612118612a1b565b61012d80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f5a674c516c196404869e5f502b5634ce442416bb016dde54b5de4c812cc019e690600090a392915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036121b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166121e76129ff565b6001600160a01b03161461220d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661223057604051630103019560e11b815260040160405180910390fd5b612238612a1b565b61013580546001600160a01b038381166001600160a01b031983168117909355169081600261073e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122aa5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122dc6129ff565b6001600160a01b0316146123025760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661232557604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b031633146123535760405163472511eb60e11b815233600482015260240161068c565b61012e5488146123855761012e5460405163542fced960e11b815261068c918a91600401918252602082015260400190565b85841415806123945750858214155b156123b25760405163a0b1d72d60e01b815260040160405180910390fd5b60006123c489838a8a8a8a8a8a611c8f565b905060006123f27f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013254604051638a283fc360e01b8152600481018b90529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246691906139ea565b9050612475818d848e88612d34565b505050505050505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124cb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166124fd6129ff565b6001600160a01b0316146125235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661254657604051630103019560e11b815260040160405180910390fd5b61254e612a1b565b8060000361259e5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e0000000000604482015260640161068c565b610130805490829055604051829082907ff62a6f06fde00a303cd5939e6b53762854412c96a196cda26720cedd28af9e7090600090a35050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126225760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166126546129ff565b6001600160a01b03161461267a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661269d57604051630103019560e11b815260040160405180910390fd5b5061012e5490565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126ef5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127216129ff565b6001600160a01b0316146127475760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661276a57604051630103019560e11b815260040160405180910390fd5b5061012d546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036127c55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127f76129ff565b6001600160a01b03161461281d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661284057604051630103019560e11b815260040160405180910390fd5b50610133546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036128995760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166128cb6129ff565b6001600160a01b0316146128f15760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661291457604051630103019560e11b815260040160405180910390fd5b61012e5481146113e257600081815261012f60205260408120546001600160801b0316908190036129585760405163ddae3b7160e01b815260040160405180910390fd5b6101305461296f6001600160801b03831642613c8f565b111561197557604051631d739acf60e11b815260040160405180910390fd5b612996612a1b565b606580546001600160a01b0383166001600160a01b031990911681179091556129c76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080516020613df4833981519152546001600160a01b031690565b6033546001600160a01b03163314612a755760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161068c565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612abf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612af16129ff565b6001600160a01b031614612b175760405162461bcd60e51b815260040161068c9061397c565b6113e2612a1b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612b5757612b528361302b565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bb1575060408051601f3d908101601f19168201909252612bae91810190613d73565b60015b612c145760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161068c565b600080516020613df48339815191528114612c835760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161068c565b50612b528383836130c7565b600054610100900460ff16612cb65760405162461bcd60e51b815260040161068c90613d8c565b612a756130f2565b60006010602060ff84168211801590612cdd57508060ff168460ff1611155b949350505050565b600054610100900460ff16612d0c5760405162461bcd60e51b815260040161068c90613d8c565b60fb805460ff19166001179055565b606580546001600160a01b03191690556113e281613129565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612d7c5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612dae6129ff565b6001600160a01b031614612dd45760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16612df757604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314612e255760405163472511eb60e11b815233600482015260240161068c565b6000604051806040016040528086600060088110612e4557612e45613a07565b6020020135815260200186600160088110612e6257612e62613a07565b6020020135905260408051608081018252878201359181019182529192506000919081906060820189600360200201358152508152602001604051806040016040528089600460088110612eb857612eb8613a07565b6020020135815260200189600560088110612ed557612ed5613a07565b60200201359052905260408051808201909152909150600090808860066020020135815260200188600760088110612f0f57612f0f613a07565b6020020135815250905060006040518060200160405280888152509050886001600160a01b03166343753b4d858585856040518563ffffffff1660e01b8152600401612f5e9493929190613a40565b6020604051808303816000875af1925050508015612f99575060408051601f3d908101601f19168201909252612f9691810190613ae7565b60015b612fa557610aa9613b09565b80612fc357604051631e716a8b60e01b815260040160405180910390fd5b61012e869055600087815261012f6020526040902080546001600160801b031916426001600160801b031617905585600260405189907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b6001600160a01b0381163b6130985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161068c565b600080516020613df483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6130d08361317b565b6000825111806130dd5750805b15612b52576130ec83836131bb565b50505050565b600054610100900460ff166131195760405162461bcd60e51b815260040161068c90613d8c565b6131216132b1565b612a756132e0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6131848161302b565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6132235760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161068c565b600080846001600160a01b03168460405161323e9190613dd7565b600060405180830381855af49150503d8060008114613279576040519150601f19603f3d011682016040523d82523d6000602084013e61327e565b606091505b50915091506132a68282604051806060016040528060278152602001613e1460279139613307565b925050505b92915050565b600054610100900460ff166132d85760405162461bcd60e51b815260040161068c90613d8c565b612a75613320565b600054610100900460ff16612a755760405162461bcd60e51b815260040161068c90613d8c565b606083156133165750816117a5565b6117a58383613350565b600054610100900460ff166133475760405162461bcd60e51b815260040161068c90613d8c565b612a7533612d1b565b815115610ac85781518083602001fd5b6001600160a01b03811681146113e257600080fd5b60006020828403121561338757600080fd5b81356117a581613360565b8061010081018310156132ab57600080fd5b803563ffffffff811681146117ee57600080fd5b60008083601f8401126133ca57600080fd5b50813567ffffffffffffffff8111156133e257600080fd5b6020830191508360208260051b85010111156133fd57600080fd5b9250929050565b600080600080600080610180878903121561341e57600080fd5b6134288888613392565b9550610100870135945061343f61012088016133a4565b935061014087013567ffffffffffffffff81111561345c57600080fd5b61346889828a016133b8565b979a969950949794969561016090950135949350505050565b60008083601f84011261349357600080fd5b50813567ffffffffffffffff8111156134ab57600080fd5b6020830191508360208285010111156133fd57600080fd5b60008060008060008061018087890312156134dd57600080fd5b6134e78888613392565b95506134f661010088016133a4565b945061012087013567ffffffffffffffff81111561351357600080fd5b61351f89828a01613481565b979a96995097610140810135966101609091013595509350505050565b60008060008060006080868803121561355457600080fd5b853567ffffffffffffffff81111561356b57600080fd5b61357788828901613481565b9096509450506020860135925060408601359150613597606087016133a4565b90509295509295909350565b600080600080600061018086880312156135bc57600080fd5b853594506020860135935060408601359250606086013591506135978760808801613392565b600080600080600060a086880312156135fa57600080fd5b853560ff8116811461360b57600080fd5b945060208601359350604086013561362281613360565b9250606086013561363281613360565b9150608086013561364281613360565b809150509295509295909350565b60006020828403121561366257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff811182821017156136a5576136a5613669565b6040525050565b600080604083850312156136bf57600080fd5b82356136ca81613360565b915060208381013567ffffffffffffffff808211156136e857600080fd5b818601915086601f8301126136fc57600080fd5b81358181111561370e5761370e613669565b6040519150613726601f8201601f191685018361367f565b808252878482850101111561373a57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060008060008060008060a0898b03121561377457600080fd5b8835975060208901359650604089013567ffffffffffffffff8082111561379a57600080fd5b6137a68c838d016133b8565b909850965060608b01359150808211156137bf57600080fd5b6137cb8c838d016133b8565b909650945060808b01359150808211156137e457600080fd5b506137f18b828c016133b8565b999c989b5096995094979396929594505050565b60008060008060006080868803121561381d57600080fd5b613826866133a4565b94506020860135935060408601359250606086013567ffffffffffffffff81111561385057600080fd5b61385c888289016133b8565b969995985093965092949392505050565b60008060008060008060008060006101a08a8c03121561388c57600080fd5b6138968b8b613392565b98506101008a013597506101208a013567ffffffffffffffff808211156138bc57600080fd5b6138c88d838e016133b8565b90995097506101408c01359150808211156138e257600080fd5b6138ee8d838e016133b8565b90975095506101608c013591508082111561390857600080fd5b506139158c828d016133b8565b9a9d999c50979a969995989497966101800135949350505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6000826139e557634e487b7160e01b600052601260045260246000fd5b500690565b6000602082840312156139fc57600080fd5b81516117a581613360565b634e487b7160e01b600052603260045260246000fd5b8060005b60028110156130ec578151845260209384019390910190600101613a21565b6101208101613a4f8287613a1d565b60408083018660005b6002808210613a675750613aa2565b82518460005b83811015613a8b578251825260209283019290910190600101613a6d565b505050928401925060209190910190600101613a58565b50505050613ab360c0830185613a1d565b61010082018360005b6001811015613adb578151835260209283019290910190600101613abc565b50505095945050505050565b600060208284031215613af957600080fd5b815180151581146117a557600080fd5b600060033d111561163f5760046000803e5060005160e01c90565b600060443d1015613b325790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715613b6257505050505090565b8285019150815181811115613b7a5750505050505090565b843d8701016020828501011115613b945750505050505090565b613ba36020828601018761367f565b509095945050505050565b60005b83811015613bc9578181015183820152602001613bb1565b50506000910152565b6020815260008251806020840152613bf1816040850160208701613bae565b601f01601f19169190910160400192915050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006101a08201905087825286602083015285604083015284606083015261010084608084013760ff8316610180830152979650505050505050565b818103818111156132ab57634e487b7160e01b600052601160045260246000fd5b60006001600160fb1b03831115613cc657600080fd5b8260051b80838637939093019392505050565b888152600060208981840152604083018960005b8a811015613d165763ffffffff613d03836133a4565b1683529183019190830190600101613ced565b5050613d2d613d2682898b613cb0565b8688613cb0565b9c9b505050505050505050505050565b63ffffffff60e01b8660e01b1681528460048201528360248201526000613d68604483018486613cb0565b979650505050505050565b600060208284031215613d8557600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251613de9818460208701613bae565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202258b63db6550ae18ade93a6816c682fce5f6960e9619c49b1085dddff743c4364736f6c63430008150033", + "sourceMap": "443:11607:43:-:0;;;1332:4:23;1289:48;;443:11607:43;;;;;;;;;-1:-1:-1;12497:22:42;:20;:22::i;:::-;443:11607:43;;5928:279:22;5996:13;;;;;;;5995:14;5987:66;;;;-1:-1:-1;;;5987:66:22;;216:2:80;5987:66:22;;;198:21:80;255:2;235:18;;;228:30;294:34;274:18;;;267:62;-1:-1:-1;;;345:18:80;;;338:37;392:19;;5987:66:22;;;;;;;;6067:12;;6082:15;6067:12;;;:30;6063:138;;;6113:12;:30;;-1:-1:-1;;6113:30:22;6128:15;6113:30;;;;;;6162:28;;564:36:80;;;6162:28:22;;552:2:80;537:18;6162:28:22;;;;;;;6063:138;5928:279::o;422:184:80:-;443:11607:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x6080604052600436106101f95760003560e01c8063715018a61161010d578063aa4a729e116100a0578063e30c39781161006f578063e30c3978146105bc578063f134b6ca146105da578063f2038f95146105ef578063f2358e1d14610604578063f2fde38b1461062457600080fd5b8063aa4a729e14610547578063b843b4e514610567578063c70aa72714610587578063d7b0fef1146105a757600080fd5b80638da5cb5b116100dc5780638da5cb5b146104cd5780638e5cdd50146104eb5780638fc22e9f14610512578063a7bba5821461052757600080fd5b8063715018a61461046357806379ba50971461047857806386ec599a1461048d5780638c76a909146104ad57600080fd5b806338c87065116101905780634f1ef2861161015f5780634f1ef286146103c25780634ffbdde5146103d557806352d1902d146103ea578063561f204b146103ff5780636b0566001461044357600080fd5b806338c87065146103135780633e8919b6146103335780633f7c178d1461036057806343f974cb146103ad57600080fd5b80632f059fca116101cc5780632f059fca1461028057806331e4e992146102a0578063354ca120146102d35780633659cfe6146102f357600080fd5b80630e3a12f3146101fe5780632217b2111461022057806323cfdba51461024057806329b6eca914610260575b600080fd5b34801561020a57600080fd5b5061021e610219366004613375565b610644565b005b34801561022c57600080fd5b5061021e61023b366004613404565b61076b565b34801561024c57600080fd5b5061021e61025b3660046134c3565b610b83565b34801561026c57600080fd5b5061021e61027b366004613375565b610f4c565b34801561028c57600080fd5b5061021e61029b366004613375565b610ffa565b3480156102ac57600080fd5b506102c06102bb36600461353c565b6110ef565b6040519081526020015b60405180910390f35b3480156102df57600080fd5b5061021e6102ee3660046135a3565b6111dd565b3480156102ff57600080fd5b5061021e61030e366004613375565b61131d565b34801561031f57600080fd5b5061021e61032e3660046135e2565b6113e5565b34801561033f57600080fd5b5061034861156b565b6040516001600160a01b0390911681526020016102ca565b34801561036c57600080fd5b5061038061037b366004613650565b611642565b60408051825181526020808401516001600160801b031690820152918101511515908201526060016102ca565b3480156103b957600080fd5b506102c06117f3565b61021e6103d03660046136ac565b6118c0565b3480156103e157600080fd5b50610348611979565b3480156103f657600080fd5b506102c0611a4f565b34801561040b57600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610380565b34801561044f57600080fd5b5061021e61045e366004613375565b611b02565b34801561046f57600080fd5b5061021e611bf7565b34801561048457600080fd5b5061021e611c18565b34801561049957600080fd5b506102c06104a8366004613758565b611c8f565b3480156104b957600080fd5b506102c06104c8366004613805565b611d9b565b3480156104d957600080fd5b506033546001600160a01b0316610348565b3480156104f757600080fd5b50610500611e9e565b60405160ff90911681526020016102ca565b34801561051e57600080fd5b50610348611f75565b34801561053357600080fd5b50610348610542366004613375565b61204b565b34801561055357600080fd5b5061021e610562366004613375565b61216d565b34801561057357600080fd5b5061021e61058236600461386d565b612262565b34801561059357600080fd5b5061021e6105a2366004613650565b612483565b3480156105b357600080fd5b506102c06125d8565b3480156105c857600080fd5b506065546001600160a01b0316610348565b3480156105e657600080fd5b506103486126a5565b3480156105fb57600080fd5b5061034861277b565b34801561061057600080fd5b5061021e61061f366004613650565b612851565b34801561063057600080fd5b5061021e61063f366004613375565b61298e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106955760405162461bcd60e51b815260040161068c90613930565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106c76129ff565b6001600160a01b0316146106ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661071057604051630103019560e11b815260040160405180910390fd5b610718612a1b565b61013380546001600160a01b038381166001600160a01b03198316811790935516908160045b6040517fd194b8423e9cb3c7cbebbbc3fe7f79dc2cbe0b40e03270d975abff491504c7b190600090a45050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107b35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107e56129ff565b6001600160a01b03161461080b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661082e57604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b0316331461085c5760405163472511eb60e11b815233600482015260240161068c565b61012e54851461088e5761012e5460405163542fced960e11b815261068c918791600401918252602082015260400190565b600061089d8587848787611d9b565b905060006108cb7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013154604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa15801561091b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093f91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c60006008811061096e5761096e613a07565b602002013581526020018c60016008811061098b5761098b613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f6004600881106109db576109db613a07565b602002013581526020018f6005600881106109f8576109f8613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610a2c57610a2c613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610a629493929190613a40565b6020604051808303816000875af1925050508015610a9d575060408051601f3d908101601f19168201909252610a9a91810190613ae7565b60015b610afd57610aa9613b09565b806308c379a003610ae25750610abd613b24565b80610ac85750610ae4565b8060405162461bcd60e51b815260040161068c9190613bd2565b505b604051631e716a8b60e01b815260040160405180910390fd5b80610b1b57604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600089815261012f6020526040812080546001600160801b031916426001600160801b031617905585906040518b907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a4505b505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bcb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610bfd6129ff565b6001600160a01b031614610c235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16610c4657604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314610c745760405163472511eb60e11b815233600482015260240161068c565b61012e548214610ca65761012e5460405163542fced960e11b815261068c918491600401918252602082015260400190565b6000610cb5858585858a6110ef565b90506000610ce37f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013554604051638a283fc360e01b815263ffffffff8a1660048201529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c600060088110610d8b57610d8b613a07565b602002013581526020018c600160088110610da857610da8613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f600460088110610df857610df8613a07565b602002013581526020018f600560088110610e1557610e15613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610e4957610e49613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610e7f9493929190613a40565b6020604051808303816000875af1925050508015610eba575060408051601f3d908101601f19168201909252610eb791810190613ae7565b60015b610ec657610aa9613b09565b80610ee457604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600086815261012f6020526040902080546001600160801b031916426001600160801b031617905584600160405188907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b600054600290610100900460ff16158015610f6e575060005460ff8083169116105b610f8a5760405162461bcd60e51b815260040161068c90613c05565b6000805461013580546001600160a01b0319166001600160a01b03861617905561ff001961010060ff851661ffff19909316831717169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110425760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166110746129ff565b6001600160a01b03161461109a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166110bd57604051630103019560e11b815260040160405180910390fd5b6110c5612a1b565b61013180546001600160a01b038381166001600160a01b031983168117909355169081600161073e565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036111395760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661116b6129ff565b6001600160a01b0316146111915760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166111b457604051630103019560e11b815260040160405180910390fd5b604051600483028088833781810195865260209095019390935250506040909101902092915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112255760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112576129ff565b6001600160a01b03161461127d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166112a057604051630103019560e11b815260040160405180910390fd5b6112a985612851565b6101335461013454604051634d65479560e11b81526001600160a01b0390921691639aca8f2a916112f191899188918a9189918991600160a81b900460ff1690600401613c53565b60006040518083038186803b15801561130957600080fd5b505afa158015610b78573d6000803e3d6000fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113655760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166113976129ff565b6001600160a01b0316146113bd5760405162461bcd60e51b815260040161068c9061397c565b6113c681612a77565b604080516000808252602082019092526113e291839190612b1f565b50565b600054600190610100900460ff16158015611407575060005460ff8083169116105b6114235760405162461bcd60e51b815260040161068c90613c05565b6000805461ffff191660ff83161761010017905561143f612c8f565b61144886612cbe565b61146a57604051630220cee360e61b815260ff8716600482015260240161068c565b610134805460ff60a81b1916600160a81b60ff891602179055610e106101305561012e85905561013180546001600160a01b03199081166001600160a01b0387811691909117909255610132805482168684161790556101338054821685841617905560335461012d80549190931691161790556114e6612ce5565b6040805160ff88168152602081018790527fd1bcc66c061c32a21f569d138c2dadef4a38a0636309881954af5f44010ec1d8910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036115b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166115e76129ff565b6001600160a01b03161461160d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661163057604051630103019560e11b815260040160405180910390fd5b50610135546001600160a01b03165b90565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116a75760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166116d96129ff565b6001600160a01b0316146116ff5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661172257604051630103019560e11b815260040160405180910390fd5b61012e5482036117515750506040805160608101825261012e5481526000602082015260019181019190915290565b600082815261012f60205260408120546001600160801b0316908190036117ac5760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b610130546000906117c66001600160801b03841642613c8f565b604080516060810182528781526001600160801b039095166020860152911015908301525090505b919050565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361183d5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661186f6129ff565b6001600160a01b0316146118955760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166118b857604051630103019560e11b815260040160405180910390fd5b506101305490565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119085760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661193a6129ff565b6001600160a01b0316146119605760405162461bcd60e51b815260040161068c9061397c565b61196982612a77565b61197582826001612b1f565b5050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119c35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166119f56129ff565b6001600160a01b031614611a1b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611a3e57604051630103019560e11b815260040160405180910390fd5b50610132546001600160a01b031690565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611aef5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161068c565b50600080516020613df483398151915290565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b4a5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b7c6129ff565b6001600160a01b031614611ba25760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611bc557604051630103019560e11b815260040160405180910390fd5b611bcd612a1b565b61013280546001600160a01b038381166001600160a01b031983168117909355169081600361073e565b611bff612a1b565b6040516377aeb0ad60e01b815260040160405180910390fd5b60655433906001600160a01b03168114611c865760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161068c565b6113e281612d1b565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611cd95760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d0b6129ff565b6001600160a01b031614611d315760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611d5457604051630103019560e11b815260040160405180910390fd5b60008989898989898989604051602001611d75989796959493929190613cd9565b60408051601f1981840301815291905280516020909101209a9950505050505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611de55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611e176129ff565b6001600160a01b031614611e3d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611e6057604051630103019560e11b815260040160405180910390fd5b60008686868686604051602001611e7b959493929190613d3d565b60408051601f198184030181529190528051602090910120979650505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611ee85760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611f1a6129ff565b6001600160a01b031614611f405760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611f6357604051630103019560e11b815260040160405180910390fd5b5061013454600160a81b900460ff1690565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611fbf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ff16129ff565b6001600160a01b0316146120175760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661203a57604051630103019560e11b815260040160405180910390fd5b50610131546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120955760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120c76129ff565b6001600160a01b0316146120ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661211057604051630103019560e11b815260040160405180910390fd5b612118612a1b565b61012d80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f5a674c516c196404869e5f502b5634ce442416bb016dde54b5de4c812cc019e690600090a392915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036121b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166121e76129ff565b6001600160a01b03161461220d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661223057604051630103019560e11b815260040160405180910390fd5b612238612a1b565b61013580546001600160a01b038381166001600160a01b031983168117909355169081600261073e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122aa5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122dc6129ff565b6001600160a01b0316146123025760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661232557604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b031633146123535760405163472511eb60e11b815233600482015260240161068c565b61012e5488146123855761012e5460405163542fced960e11b815261068c918a91600401918252602082015260400190565b85841415806123945750858214155b156123b25760405163a0b1d72d60e01b815260040160405180910390fd5b60006123c489838a8a8a8a8a8a611c8f565b905060006123f27f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013254604051638a283fc360e01b8152600481018b90529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246691906139ea565b9050612475818d848e88612d34565b505050505050505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124cb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166124fd6129ff565b6001600160a01b0316146125235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661254657604051630103019560e11b815260040160405180910390fd5b61254e612a1b565b8060000361259e5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e0000000000604482015260640161068c565b610130805490829055604051829082907ff62a6f06fde00a303cd5939e6b53762854412c96a196cda26720cedd28af9e7090600090a35050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126225760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166126546129ff565b6001600160a01b03161461267a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661269d57604051630103019560e11b815260040160405180910390fd5b5061012e5490565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126ef5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127216129ff565b6001600160a01b0316146127475760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661276a57604051630103019560e11b815260040160405180910390fd5b5061012d546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036127c55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127f76129ff565b6001600160a01b03161461281d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661284057604051630103019560e11b815260040160405180910390fd5b50610133546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036128995760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166128cb6129ff565b6001600160a01b0316146128f15760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661291457604051630103019560e11b815260040160405180910390fd5b61012e5481146113e257600081815261012f60205260408120546001600160801b0316908190036129585760405163ddae3b7160e01b815260040160405180910390fd5b6101305461296f6001600160801b03831642613c8f565b111561197557604051631d739acf60e11b815260040160405180910390fd5b612996612a1b565b606580546001600160a01b0383166001600160a01b031990911681179091556129c76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080516020613df4833981519152546001600160a01b031690565b6033546001600160a01b03163314612a755760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161068c565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612abf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612af16129ff565b6001600160a01b031614612b175760405162461bcd60e51b815260040161068c9061397c565b6113e2612a1b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612b5757612b528361302b565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bb1575060408051601f3d908101601f19168201909252612bae91810190613d73565b60015b612c145760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161068c565b600080516020613df48339815191528114612c835760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161068c565b50612b528383836130c7565b600054610100900460ff16612cb65760405162461bcd60e51b815260040161068c90613d8c565b612a756130f2565b60006010602060ff84168211801590612cdd57508060ff168460ff1611155b949350505050565b600054610100900460ff16612d0c5760405162461bcd60e51b815260040161068c90613d8c565b60fb805460ff19166001179055565b606580546001600160a01b03191690556113e281613129565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612d7c5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612dae6129ff565b6001600160a01b031614612dd45760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16612df757604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314612e255760405163472511eb60e11b815233600482015260240161068c565b6000604051806040016040528086600060088110612e4557612e45613a07565b6020020135815260200186600160088110612e6257612e62613a07565b6020020135905260408051608081018252878201359181019182529192506000919081906060820189600360200201358152508152602001604051806040016040528089600460088110612eb857612eb8613a07565b6020020135815260200189600560088110612ed557612ed5613a07565b60200201359052905260408051808201909152909150600090808860066020020135815260200188600760088110612f0f57612f0f613a07565b6020020135815250905060006040518060200160405280888152509050886001600160a01b03166343753b4d858585856040518563ffffffff1660e01b8152600401612f5e9493929190613a40565b6020604051808303816000875af1925050508015612f99575060408051601f3d908101601f19168201909252612f9691810190613ae7565b60015b612fa557610aa9613b09565b80612fc357604051631e716a8b60e01b815260040160405180910390fd5b61012e869055600087815261012f6020526040902080546001600160801b031916426001600160801b031617905585600260405189907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b6001600160a01b0381163b6130985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161068c565b600080516020613df483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6130d08361317b565b6000825111806130dd5750805b15612b52576130ec83836131bb565b50505050565b600054610100900460ff166131195760405162461bcd60e51b815260040161068c90613d8c565b6131216132b1565b612a756132e0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6131848161302b565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6132235760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161068c565b600080846001600160a01b03168460405161323e9190613dd7565b600060405180830381855af49150503d8060008114613279576040519150601f19603f3d011682016040523d82523d6000602084013e61327e565b606091505b50915091506132a68282604051806060016040528060278152602001613e1460279139613307565b925050505b92915050565b600054610100900460ff166132d85760405162461bcd60e51b815260040161068c90613d8c565b612a75613320565b600054610100900460ff16612a755760405162461bcd60e51b815260040161068c90613d8c565b606083156133165750816117a5565b6117a58383613350565b600054610100900460ff166133475760405162461bcd60e51b815260040161068c90613d8c565b612a7533612d1b565b815115610ac85781518083602001fd5b6001600160a01b03811681146113e257600080fd5b60006020828403121561338757600080fd5b81356117a581613360565b8061010081018310156132ab57600080fd5b803563ffffffff811681146117ee57600080fd5b60008083601f8401126133ca57600080fd5b50813567ffffffffffffffff8111156133e257600080fd5b6020830191508360208260051b85010111156133fd57600080fd5b9250929050565b600080600080600080610180878903121561341e57600080fd5b6134288888613392565b9550610100870135945061343f61012088016133a4565b935061014087013567ffffffffffffffff81111561345c57600080fd5b61346889828a016133b8565b979a969950949794969561016090950135949350505050565b60008083601f84011261349357600080fd5b50813567ffffffffffffffff8111156134ab57600080fd5b6020830191508360208285010111156133fd57600080fd5b60008060008060008061018087890312156134dd57600080fd5b6134e78888613392565b95506134f661010088016133a4565b945061012087013567ffffffffffffffff81111561351357600080fd5b61351f89828a01613481565b979a96995097610140810135966101609091013595509350505050565b60008060008060006080868803121561355457600080fd5b853567ffffffffffffffff81111561356b57600080fd5b61357788828901613481565b9096509450506020860135925060408601359150613597606087016133a4565b90509295509295909350565b600080600080600061018086880312156135bc57600080fd5b853594506020860135935060408601359250606086013591506135978760808801613392565b600080600080600060a086880312156135fa57600080fd5b853560ff8116811461360b57600080fd5b945060208601359350604086013561362281613360565b9250606086013561363281613360565b9150608086013561364281613360565b809150509295509295909350565b60006020828403121561366257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff811182821017156136a5576136a5613669565b6040525050565b600080604083850312156136bf57600080fd5b82356136ca81613360565b915060208381013567ffffffffffffffff808211156136e857600080fd5b818601915086601f8301126136fc57600080fd5b81358181111561370e5761370e613669565b6040519150613726601f8201601f191685018361367f565b808252878482850101111561373a57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060008060008060008060a0898b03121561377457600080fd5b8835975060208901359650604089013567ffffffffffffffff8082111561379a57600080fd5b6137a68c838d016133b8565b909850965060608b01359150808211156137bf57600080fd5b6137cb8c838d016133b8565b909650945060808b01359150808211156137e457600080fd5b506137f18b828c016133b8565b999c989b5096995094979396929594505050565b60008060008060006080868803121561381d57600080fd5b613826866133a4565b94506020860135935060408601359250606086013567ffffffffffffffff81111561385057600080fd5b61385c888289016133b8565b969995985093965092949392505050565b60008060008060008060008060006101a08a8c03121561388c57600080fd5b6138968b8b613392565b98506101008a013597506101208a013567ffffffffffffffff808211156138bc57600080fd5b6138c88d838e016133b8565b90995097506101408c01359150808211156138e257600080fd5b6138ee8d838e016133b8565b90975095506101608c013591508082111561390857600080fd5b506139158c828d016133b8565b9a9d999c50979a969995989497966101800135949350505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6000826139e557634e487b7160e01b600052601260045260246000fd5b500690565b6000602082840312156139fc57600080fd5b81516117a581613360565b634e487b7160e01b600052603260045260246000fd5b8060005b60028110156130ec578151845260209384019390910190600101613a21565b6101208101613a4f8287613a1d565b60408083018660005b6002808210613a675750613aa2565b82518460005b83811015613a8b578251825260209283019290910190600101613a6d565b505050928401925060209190910190600101613a58565b50505050613ab360c0830185613a1d565b61010082018360005b6001811015613adb578151835260209283019290910190600101613abc565b50505095945050505050565b600060208284031215613af957600080fd5b815180151581146117a557600080fd5b600060033d111561163f5760046000803e5060005160e01c90565b600060443d1015613b325790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715613b6257505050505090565b8285019150815181811115613b7a5750505050505090565b843d8701016020828501011115613b945750505050505090565b613ba36020828601018761367f565b509095945050505050565b60005b83811015613bc9578181015183820152602001613bb1565b50506000910152565b6020815260008251806020840152613bf1816040850160208701613bae565b601f01601f19169190910160400192915050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006101a08201905087825286602083015285604083015284606083015261010084608084013760ff8316610180830152979650505050505050565b818103818111156132ab57634e487b7160e01b600052601160045260246000fd5b60006001600160fb1b03831115613cc657600080fd5b8260051b80838637939093019392505050565b888152600060208981840152604083018960005b8a811015613d165763ffffffff613d03836133a4565b1683529183019190830190600101613ced565b5050613d2d613d2682898b613cb0565b8688613cb0565b9c9b505050505050505050505050565b63ffffffff60e01b8660e01b1681528460048201528360248201526000613d68604483018486613cb0565b979650505050505050565b600060208284031215613d8557600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251613de9818460208701613bae565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202258b63db6550ae18ade93a6816c682fce5f6960e9619c49b1085dddff743c4364736f6c63430008150033", + "sourceMap": "443:11607:43:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37178:393:42;;;;;;;;;;-1:-1:-1;37178:393:42;;;;;:::i;:::-;;:::i;:::-;;17580:2498;;;;;;;;;;-1:-1:-1;17580:2498:42;;;;;:::i;:::-;;:::i;6380:2438:43:-;;;;;;;;;;-1:-1:-1;6380:2438:43;;;;;:::i;:::-;;:::i;3800:152::-;;;;;;;;;;-1:-1:-1;3800:152:43;;;;;:::i;:::-;;:::i;34738:423:42:-;;;;;;;;;;-1:-1:-1;34738:423:42;;;;;:::i;:::-;;:::i;11363:685:43:-;;;;;;;;;;-1:-1:-1;11363:685:43;;;;;:::i;:::-;;:::i;:::-;;;4125:25:80;;;4113:2;4098:18;11363:685:43;;;;;;;;40699:508:42;;;;;;;;;;-1:-1:-1;40699:508:42;;;;;:::i;:::-;;:::i;3317:197:23:-;;;;;;;;;;-1:-1:-1;3317:197:23;;;;;:::i;:::-;;:::i;13806:1014:42:-;;;;;;;;;;-1:-1:-1;13806:1014:42;;;;;:::i;:::-;;:::i;9156:228:43:-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;6024:32:80;;;6006:51;;5994:2;5979:18;9156:228:43;5860:203:80;32299:567:42;;;;;;;;;;-1:-1:-1;32299:567:42;;;;;:::i;:::-;;:::i;:::-;;;;6471:13:80;;6453:32;;6545:4;6533:17;;;6527:24;-1:-1:-1;;;;;6523:65:80;6501:20;;;6494:95;6647:17;;;6641:24;6634:32;6627:40;6605:20;;;6598:70;6441:2;6426:18;32299:567:42;6253:421:80;37747:189:42;;;;;;;;;;;;;:::i;3763:222:23:-;;;;;;:::i;:::-;;:::i;35454:227:42:-;;;;;;;;;;;;;:::i;3006:131:23:-;;;;;;;;;;;;;:::i;7130:120:42:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;7218:25:42;;;;;;;;;;;;;;;;;;;;7130:120;;36071:416;;;;;;;;;;-1:-1:-1;36071:416:42;;;;;:::i;:::-;;:::i;4649:109:44:-;;;;;;;;;;;;;:::i;2010:206:17:-;;;;;;;;;;;;;:::i;31089:465:42:-;;;;;;;;;;-1:-1:-1;31089:465:42;;;;;:::i;:::-;;:::i;29135:413::-;;;;;;;;;;-1:-1:-1;29135:413:42;;;;;:::i;:::-;;:::i;1441:85:18:-;;;;;;;;;;-1:-1:-1;1513:6:18;;-1:-1:-1;;;;;1513:6:18;1441:85;;38714:119:42;;;;;;;;;;;;;:::i;:::-;;;10258:4:80;10246:17;;;10228:36;;10216:2;10201:18;38714:119:42;10086:184:80;34179:231:42;;;;;;;;;;;;;:::i;39480:384::-;;;;;;;;;;-1:-1:-1;39480:384:42;;;;;:::i;:::-;;:::i;9704:418:43:-;;;;;;;;;;-1:-1:-1;9704:418:43;;;;;:::i;:::-;;:::i;22820:1590:42:-;;;;;;;;;;-1:-1:-1;22820:1590:42;;;;;:::i;:::-;;:::i;38168:402::-;;;;;;;;;;-1:-1:-1;38168:402:42;;;;;:::i;:::-;;:::i;31682:121::-;;;;;;;;;;;;;:::i;1123:99:17:-;;;;;;;;;;-1:-1:-1;1202:13:17;;-1:-1:-1;;;;;1202:13:17;1123:99;;39054:133:42;;;;;;;;;;;;;:::i;36670:205::-;;;;;;;;;;;;;:::i;33309:638::-;;;;;;;;;;-1:-1:-1;33309:638:42;;;;;:::i;:::-;;:::i;1415:178:17:-;;;;;;;;;;-1:-1:-1;1415:178:17;;;;;:::i;:::-;;:::i;37178:393:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;;;;;;;;;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;37378:17:42::3;::::0;;-1:-1:-1;;;;;37405:31:42;;::::3;-1:-1:-1::0;;;;;;37405:31:42;::::3;::::0;::::3;::::0;;;37378:17:::3;::::0;;37482:28:::3;37451:113;;::::0;::::3;::::0;;;::::3;37335:236;37178:393:::0;:::o;17580:2498::-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;17871:11:::3;;17860:7;:22;17856:95;;17928:11;::::0;17905:35:::3;::::0;-1:-1:-1;;;17905:35:42;;::::3;::::0;17919:7;;17905:35:::3;;12764:25:80::0;;;12820:2;12805:18;;12798:34;12752:2;12737:18;;12590:248;17856:95:42::3;18042:17;18062:112;18114:10;18126:7;18135:8;18145:19;;18062:38;:112::i;:::-;18042:132:::0;-1:-1:-1;18445:22:42::3;18470:39;4368:77;18042:132:::0;18470:39:::3;:::i;:::-;18639:23;::::0;:66:::3;::::0;-1:-1:-1;;;18639:66:42;;::::3;::::0;::::3;4125:25:80::0;;;18445:64:42;;-1:-1:-1;18593:31:42::3;::::0;-1:-1:-1;;;;;18639:23:42;;::::3;::::0;:38:::3;::::0;4098:18:80;;18639:66:42::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18593:112;;18774:17;-1:-1:-1::0;;;;;18774:29:42::3;;:267;;;;;;;;18818:14;18833:1;18818:17;;;;;;;:::i;:::-;;;;;18774:267;;;;18837:14;18852:1;18837:17;;;;;;;:::i;:::-;;;;;18774:267:::0;;::::3;::::0;;;;;;;18871:17;;::::3;;18774:267:::0;;::::3;::::0;;;;;;;;;18871:14;18905:1:::3;18890:17;;;;18774:267;;::::0;::::3;;;;;;;;;;;;18911:14;18926:1;18911:17;;;;;;;:::i;:::-;;;;;18774:267;;;;18930:14;18945:1;18930:17;;;;;;;:::i;:::-;;;;;18774:267:::0;;;;::::3;::::0;;;;::::3;::::0;;;;18964:14;18979:1:::3;18964:17;;;;18774:267;;;;18983:14;18998:1;18983:17;;;;;;;:::i;:::-;;;;;18774:267;;::::0;::::3;;;;;;;;19016:14;18774:267;;::::0;::::3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;18774:267:42::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;18774:267:42::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;18770:1302;;;;:::i;:::-;;;::::0;::::3;;;;;:::i;:::-;;;;;;;;19824:9;19817:17;;-1:-1:-1::0;;;19817:17:42::3;;;;;;;;:::i;18770:1302::-;;;20037:24;;-1:-1:-1::0;;;20037:24:42::3;;;;;;;;;;;18770:1302;19161:14;19156:85;;19202:24;;-1:-1:-1::0;;;19202:24:42::3;;;;;;;;;;;19156:85;19409:11;:22:::0;;;19577:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;19577:47:42::3;19608:15;-1:-1:-1::0;;;;;19577:47:42::3;;::::0;;19409:22;;19644:52:::3;::::0;19656:7;;19644:52:::3;::::0;;;::::3;19042:665;18770:1302;17846:2232;;;17580:2498:::0;;;;;;:::o;6380:2438:43:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;6665:11:43::3;;6654:7;:22;6650:95;;6722:11;::::0;6699:35:::3;::::0;-1:-1:-1;;;6699:35:43;;::::3;::::0;6713:7;;6699:35:::3;;12764:25:80::0;;;12820:2;12805:18;;12798:34;12752:2;12737:18;;12590:248;6650:95:43::3;6836:17;6868:87;6903:21;;6926:7;6935:8;6945:9;6868:34;:87::i;:::-;6836:119:::0;-1:-1:-1;7226:22:43::3;7251:39;4368:77:42;6836:119:43::0;7251:39:::3;:::i;:::-;7407:22;::::0;:48:::3;::::0;-1:-1:-1;;;7407:48:43;;17424:10:80;17412:23;;7407:48:43::3;::::0;::::3;17394:42:80::0;7226:64:43;;-1:-1:-1;7374:30:43::3;::::0;-1:-1:-1;;;;;7407:22:43;;::::3;::::0;:37:::3;::::0;17367:18:80;;7407:48:43::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7374:81;;7524:16;-1:-1:-1::0;;;;;7524:28:43::3;;:258;;;;;;;;7567:13;7581:1;7567:16;;;;;;;:::i;:::-;;;;;7524:258;;;;7585:13;7599:1;7585:16;;;;;;;:::i;:::-;;;;;7524:258:::0;;::::3;::::0;;;;;;;7618:16;;::::3;;7524:258:::0;;::::3;::::0;;;;;;;;;7618:13;7650:1:::3;7636:16;;;;7524:258;;::::0;::::3;;;;;;;;;;;;7656:13;7670:1;7656:16;;;;;;;:::i;:::-;;;;;7524:258;;;;7674:13;7688:1;7674:16;;;;;;;:::i;:::-;;;;;7524:258:::0;;;;::::3;::::0;;;;::::3;::::0;;;;7707:13;7721:1:::3;7707:16;;;;7524:258;;;;7725:13;7739:1;7725:16;;;;;;;:::i;:::-;;;;;7524:258;;::::0;::::3;;;;;;;;7757:14;7524:258;;::::0;::::3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;7524:258:43::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;7524:258:43::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;7520:1292;;;;:::i;:::-;7902:14;7897:85;;7943:24;;-1:-1:-1::0;;;7943:24:43::3;;;;;;;;;;;7897:85;8150:11;:22:::0;;;8318:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;8318:47:43::3;8349:15;-1:-1:-1::0;;;;;8318:47:43::3;;::::0;;8150:22;-1:-1:-1;8385:51:43::3;::::0;8397:7;;8385:51:::3;::::0;;;::::3;7783:664;6640:2178;;;6380:2438:::0;;;;;;:::o;3800:152::-;4871:13:22;;3886:1:43;;4871:13:22;;;;;4870:14;:40;;;;-1:-1:-1;4888:12:22;;:22;;;;:12;;:22;4870:40;4862:99;;;;-1:-1:-1;;;4862:99:22;;;;;;;:::i;:::-;4971:12;:22;;3899::43::1;:46:::0;;-1:-1:-1;;;;;;3899:46:43::1;-1:-1:-1::0;;;;;3899:46:43;::::1;;::::0;;-1:-1:-1;;4971:22:22;;;;-1:-1:-1;;5003:20:22;;;;;;5044:21;;;;5080:20;;10228:36:80;;;5080:20:22;;10216:2:80;10201:18;5080:20:22;;;;;;;3800:152:43;;:::o;34738:423:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;34954:23:42::3;::::0;;-1:-1:-1;;;;;34987:34:42;;::::3;-1:-1:-1::0;;;;;;34987:34:42;::::3;::::0;::::3;::::0;;;34954:23:::3;::::0;;;35036:118:::3;::::0;11363:685:43;11591:12;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;11663:4:43::2;11657:11;11719:1;11708:9;11704:17;11790:15;11760:28;11747:11;11734:72;11838:33:::0;;::::2;11884:28:::0;;;11949:2:::2;11932:20:::0;;::::2;11925:38:::0;;;;-1:-1:-1;;12011:2:43::2;12007:24:::0;;::::2;11984:48:::0;;;11363:685;-1:-1:-1;;11363:685:43:o;40699:508:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;40987:22:42::2;41004:4;40987:16;:22::i;:::-;41075:17;::::0;41181:9:::2;::::0;41075:125:::2;::::0;-1:-1:-1;;;41075:125:42;;-1:-1:-1;;;;;41075:17:42;;::::2;::::0;:29:::2;::::0;:125:::2;::::0;41118:4;;41124:13;;41139:10;;41151:21;;41174:5;;-1:-1:-1;;;41181:9:42;::::2;;;::::0;41075:125:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;3317:197:23::0;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;3400:36:::1;3418:17;3400;:36::i;:::-;3487:12;::::0;;3497:1:::1;3487:12:::0;;;::::1;::::0;::::1;::::0;;;3446:61:::1;::::0;3468:17;;3487:12;3446:21:::1;:61::i;:::-;3317:197:::0;:::o;13806:1014:42:-;4871:13:22;;14060:1:42;;4871:13:22;;;;;4870:14;:40;;;;-1:-1:-1;4888:12:22;;:22;;;;:12;;:22;4870:40;4862:99;;;;-1:-1:-1;;;4862:99:22;;;;;;;:::i;:::-;4971:12;:22;;-1:-1:-1;;5003:20:22;4971:22;;;5003:20;4971:22;5003:20;;;14148:16:42::1;:14;:16::i;:::-;14180:48;14217:10;14180:36;:48::i;:::-;14175:119;;14251:32;::::0;-1:-1:-1;;;14251:32:42;;10258:4:80;10246:17;;14251:32:42::1;::::0;::::1;10228:36:80::0;10201:18;;14251:32:42::1;10086:184:80::0;14175:119:42::1;14361:9;:22:::0;;-1:-1:-1;;;;14361:22:42::1;-1:-1:-1::0;;;14361:22:42::1;::::0;::::1;;;::::0;;14413:7:::1;14393:17;:27:::0;14430:11:::1;:25:::0;;;14465:23:::1;:50:::0;;-1:-1:-1;;;;;;14465:50:42;;::::1;-1:-1:-1::0;;;;;14465:50:42;;::::1;::::0;;;::::1;::::0;;;14525:23:::1;:47:::0;;;::::1;::::0;;::::1;;::::0;;14582:17:::1;:38:::0;;;::::1;::::0;;::::1;;::::0;;1513:6:18;;14630:17:42::1;:27:::0;;1513:6:18;;;;14630:27:42;::::1;;::::0;;14717:18:::1;:16;:18::i;:::-;14751:62;::::0;;18673:4:80;18661:17;;18643:36;;18710:2;18695:18;;18688:34;;;14751:62:42::1;::::0;18616:18:80;14751:62:42::1;;;;;;;5060:5:22::0;5044:21;;-1:-1:-1;;5044:21:22;;;5080:20;;10258:4:80;10246:17;;10228:36;;5080:20:22;;10216:2:80;10201:18;5080:20:22;;;;;;;13806:1014:42;;;;;;:::o;9156:228:43:-;9316:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;9354:22:43::2;::::0;-1:-1:-1;;;;;9354:22:43::2;1144:1:77;9156:228:43::0;:::o;32299:567:42:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;32478:11:42::2;;32470:4;:19:::0;32466:394:::2;;-1:-1:-1::0;;32512:30:42::2;::::0;;::::2;::::0;::::2;::::0;;32521:11:::2;::::0;32512:30;;-1:-1:-1;32512:30:42::2;::::0;::::2;::::0;32537:4:::2;32512:30:::0;;;;;;;;32299:567::o;32466:394::-:2;32573:21;32597:17:::0;;;:11:::2;:17;::::0;;;;;-1:-1:-1;;;;;32597:17:42::2;::::0;32633:18;;;32629:78:::2;;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;;;;;7218:25:42;;;;;;;;;;;;;;;;;;;;32678:14:::2;32671:21:::0;32299:567;-1:-1:-1;;;32299:567:42:o;32629:78::-:2;32772:17;::::0;32721:12:::2;::::0;32738:31:::2;-1:-1:-1::0;;;;;32738:31:42;::::2;:15;:31;:::i;:::-;32811:38;::::0;;::::2;::::0;::::2;::::0;;;;;-1:-1:-1;;;;;32811:38:42;;::::2;;::::0;::::2;::::0;32738:51;-1:-1:-1;32736:54:42::2;32811:38:::0;;;;-1:-1:-1;32811:38:42;-1:-1:-1;32466:394:42::2;32299:567:::0;;;:::o;37747:189::-;37882:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;37912:17:42::2;::::0;37747:189;:::o;3763:222:23:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;3880:36:::1;3898:17;3880;:36::i;:::-;3926:52;3948:17;3967:4;3973;3926:21;:52::i;:::-;3763:222:::0;;:::o;35454:227:42:-;35612:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;35650:23:42::2;::::0;-1:-1:-1;;;;;35650:23:42::2;35454:227:::0;:::o;3006:131:23:-;3084:7;2324:4;-1:-1:-1;;;;;2333:6:23;2316:23;;2308:92;;;;-1:-1:-1;;;2308:92:23;;19165:2:80;2308:92:23;;;19147:21:80;19204:2;19184:18;;;19177:30;19243:34;19223:18;;;19216:62;19314:26;19294:18;;;19287:54;19358:19;;2308:92:23;18963:420:80;2308:92:23;-1:-1:-1;;;;;;;;;;;;3006:131:23;:::o;36071:416:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;36283:23:42::3;::::0;;-1:-1:-1;;;;;36316:34:42;;::::3;-1:-1:-1::0;;;;;;36316:34:42;::::3;::::0;::::3;::::0;;;36283:23:::3;::::0;;36396:36:::3;36365:115;::::0;4649:109:44;1334:13:18;:11;:13::i;:::-;4726:25:44::1;;-1:-1:-1::0;;;4726:25:44::1;;;;;;;;;;;2010:206:17::0;1202:13;;929:10:25;;-1:-1:-1;;;;;1202:13:17;2103:24;;2095:78;;;;-1:-1:-1;;;2095:78:17;;19590:2:80;2095:78:17;;;19572:21:80;19629:2;19609:18;;;19602:30;19668:34;19648:18;;;19641:62;-1:-1:-1;;;19719:18:80;;;19712:39;19768:19;;2095:78:17;19388:405:80;2095:78:17;2183:26;2202:6;2183:18;:26::i;31089:465:42:-;31366:12;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;31390:24:42::2;31446:7;31455:8;31465:11;;31478:13;;31493;;31429:78;;;;;;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;31429:78:42;;::::2;::::0;;;;;;31525:22;;31429:78:::2;31525:22:::0;;::::2;::::0;;31089:465;-1:-1:-1;;;;;;;;;;31089:465:42:o;29135:413::-;29370:12;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;29394:24:42::2;29450:10;29462:7;29471:8;29481:19;;29433:68;;;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;29433:68:42;;::::2;::::0;;;;;;29519:22;;29433:68:::2;29519:22:::0;;::::2;::::0;;29135:413;-1:-1:-1;;;;;;;29135:413:42:o;38714:119::-;38793:5;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;38817:9:42::2;::::0;-1:-1:-1;;;38817:9:42;::::2;;;::::0;38714:119::o;34179:231::-;34341:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;34379:23:42::2;::::0;-1:-1:-1;;;;;34379:23:42::2;34179:231:::0;:::o;39480:384::-;39646:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;39691:17:42::3;::::0;;-1:-1:-1;;;;;39718:39:42;;::::3;-1:-1:-1::0;;;;;;39718:39:42;::::3;::::0;::::3;::::0;;;39772:57:::3;::::0;39691:17;::::3;::::0;39718:39;39691:17;;39772:57:::3;::::0;39669:19:::3;::::0;39772:57:::3;39846:11:::0;39480:384;-1:-1:-1;;39480:384:42:o;9704:418:43:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;9918:22:43::3;::::0;;-1:-1:-1;;;;;9950:33:43;;::::3;-1:-1:-1::0;;;;;;9950:33:43;::::3;::::0;::::3;::::0;;;9918:22:::3;::::0;;10029:38:::3;9998:117;::::0;22820:1590:42;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;23154:11:::3;;23143:7;:22;23139:95;;23211:11;::::0;23188:35:::3;::::0;-1:-1:-1;;;23188:35:42;;::::3;::::0;23202:7;;23188:35:::3;;12764:25:80::0;;;12820:2;12805:18;;12798:34;12752:2;12737:18;;12590:248;23139:95:42::3;23322:42:::0;;::::3;;::::0;:88:::3;;-1:-1:-1::0;23368:42:42;;::::3;;23322:88;23305:172;;;23442:24;;-1:-1:-1::0;;;23442:24:42::3;;;;;;;;;;;23305:172;23564:17;23584:116;23630:7;23639:8;23649:11;;23662:13;;23677;;23584:32;:116::i;:::-;23564:136:::0;-1:-1:-1;23971:24:42::3;23998:39;4368:77;23564:136:::0;23998:39:::3;:::i;:::-;24152:23;::::0;:58:::3;::::0;-1:-1:-1;;;24152:58:42;;::::3;::::0;::::3;4125:25:80::0;;;23971:66:42;;-1:-1:-1;24121:28:42::3;::::0;-1:-1:-1;;;;;24152:23:42;;::::3;::::0;:38:::3;::::0;4098:18:80;;24152:58:42::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24121:89;;24316:87;24338:14;24354:11;24367:16;24385:7;24394:8;24316:21;:87::i;:::-;23129:1281;;;22820:1590:::0;;;;;;;;;:::o;38168:402::-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;38330::42::3;38347:1;38330:18:::0;38326:86:::3;;38364:37;::::0;-1:-1:-1;;;38364:37:42;;21716:2:80;38364:37:42::3;::::0;::::3;21698:21:80::0;21755:2;21735:18;;;21728:30;21794:29;21774:18;;;21767:57;21841:18;;38364:37:42::3;21514:351:80::0;38326:86:42::3;38441:17;::::0;;38468:33;;;;38517:46:::3;::::0;38488:13;;38441:17;;38517:46:::3;::::0;38421:17:::3;::::0;38517:46:::3;38316:254;38168:402:::0;:::o;31682:121::-;31759:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;31785:11:42::2;::::0;31682:121;:::o;39054:133::-;39137:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;39163:17:42::2;::::0;-1:-1:-1;;;;;39163:17:42::2;39054:133:::0;:::o;36670:205::-;36812:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;36850:17:42::2;::::0;-1:-1:-1;;;;;36850:17:42::2;36670:205:::0;:::o;33309:638::-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;33461:11:42::2;::::0;33449:56;;33488:7:::2;33449:56;33580:21;33604:17:::0;;;:11:::2;:17;::::0;;;;;-1:-1:-1;;;;;33604:17:42::2;::::0;33704:18;;;33700:73:::2;;33745:17;;-1:-1:-1::0;;;33745:17:42::2;;;;;;;;;;;33700:73;33877:17;::::0;33843:31:::2;-1:-1:-1::0;;;;;33843:31:42;::::2;:15;:31;:::i;:::-;:51;33839:102;;;33917:13;;-1:-1:-1::0;;;33917:13:42::2;;;;;;;;;;;1415:178:17::0;1334:13:18;:11;:13::i;:::-;1504::17::1;:24:::0;;-1:-1:-1;;;;;1504:24:17;::::1;-1:-1:-1::0;;;;;;1504:24:17;;::::1;::::0;::::1;::::0;;;1568:7:::1;1513:6:18::0;;-1:-1:-1;;;;;1513:6:18;;1441:85;1568:7:17::1;-1:-1:-1::0;;;;;1543:43:17::1;;;;;;;;;;;1415:178:::0;:::o;1563:151:20:-;-1:-1:-1;;;;;;;;;;;1642:65:20;-1:-1:-1;;;;;1642:65:20;;1563:151::o;1599:130:18:-;1513:6;;-1:-1:-1;;;;;1513:6:18;929:10:25;1662:23:18;1654:68;;;;-1:-1:-1;;;1654:68:18;;22072:2:80;1654:68:18;;;22054:21:80;;;22091:18;;;22084:30;22150:34;22130:18;;;22123:62;22202:18;;1654:68:18;21870:356:80;1654:68:18;1599:130::o;4067:204:44:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1334:13:18::1;:11;:13::i;2938:974:20:-:0;951:66;3384:59;;;3380:526;;;3459:37;3478:17;3459:18;:37::i;:::-;2938:974;;;:::o;3380:526::-;3560:17;-1:-1:-1;;;;;3531:61:20;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3531:63:20;;;;;;;;-1:-1:-1;;3531:63:20;;;;;;;;;;;;:::i;:::-;;;3527:302;;3758:56;;-1:-1:-1;;;3758:56:20;;22622:2:80;3758:56:20;;;22604:21:80;22661:2;22641:18;;;22634:30;22700:34;22680:18;;;22673:62;-1:-1:-1;;;22751:18:80;;;22744:44;22805:19;;3758:56:20;22420:410:80;3527:302:20;-1:-1:-1;;;;;;;;;;;3644:28:20;;3636:82;;;;-1:-1:-1;;;3636:82:20;;23037:2:80;3636:82:20;;;23019:21:80;23076:2;23056:18;;;23049:30;23115:34;23095:18;;;23088:62;-1:-1:-1;;;23166:18:80;;;23159:39;23215:19;;3636:82:20;22835:405:80;3636:82:20;3595:138;3842:53;3860:17;3879:4;3885:9;3842:17;:53::i;15154:97:42:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;15224:20:42::1;:18;:20::i;434:207:78:-:0;492:19;540:2;569;588:21;;;;-1:-1:-1;588:21:78;;;:46;;;626:8;613:21;;:9;:21;;;;588:46;581:53;434:207;-1:-1:-1;;;;434:207:78:o;794:90:77:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;858:12:77::1;:19:::0;;-1:-1:-1;;858:19:77::1;873:4;858:19;::::0;;794:90::o;1777:153:17:-;1866:13;1859:20;;-1:-1:-1;;;;;;1859:20:17;;;1889:34;1914:8;1889:24;:34::i;26242:1763:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;26566:20:::3;:55;;;;;;;;26590:11;26602:1;26590:14;;;;;;;:::i;:::-;;;;;26566:55;;;;26606:11;26618:1;26606:14;;;;;;;:::i;:::-;;;;;26566:55:::0;;26631:106:::3;::::0;;;;;;;26671:14;;::::3;;26631:106:::0;;::::3;::::0;;;26566:55;;-1:-1:-1;;;26631:106:42;;;;;;26671:11;26699:1:::3;26687:14;;;;26631:106;;::::0;::::3;;;;;;;;;;;;26705:11;26717:1;26705:14;;;;;;;:::i;:::-;;;;;26631:106;;;;26721:11;26733:1;26721:14;;;;;;;:::i;:::-;;;;;26631:106:::0;;;;26747:56:::3;::::0;;;;::::3;::::0;;;26631:106;;-1:-1:-1;26747:21:42::3;::::0;:56;26772:11;26784:1:::3;26772:14;;;;26747:56;;;;26788:11;26800:1;26788:14;;;;;;;:::i;:::-;;;;;26747:56;;::::0;::::3;;26813:28;:42;;;;;;;;26845:9;26813:42;;::::0;::::3;;26920:14;-1:-1:-1::0;;;;;26920:26:42::3;;26947:2;26951;26955:3;26960:10;26920:51;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;26920:51:42::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;26920:51:42::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;26916:1083;;;;:::i;:::-;27091:14;27086:85;;27132:24;;-1:-1:-1::0;;;27132:24:42::3;;;;;;;;;;;27086:85;27339:11;:22:::0;;;27507:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;27507:47:42::3;27538:15;-1:-1:-1::0;;;;;27507:47:42::3;;::::0;;27339:22;27595:17:::3;27574:49;::::0;27586:7;;27574:49:::3;::::0;;;::::3;26972:662;26500:1505;;;;26242:1763:::0;;;;;:::o;1805:281:20:-;-1:-1:-1;;;;;1476:19:24;;;1878:106:20;;;;-1:-1:-1;;;1878:106:20;;23859:2:80;1878:106:20;;;23841:21:80;23898:2;23878:18;;;23871:30;23937:34;23917:18;;;23910:62;-1:-1:-1;;;23988:18:80;;;23981:43;24041:19;;1878:106:20;23657:409:80;1878:106:20;-1:-1:-1;;;;;;;;;;;1994:85:20;;-1:-1:-1;;;;;;1994:85:20;-1:-1:-1;;;;;1994:85:20;;;;;;;;;;1805:281::o;2478:288::-;2616:29;2627:17;2616:10;:29::i;:::-;2673:1;2659:4;:11;:15;:28;;;;2678:9;2659:28;2655:105;;;2703:46;2725:17;2744:4;2703:21;:46::i;:::-;;2478:288;;;:::o;3048:131:44:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;3122:16:44::1;:14;:16::i;:::-;3148:24;:22;:24::i;2673:187:18:-:0;2765:6;;;-1:-1:-1;;;;;2781:17:18;;;-1:-1:-1;;;;;;2781:17:18;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2736:124;2673:187;:::o;2192:152:20:-;2258:37;2277:17;2258:18;:37::i;:::-;2310:27;;-1:-1:-1;;;;;2310:27:20;;;;;;;;2192:152;:::o;7088:455::-;7171:12;-1:-1:-1;;;;;1476:19:24;;;7195:88:20;;;;-1:-1:-1;;;7195:88:20;;24273:2:80;7195:88:20;;;24255:21:80;24312:2;24292:18;;;24285:30;24351:34;24331:18;;;24324:62;-1:-1:-1;;;24402:18:80;;;24395:36;24448:19;;7195:88:20;24071:402:80;7195:88:20;7354:12;7368:23;7395:6;-1:-1:-1;;;;;7395:19:20;7415:4;7395:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7353:67;;;;7437:99;7473:7;7482:10;7437:99;;;;;;;;;;;;;;;;;:35;:99::i;:::-;7430:106;;;;7088:455;;;;;:::o;1003:95:18:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;1065:26:18::1;:24;:26::i;1042:67:23:-:0;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;7438:295:24:-;7584:12;7612:7;7608:119;;;-1:-1:-1;7642:10:24;7635:17;;7608:119;7683:33;7691:10;7703:12;7683:7;:33::i;1104:111:18:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;1176:32:18::1;929:10:25::0;1176:18:18::1;:32::i;7739:540:24:-:0;7898:17;;:21;7894:379;;8126:10;8120:17;8182:15;8169:10;8165:2;8161:19;8154:44;14:151:80;-1:-1:-1;;;;;109:31:80;;99:42;;89:70;;155:1;152;145:12;170:295;257:6;310:2;298:9;289:7;285:23;281:32;278:52;;;326:1;323;316:12;278:52;365:9;352:23;384:51;429:5;384:51;:::i;470:160::-;564:6;597:3;585:16;;582:25;-1:-1:-1;579:45:80;;;620:1;617;610:12;635:163;702:20;;762:10;751:22;;741:33;;731:61;;788:1;785;778:12;803:367;866:8;876:6;930:3;923:4;915:6;911:17;907:27;897:55;;948:1;945;938:12;897:55;-1:-1:-1;971:20:80;;1014:18;1003:30;;1000:50;;;1046:1;1043;1036:12;1000:50;1083:4;1075:6;1071:17;1059:29;;1143:3;1136:4;1126:6;1123:1;1119:14;1111:6;1107:27;1103:38;1100:47;1097:67;;;1160:1;1157;1150:12;1097:67;803:367;;;;;:::o;1175:773::-;1321:6;1329;1337;1345;1353;1361;1414:3;1402:9;1393:7;1389:23;1385:33;1382:53;;;1431:1;1428;1421:12;1382:53;1454;1499:7;1488:9;1454:53;:::i;:::-;1444:63;;1554:3;1543:9;1539:19;1526:33;1516:43;;1578:38;1611:3;1600:9;1596:19;1578:38;:::i;:::-;1568:48;;1667:3;1656:9;1652:19;1639:33;1695:18;1687:6;1684:30;1681:50;;;1727:1;1724;1717:12;1681:50;1766:70;1828:7;1819:6;1808:9;1804:22;1766:70;:::i;:::-;1175:773;;;;-1:-1:-1;1175:773:80;;;;;1937:3;1922:19;;;1909:33;;1175:773;-1:-1:-1;;;;1175:773:80:o;1953:347::-;2004:8;2014:6;2068:3;2061:4;2053:6;2049:17;2045:27;2035:55;;2086:1;2083;2076:12;2035:55;-1:-1:-1;2109:20:80;;2152:18;2141:30;;2138:50;;;2184:1;2181;2174:12;2138:50;2221:4;2213:6;2209:17;2197:29;;2273:3;2266:4;2257:6;2249;2245:19;2241:30;2238:39;2235:59;;;2290:1;2287;2280:12;2305:745;2435:6;2443;2451;2459;2467;2475;2528:3;2516:9;2507:7;2503:23;2499:33;2496:53;;;2545:1;2542;2535:12;2496:53;2568;2613:7;2602:9;2568:53;:::i;:::-;2558:63;;2640:38;2673:3;2662:9;2658:19;2640:38;:::i;:::-;2630:48;;2729:3;2718:9;2714:19;2701:33;2757:18;2749:6;2746:30;2743:50;;;2789:1;2786;2779:12;2743:50;2828:58;2878:7;2869:6;2858:9;2854:22;2828:58;:::i;:::-;2305:745;;;;-1:-1:-1;2905:8:80;2987:3;2972:19;;2959:33;;3039:3;3024:19;;;3011:33;;-1:-1:-1;2305:745:80;-1:-1:-1;;;;2305:745:80:o;3356:618::-;3452:6;3460;3468;3476;3484;3537:3;3525:9;3516:7;3512:23;3508:33;3505:53;;;3554:1;3551;3544:12;3505:53;3594:9;3581:23;3627:18;3619:6;3616:30;3613:50;;;3659:1;3656;3649:12;3613:50;3698:58;3748:7;3739:6;3728:9;3724:22;3698:58;:::i;:::-;3775:8;;-1:-1:-1;3672:84:80;-1:-1:-1;;3857:2:80;3842:18;;3829:32;;-1:-1:-1;3908:2:80;3893:18;;3880:32;;-1:-1:-1;3931:37:80;3964:2;3949:18;;3931:37;:::i;:::-;3921:47;;3356:618;;;;;;;;:::o;4161:509::-;4281:6;4289;4297;4305;4313;4366:3;4354:9;4345:7;4341:23;4337:33;4334:53;;;4383:1;4380;4373:12;4334:53;4419:9;4406:23;4396:33;;4476:2;4465:9;4461:18;4448:32;4438:42;;4527:2;4516:9;4512:18;4499:32;4489:42;;4578:2;4567:9;4563:18;4550:32;4540:42;;4601:63;4656:7;4650:3;4639:9;4635:19;4601:63;:::i;4947:908::-;5126:6;5134;5142;5150;5158;5211:3;5199:9;5190:7;5186:23;5182:33;5179:53;;;5228:1;5225;5218:12;5179:53;5267:9;5254:23;5317:4;5310:5;5306:16;5299:5;5296:27;5286:55;;5337:1;5334;5327:12;5286:55;5360:5;-1:-1:-1;5412:2:80;5397:18;;5384:32;;-1:-1:-1;5468:2:80;5453:18;;5440:32;5481:53;5440:32;5481:53;:::i;:::-;5553:7;-1:-1:-1;5612:2:80;5597:18;;5584:32;5625:53;5584:32;5625:53;:::i;:::-;5697:7;-1:-1:-1;5756:3:80;5741:19;;5728:33;5770:53;5728:33;5770:53;:::i;:::-;5842:7;5832:17;;;4947:908;;;;;;;;:::o;6068:180::-;6127:6;6180:2;6168:9;6159:7;6155:23;6151:32;6148:52;;;6196:1;6193;6186:12;6148:52;-1:-1:-1;6219:23:80;;6068:180;-1:-1:-1;6068:180:80:o;6861:127::-;6922:10;6917:3;6913:20;6910:1;6903:31;6953:4;6950:1;6943:15;6977:4;6974:1;6967:15;6993:249;7103:2;7084:13;;-1:-1:-1;;7080:27:80;7068:40;;7138:18;7123:34;;7159:22;;;7120:62;7117:88;;;7185:18;;:::i;:::-;7221:2;7214:22;-1:-1:-1;;6993:249:80:o;7247:953::-;7324:6;7332;7385:2;7373:9;7364:7;7360:23;7356:32;7353:52;;;7401:1;7398;7391:12;7353:52;7440:9;7427:23;7459:51;7504:5;7459:51;:::i;:::-;7529:5;-1:-1:-1;7553:2:80;7591:18;;;7578:32;7629:18;7659:14;;;7656:34;;;7686:1;7683;7676:12;7656:34;7724:6;7713:9;7709:22;7699:32;;7769:7;7762:4;7758:2;7754:13;7750:27;7740:55;;7791:1;7788;7781:12;7740:55;7827:2;7814:16;7849:2;7845;7842:10;7839:36;;;7855:18;;:::i;:::-;7904:2;7898:9;;-1:-1:-1;7916:65:80;7971:2;7952:13;;-1:-1:-1;;7948:27:80;7944:36;;7898:9;7916:65;:::i;:::-;8005:2;7997:6;7990:18;8045:7;8040:2;8035;8031;8027:11;8023:20;8020:33;8017:53;;;8066:1;8063;8056:12;8017:53;8122:2;8117;8113;8109:11;8104:2;8096:6;8092:15;8079:46;8167:1;8162:2;8157;8149:6;8145:15;8141:24;8134:35;;8188:6;8178:16;;;;;7247:953;;;;;:::o;8205:1225::-;8380:6;8388;8396;8404;8412;8420;8428;8436;8489:3;8477:9;8468:7;8464:23;8460:33;8457:53;;;8506:1;8503;8496:12;8457:53;8542:9;8529:23;8519:33;;8599:2;8588:9;8584:18;8571:32;8561:42;;8654:2;8643:9;8639:18;8626:32;8677:18;8718:2;8710:6;8707:14;8704:34;;;8734:1;8731;8724:12;8704:34;8773:70;8835:7;8826:6;8815:9;8811:22;8773:70;:::i;:::-;8862:8;;-1:-1:-1;8747:96:80;-1:-1:-1;8950:2:80;8935:18;;8922:32;;-1:-1:-1;8966:16:80;;;8963:36;;;8995:1;8992;8985:12;8963:36;9034:72;9098:7;9087:8;9076:9;9072:24;9034:72;:::i;:::-;9125:8;;-1:-1:-1;9008:98:80;-1:-1:-1;9213:3:80;9198:19;;9185:33;;-1:-1:-1;9230:16:80;;;9227:36;;;9259:1;9256;9249:12;9227:36;;9298:72;9362:7;9351:8;9340:9;9336:24;9298:72;:::i;:::-;8205:1225;;;;-1:-1:-1;8205:1225:80;;-1:-1:-1;8205:1225:80;;;;;;9389:8;-1:-1:-1;;;8205:1225:80:o;9435:646::-;9547:6;9555;9563;9571;9579;9632:3;9620:9;9611:7;9607:23;9603:33;9600:53;;;9649:1;9646;9639:12;9600:53;9672:28;9690:9;9672:28;:::i;:::-;9662:38;;9747:2;9736:9;9732:18;9719:32;9709:42;;9798:2;9787:9;9783:18;9770:32;9760:42;;9853:2;9842:9;9838:18;9825:32;9880:18;9872:6;9869:30;9866:50;;;9912:1;9909;9902:12;9866:50;9951:70;10013:7;10004:6;9993:9;9989:22;9951:70;:::i;:::-;9435:646;;;;-1:-1:-1;9435:646:80;;-1:-1:-1;10040:8:80;;9925:96;9435:646;-1:-1:-1;;;9435:646:80:o;10275:1352::-;10484:6;10492;10500;10508;10516;10524;10532;10540;10548;10601:3;10589:9;10580:7;10576:23;10572:33;10569:53;;;10618:1;10615;10608:12;10569:53;10641;10686:7;10675:9;10641:53;:::i;:::-;10631:63;;10741:3;10730:9;10726:19;10713:33;10703:43;;10797:3;10786:9;10782:19;10769:33;10821:18;10862:2;10854:6;10851:14;10848:34;;;10878:1;10875;10868:12;10848:34;10917:70;10979:7;10970:6;10959:9;10955:22;10917:70;:::i;:::-;11006:8;;-1:-1:-1;10891:96:80;-1:-1:-1;11094:3:80;11079:19;;11066:33;;-1:-1:-1;11111:16:80;;;11108:36;;;11140:1;11137;11130:12;11108:36;11179:72;11243:7;11232:8;11221:9;11217:24;11179:72;:::i;:::-;11270:8;;-1:-1:-1;11153:98:80;-1:-1:-1;11358:3:80;11343:19;;11330:33;;-1:-1:-1;11375:16:80;;;11372:36;;;11404:1;11401;11394:12;11372:36;;11443:72;11507:7;11496:8;11485:9;11481:24;11443:72;:::i;:::-;10275:1352;;;;-1:-1:-1;10275:1352:80;;;;;;;;11534:8;11616:3;11601:19;11588:33;;10275:1352;-1:-1:-1;;;;10275:1352:80:o;11632:408::-;11834:2;11816:21;;;11873:2;11853:18;;;11846:30;11912:34;11907:2;11892:18;;11885:62;-1:-1:-1;;;11978:2:80;11963:18;;11956:42;12030:3;12015:19;;11632:408::o;12045:::-;12247:2;12229:21;;;12286:2;12266:18;;;12259:30;12325:34;12320:2;12305:18;;12298:62;-1:-1:-1;;;12391:2:80;12376:18;;12369:42;12443:3;12428:19;;12045:408::o;12843:209::-;12875:1;12901;12891:132;;12945:10;12940:3;12936:20;12933:1;12926:31;12980:4;12977:1;12970:15;13008:4;13005:1;12998:15;12891:132;-1:-1:-1;13037:9:80;;12843:209::o;13057:294::-;13150:6;13203:2;13191:9;13182:7;13178:23;13174:32;13171:52;;;13219:1;13216;13209:12;13171:52;13251:9;13245:16;13270:51;13315:5;13270:51;:::i;13356:127::-;13417:10;13412:3;13408:20;13405:1;13398:31;13448:4;13445:1;13438:15;13472:4;13469:1;13462:15;13488:326;13581:5;13604:1;13614:194;13628:4;13625:1;13622:11;13614:194;;;13687:13;;13675:26;;13724:4;13748:12;;;;13783:15;;;;13648:1;13641:9;13614:194;;13819:1627;14267:3;14252:19;;14280:43;14256:9;14305:6;14280:43;:::i;:::-;14342:2;14379;14368:9;14364:18;14424:6;14448:1;14458:586;14522:4;14555:2;14552:1;14549:9;14539:30;;14562:5;;;14539:30;14592:13;;14631:3;14714:1;14728:234;14744:2;14739:3;14736:11;14728:234;;;14815:15;;14801:30;;14858:4;14931:17;;;;14888:14;;;;14766:1;14757:11;14728:234;;;-1:-1:-1;;;14982:12:80;;;;-1:-1:-1;15029:4:80;15017:17;;;;;14485:1;14478:9;14458:586;;;14462:3;;;;15053:53;15101:3;15090:9;15086:19;15078:6;15053:53;:::i;:::-;15143:3;15132:9;15128:19;15195:6;15221:1;15231:209;15247:1;15242:3;15239:10;15231:209;;;15309:15;;15295:30;;15348:4;15374:14;;;;15413:17;;;;15268:1;15259:11;15231:209;;;15235:3;;;13819:1627;;;;;;;:::o;15451:277::-;15518:6;15571:2;15559:9;15550:7;15546:23;15542:32;15539:52;;;15587:1;15584;15577:12;15539:52;15619:9;15613:16;15672:5;15665:13;15658:21;15651:5;15648:32;15638:60;;15694:1;15691;15684:12;15733:179;15768:3;15810:1;15792:16;15789:23;15786:120;;;15856:1;15853;15850;15835:23;-1:-1:-1;15893:1:80;15887:8;15882:3;15878:18;15733:179;:::o;15917:671::-;15956:3;15998:4;15980:16;15977:26;15974:39;;;15917:671;:::o;15974:39::-;16040:2;16034:9;-1:-1:-1;;16105:16:80;16101:25;;16098:1;16034:9;16077:50;16156:4;16150:11;16180:16;16215:18;16286:2;16279:4;16271:6;16267:17;16264:25;16259:2;16251:6;16248:14;16245:45;16242:58;;;16293:5;;;;;15917:671;:::o;16242:58::-;16330:6;16324:4;16320:17;16309:28;;16366:3;16360:10;16393:2;16385:6;16382:14;16379:27;;;16399:5;;;;;;15917:671;:::o;16379:27::-;16483:2;16464:16;16458:4;16454:27;16450:36;16443:4;16434:6;16429:3;16425:16;16421:27;16418:69;16415:82;;;16490:5;;;;;;15917:671;:::o;16415:82::-;16506:57;16557:4;16548:6;16540;16536:19;16532:30;16526:4;16506:57;:::i;:::-;-1:-1:-1;16579:3:80;;15917:671;-1:-1:-1;;;;;15917:671:80:o;16593:250::-;16678:1;16688:113;16702:6;16699:1;16696:13;16688:113;;;16778:11;;;16772:18;16759:11;;;16752:39;16724:2;16717:10;16688:113;;;-1:-1:-1;;16835:1:80;16817:16;;16810:27;16593:250::o;16848:396::-;16997:2;16986:9;16979:21;16960:4;17029:6;17023:13;17072:6;17067:2;17056:9;17052:18;17045:34;17088:79;17160:6;17155:2;17144:9;17140:18;17135:2;17127:6;17123:15;17088:79;:::i;:::-;17228:2;17207:15;-1:-1:-1;;17203:29:80;17188:45;;;;17235:2;17184:54;;16848:396;-1:-1:-1;;16848:396:80:o;17447:410::-;17649:2;17631:21;;;17688:2;17668:18;;;17661:30;17727:34;17722:2;17707:18;;17700:62;-1:-1:-1;;;17793:2:80;17778:18;;17771:44;17847:3;17832:19;;17447:410::o;17862:606::-;18140:4;18182:3;18171:9;18167:19;18159:27;;18213:6;18202:9;18195:25;18256:6;18251:2;18240:9;18236:18;18229:34;18299:6;18294:2;18283:9;18279:18;18272:34;18342:6;18337:2;18326:9;18322:18;18315:34;18400:6;18392;18386:3;18375:9;18371:19;18358:49;18456:4;18448:6;18444:17;18438:3;18427:9;18423:19;18416:46;17862:606;;;;;;;;;:::o;18733:225::-;18800:9;;;18821:11;;;18818:134;;;18874:10;18869:3;18865:20;18862:1;18855:31;18909:4;18906:1;18899:15;18937:4;18934:1;18927:15;19798:261;19868:3;-1:-1:-1;;;;;19889:31:80;;19886:51;;;19933:1;19930;19923:12;19886:51;19969:6;19966:1;19962:14;20010:8;20003:5;19998:3;19985:34;20035:18;;;;;19798:261;-1:-1:-1;;;19798:261:80:o;20064:951::-;20495:6;20490:3;20483:19;20465:3;20521:2;20553:6;20548:2;20543:3;20539:12;20532:28;20591:2;20586:3;20582:12;20640:6;20664:1;20674:204;20688:6;20685:1;20682:13;20674:204;;;20782:10;20755:25;20773:6;20755:25;:::i;:::-;20751:42;20737:57;;20816:14;;;;20853:15;;;;20710:1;20703:9;20674:204;;;20678:3;;20894:115;20948:60;21002:5;20994:6;20986;20948:60;:::i;:::-;20940:6;20932;20894:115;:::i;:::-;20887:122;20064:951;-1:-1:-1;;;;;;;;;;;;20064:951:80:o;21020:489::-;21334:10;21329:3;21325:20;21316:6;21311:3;21307:16;21303:43;21298:3;21291:56;21376:6;21372:1;21367:3;21363:11;21356:27;21413:6;21408:2;21403:3;21399:12;21392:28;21273:3;21436:67;21499:2;21494:3;21490:12;21482:6;21474;21436:67;:::i;:::-;21429:74;21020:489;-1:-1:-1;;;;;;;21020:489:80:o;22231:184::-;22301:6;22354:2;22342:9;22333:7;22329:23;22325:32;22322:52;;;22370:1;22367;22360:12;22322:52;-1:-1:-1;22393:16:80;;22231:184;-1:-1:-1;22231:184:80:o;23245:407::-;23447:2;23429:21;;;23486:2;23466:18;;;23459:30;23525:34;23520:2;23505:18;;23498:62;-1:-1:-1;;;23591:2:80;23576:18;;23569:41;23642:3;23627:19;;23245:407::o;24478:287::-;24607:3;24645:6;24639:13;24661:66;24720:6;24715:3;24708:4;24700:6;24696:17;24661:66;:::i;:::-;24743:16;;;;;24478:287;-1:-1:-1;;24478:287:80:o", + "linkReferences": {}, + "immutableReferences": { + "29832": [ + { + "start": 1614, + "length": 32 + }, + { + "start": 1687, + "length": 32 + }, + { + "start": 1909, + "length": 32 + }, + { + "start": 1973, + "length": 32 + }, + { + "start": 2957, + "length": 32 + }, + { + "start": 3021, + "length": 32 + }, + { + "start": 4100, + "length": 32 + }, + { + "start": 4164, + "length": 32 + }, + { + "start": 4347, + "length": 32 + }, + { + "start": 4411, + "length": 32 + }, + { + "start": 4583, + "length": 32 + }, + { + "start": 4647, + "length": 32 + }, + { + "start": 4903, + "length": 32 + }, + { + "start": 4967, + "length": 32 + }, + { + "start": 5495, + "length": 32 + }, + { + "start": 5559, + "length": 32 + }, + { + "start": 5737, + "length": 32 + }, + { + "start": 5801, + "length": 32 + }, + { + "start": 6143, + "length": 32 + }, + { + "start": 6207, + "length": 32 + }, + { + "start": 6346, + "length": 32 + }, + { + "start": 6410, + "length": 32 + }, + { + "start": 6533, + "length": 32 + }, + { + "start": 6597, + "length": 32 + }, + { + "start": 6748, + "length": 32 + }, + { + "start": 6924, + "length": 32 + }, + { + "start": 6988, + "length": 32 + }, + { + "start": 7323, + "length": 32 + }, + { + "start": 7387, + "length": 32 + }, + { + "start": 7591, + "length": 32 + }, + { + "start": 7655, + "length": 32 + }, + { + "start": 7850, + "length": 32 + }, + { + "start": 7914, + "length": 32 + }, + { + "start": 8065, + "length": 32 + }, + { + "start": 8129, + "length": 32 + }, + { + "start": 8279, + "length": 32 + }, + { + "start": 8343, + "length": 32 + }, + { + "start": 8567, + "length": 32 + }, + { + "start": 8631, + "length": 32 + }, + { + "start": 8812, + "length": 32 + }, + { + "start": 8876, + "length": 32 + }, + { + "start": 9357, + "length": 32 + }, + { + "start": 9421, + "length": 32 + }, + { + "start": 9700, + "length": 32 + }, + { + "start": 9764, + "length": 32 + }, + { + "start": 9905, + "length": 32 + }, + { + "start": 9969, + "length": 32 + }, + { + "start": 10119, + "length": 32 + }, + { + "start": 10183, + "length": 32 + }, + { + "start": 10331, + "length": 32 + }, + { + "start": 10395, + "length": 32 + }, + { + "start": 10881, + "length": 32 + }, + { + "start": 10945, + "length": 32 + }, + { + "start": 11582, + "length": 32 + }, + { + "start": 11646, + "length": 32 + } + ] + } + }, + "methodIdentifiers": { + "NO_SUCH_ROOT()": "561f204b", + "acceptOwnership()": "79ba5097", + "calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)": "31e4e992", + "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": "8c76a909", + "calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])": "86ec599a", + "deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)": "23cfdba5", + "getDeleteIdentitiesVerifierLookupTableAddress()": "3e8919b6", + "getIdentityUpdateVerifierLookupTableAddress()": "4ffbdde5", + "getRegisterIdentitiesVerifierLookupTableAddress()": "8fc22e9f", + "getRootHistoryExpiry()": "43f974cb", + "getSemaphoreVerifierAddress()": "f2038f95", + "getTreeDepth()": "8e5cdd50", + "identityOperator()": "f134b6ca", + "initialize(uint8,uint256,address,address,address)": "38c87065", + "initializeV2(address)": "29b6eca9", + "latestRoot()": "d7b0fef1", + "owner()": "8da5cb5b", + "pendingOwner()": "e30c3978", + "proxiableUUID()": "52d1902d", + "queryRoot(uint256)": "3f7c178d", + "registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)": "2217b211", + "renounceOwnership()": "715018a6", + "requireValidRoot(uint256)": "f2358e1d", + "setDeleteIdentitiesVerifierLookupTable(address)": "aa4a729e", + "setIdentityOperator(address)": "a7bba582", + "setIdentityUpdateVerifierLookupTable(address)": "6b056600", + "setRegisterIdentitiesVerifierLookupTable(address)": "2f059fca", + "setRootHistoryExpiry(uint256)": "c70aa727", + "setSemaphoreVerifier(address)": "0e3a12f3", + "transferOwnership(address)": "f2fde38b", + "updateIdentities(uint256[8],uint256,uint32[],uint256[],uint256[],uint256)": "b843b4e5", + "upgradeTo(address)": "3659cfe6", + "upgradeToAndCall(address,bytes)": "4f1ef286", + "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": "354ca120" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CannotRenounceOwnership\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExpiredRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ImplementationNotInitialized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"InvalidCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStateBridgeAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedInputLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"latestRoot\",\"type\":\"uint256\"}],\"name\":\"NotLatestRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProofValidationFailure\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeAlreadyDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeAlreadyEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WorldIDIdentityManagerImplV1.UnreducedElementType\",\"name\":\"elementType\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"element\",\"type\":\"uint256\"}],\"name\":\"UnreducedElement\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"depth\",\"type\":\"uint8\"}],\"name\":\"UnsupportedTreeDepth\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum WorldIDIdentityManagerImplV1.Dependency\",\"name\":\"kind\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"DependencyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldOperator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOperator\",\"type\":\"address\"}],\"name\":\"IdentityOperatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldExpiryTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newExpiryTime\",\"type\":\"uint256\"}],\"name\":\"RootHistoryExpirySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"name\":\"StateBridgeStateChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum WorldIDIdentityManagerImplV1.TreeChange\",\"name\":\"kind\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"TreeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"_treeDepth\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialRoot\",\"type\":\"uint256\"}],\"name\":\"WorldIDIdentityManagerImplInitialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NO_SUCH_ROOT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"supersededTimestamp\",\"type\":\"uint128\"},{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.RootInfo\",\"name\":\"rootInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"packedDeletionIndices\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"batchSize\",\"type\":\"uint32\"}],\"name\":\"calculateIdentityDeletionInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"startIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"identityCommitments\",\"type\":\"uint256[]\"}],\"name\":\"calculateIdentityRegistrationInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"leafIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"oldIdentities\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newIdentities\",\"type\":\"uint256[]\"}],\"name\":\"calculateIdentityUpdateInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"deletionProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint32\",\"name\":\"batchSize\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"packedDeletionIndices\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"deleteIdentities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDeleteIdentitiesVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getIdentityUpdateVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegisterIdentitiesVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRootHistoryExpiry\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSemaphoreVerifierAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTreeDepth\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"identityOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_treeDepth\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"initialRoot\",\"type\":\"uint256\"},{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchInsertionVerifiers\",\"type\":\"address\"},{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchUpdateVerifiers\",\"type\":\"address\"},{\"internalType\":\"contract ISemaphoreVerifier\",\"name\":\"_semaphoreVerifier\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchUpdateVerifiers\",\"type\":\"address\"}],\"name\":\"initializeV2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"queryRoot\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"supersededTimestamp\",\"type\":\"uint128\"},{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.RootInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"insertionProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256[]\",\"name\":\"identityCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"registerIdentities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"requireValidRoot\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setDeleteIdentitiesVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newIdentityOperator\",\"type\":\"address\"}],\"name\":\"setIdentityOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setIdentityUpdateVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setRegisterIdentitiesVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newExpiryTime\",\"type\":\"uint256\"}],\"name\":\"setRootHistoryExpiry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ISemaphoreVerifier\",\"name\":\"newVerifier\",\"type\":\"address\"}],\"name\":\"setSemaphoreVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"updateProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"leafIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"oldIdentities\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newIdentities\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"updateIdentities\",\"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\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signalHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nullifierHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalNullifierHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256[8]\",\"name\":\"proof\",\"type\":\"uint256[8]\"}],\"name\":\"verifyProof\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Worldcoin\",\"details\":\"The manager is based on the principle of verifying externally-created Zero Knowledge Proofs to perform the insertions.This is the implementation delegated to by a proxy.\",\"errors\":{\"InvalidCommitment(uint256)\":[{\"params\":{\"index\":\"The index in the array of identity commitments where the invalid commitment was found.\"}}],\"NotLatestRoot(uint256,uint256)\":[{\"params\":{\"latestRoot\":\"The actual latest root at the time of the transaction.\",\"providedRoot\":\"The root that was provided as the `preRoot` for a transaction.\"}}],\"Unauthorized(address)\":[{\"params\":{\"user\":\"The user that attempted the action that they were not authorised for.\"}}],\"UnreducedElement(uint8,uint256)\":[{\"details\":\"`r` in this case is given by `SNARK_SCALAR_FIELD`.\",\"params\":{\"element\":\"The value of that element.\",\"elementType\":\"The kind of element that was encountered unreduced.\"}}],\"UnsupportedTreeDepth(uint8)\":[{\"params\":{\"depth\":\"Passed tree depth.\"}}]},\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is upgraded.\"},\"DependencyUpdated(uint8,address,address)\":{\"params\":{\"kind\":\"The kind of dependency that was updated.\",\"newAddress\":\"The new address of that dependency.\",\"oldAddress\":\"The old address of that dependency.\"}},\"IdentityOperatorChanged(address,address)\":{\"params\":{\"newOperator\":\"The address of the new identity operator.\",\"oldOperator\":\"The address of the old identity operator.\"}},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"RootHistoryExpirySet(uint256,uint256)\":{\"params\":{\"newExpiryTime\":\"The expiry time after the change.\",\"oldExpiryTime\":\"The expiry time prior to the change.\"}},\"StateBridgeStateChange(bool)\":{\"params\":{\"isEnabled\":\"Set to `true` if the event comes from the state bridge being enabled, `false` otherwise.\"}},\"TreeChanged(uint256,uint8,uint256)\":{\"params\":{\"kind\":\"Either \\\"insertion\\\" or \\\"update\\\", the kind of alteration that was made to the tree.\",\"postRoot\":\"The value of the tree's root after the update.\",\"preRoot\":\"The value of the tree's root before the update.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"},\"WorldIDIdentityManagerImplInitialized(uint8,uint256)\":{\"params\":{\"_treeDepth\":\"The depth of the MerkeTree\",\"initialRoot\":\"The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree.\"}}},\"kind\":\"dev\",\"methods\":{\"NO_SUCH_ROOT()\":{\"details\":\"Can be checked against when querying for root data.\"},\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)\":{\"details\":\"Implements the computation described below.the deletion indices are packed into bytes calldata where each deletion index is 32 bits wide. The indices are encoded using abi.encodePacked for testing. We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows: packedDeletionIndices || PreRoot || PostRoot 32 bits * batchSize || 256 || 256\",\"params\":{\"batchSize\":\"The number of identities that were deleted in this batch\",\"packedDeletionIndices\":\"The indices of the identities that were deleted from the tree.\",\"postRoot\":\"The root value of the tree after these insertions were made.\",\"preRoot\":\"The root value of the tree before these insertions were made.\"},\"returns\":{\"hash\":\"The input hash calculated as described below.\"}},\"calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])\":{\"details\":\"Implements the computation described below.\",\"params\":{\"identityCommitments\":\"The identities that were added to the tree to produce `postRoot`.\",\"postRoot\":\"The root value of the tree after these insertions were made.\",\"preRoot\":\"The root value of the tree before these insertions were made.\",\"startIndex\":\"The index in the tree from which inserting started.\"},\"returns\":{\"hash\":\"The input hash calculated as described below. We keccak hash all input to save verification gas. Inputs are arranged as follows: StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] 32\\t || 256 || 256 || 256 || 256 || ... || 256 bits\"}},\"calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])\":{\"details\":\"Implements the computation described below.\",\"params\":{\"leafIndices\":\"The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.\",\"newIdentities\":\"The array of new values for the identities. Length must match that of `leafIndices`.\",\"oldIdentities\":\"The array of old values for the identities. Length must match that of `leafIndices`.\",\"postRoot\":\"The root value of the tree after the updates were made.\",\"preRoot\":\"The root value of the tree before the updates were made.\"},\"returns\":{\"hash\":\"The input hash calculated as described below. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation. We keccak hash all input to save verification gas. The inputs are arranged as follows: preRoot || postRoot || ix[0] || ... || ix[n] || oi[0] || ... || oi[n] || ni[0] || ... || ni[n] || 256 || 256 || 256 || ... || 256 || 256 || ... || 256 || 256 || ... || 256 || where: - `ix[i] == leafIndices[i]` - `oi[i] == oldIdentities[i]` - `ni[i] == newIdentities[i]` - `id[i] == identities[i]` - `n == batchSize - 1`\"}},\"deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to add identities.InvalidCommitment If one or more of the provided commitments is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `deletionProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identityCommitments` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.\",\"details\":\"Can only be called by the owner.Deletion is performed off-chain and verified on-chain via the `deletionProof`. This saves gas and time over deleting identities one at a time.\",\"params\":{\"batchSize\":\"The number of identities that are to be deleted in the current batch.\",\"deletionProof\":\"The proof that given the conditions (`preRoot` and `packedDeletionIndices`), deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y` coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`, and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x` and `y` coordinates for `krs`.\",\"packedDeletionIndices\":\"The indices of the identities that were deleted from the tree.\",\"postRoot\":\"The root obtained after deleting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`.\",\"preRoot\":\"The value for the root of the tree before the `identityCommitments` have been inserted. Must be an element of the field `Kr`.\"}},\"getDeleteIdentitiesVerifierLookupTableAddress()\":{\"details\":\"The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch.\",\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier lookup table.\"}},\"getIdentityUpdateVerifierLookupTableAddress()\":{\"details\":\"The update verifier is also used for member removals.\",\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier lookup table.\"}},\"getRegisterIdentitiesVerifierLookupTableAddress()\":{\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier lookup table.\"}},\"getRootHistoryExpiry()\":{\"returns\":{\"_0\":\"expiryTime The amount of time it takes for a root to expire.\"}},\"getSemaphoreVerifierAddress()\":{\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier.\"}},\"getTreeDepth()\":{\"returns\":{\"_0\":\"initializedTreeDepth Tree depth.\"}},\"identityOperator()\":{\"returns\":{\"_0\":\"_ The address authorized to perform identity operations.\"}},\"initialize(uint8,uint256,address,address,address)\":{\"custom:reverts\":\"string If called more than once at the same initialisation number.UnsupportedTreeDepth If passed tree depth is not among defined values.\",\"details\":\"Must be called exactly once.This is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead.\",\"params\":{\"_batchInsertionVerifiers\":\"The verifier lookup table for batch insertions.\",\"_batchUpdateVerifiers\":\"The verifier lookup table for batch updates.\",\"_semaphoreVerifier\":\"The verifier to use for semaphore protocol proofs.\",\"_treeDepth\":\"The depth of the MerkeTree\",\"initialRoot\":\"The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree.\"}},\"initializeV2(address)\":{\"details\":\"Must be called exactly onceThis is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead.\"},\"latestRoot()\":{\"returns\":{\"_0\":\"root The value of the latest tree root.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"queryRoot(uint256)\":{\"details\":\"Should be used sparingly as the query can be quite expensive.\",\"params\":{\"root\":\"The root for which you are querying information.\"},\"returns\":{\"_0\":\"rootInfo The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. Note that if the queried root is the current, the timestamp will be invalid as the root has not been superseded.\"}},\"registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to add identities.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `insertionProof` cannot be verified using the provided inputs.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.\",\"params\":{\"identityCommitments\":\"The identities that were inserted into the tree starting at `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be elements of the field `Kr`.\",\"postRoot\":\"The root obtained after inserting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`. (alread in reduced form)\",\"startIndex\":\"The position in the tree at which the insertions were made.\"}},\"renounceOwnership()\":{\"details\":\"This function is intentionally not `virtual` as we do not want it to be possible to renounce ownership for any WorldID implementation.This function is marked as `onlyOwner` to maintain the access restriction from the base contract.\"},\"requireValidRoot(uint256)\":{\"custom:reverts\":\"ExpiredRoot If the provided `root` has expired.NonExistentRoot If the provided `root` does not exist in the history.\",\"details\":\"A root is valid if it is either the latest root, or not the latest root but has not expired.\",\"params\":{\"root\":\"The root of the merkle tree to check for validity.\"}},\"setDeleteIdentitiesVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newTable\":\"The new verifier lookup table to be used for verifying identity deletions.\"}},\"setIdentityOperator(address)\":{\"params\":{\"newIdentityOperator\":\"The address of the new identity operator.\"},\"returns\":{\"_0\":\"_ The address of the old identity operator.\"}},\"setIdentityUpdateVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.The update verifier is also used for member removals.\",\"params\":{\"newTable\":\"The new lookup table instance to be used for verifying identity updates.\"}},\"setRegisterIdentitiesVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newTable\":\"The new verifier lookup table to be used for verifying identity registrations.\"}},\"setRootHistoryExpiry(uint256)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newExpiryTime\":\"The new time to use to expire roots.\"}},\"setSemaphoreVerifier(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newVerifier\":\"The new verifier instance to be used for verifying semaphore proofs.\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateIdentities(uint256[8],uint256,uint32[],uint256[],uint256[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to update identities.NotLatestRoot If the provided `preRoot` is not the latest root.MismatchedInputLengths If the provided arrays for `leafIndices`, `oldIdentities` and `newIdentities` do not match in length.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.NoSuchVerifier If the batch sizes doesn't match a known verifier.\",\"params\":{\"leafIndices\":\"The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.\",\"newIdentities\":\"The array of new values for the identities. Length must match that of `leafIndices`.\",\"oldIdentities\":\"The array of old values for the identities. Length must match that of `leafIndices`.\",\"postRoot\":\"The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation.\"}},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"verifyProof(uint256,uint256,uint256,uint256,uint256[8])\":{\"custom:reverts\":\"string If the zero-knowledge proof cannot be verified for the public inputs.\",\"details\":\"Note that a double-signaling check is not included here, and should be carried by the caller.\",\"params\":{\"externalNullifierHash\":\"A keccak256 hash of the external nullifier\",\"nullifierHash\":\"The nullifier hash\",\"proof\":\"The zero-knowledge proof\",\"root\":\"The of the Merkle tree\",\"signalHash\":\"A keccak256 hash of the Semaphore signal\"}}},\"title\":\"WorldID Identity Manager Implementation Version 2\",\"version\":1},\"userdoc\":{\"errors\":{\"CannotRenounceOwnership()\":[{\"notice\":\"Thrown when an attempt is made to renounce ownership.\"}],\"ExpiredRoot()\":[{\"notice\":\"Thrown when attempting to validate a root that has expired.\"}],\"ImplementationNotInitialized()\":[{\"notice\":\"Thrown when attempting to call a function while the implementation has not been initialized.\"}],\"InvalidCommitment(uint256)\":[{\"notice\":\"Thrown when one or more of the identity commitments to be inserted is invalid.\"}],\"InvalidStateBridgeAddress()\":[{\"notice\":\"Thrown when attempting to set the state bridge address to the zero address.\"}],\"MismatchedInputLengths()\":[{\"notice\":\"Thrown when the inputs to `removeIdentities` or `updateIdentities` do not match in length.\"}],\"NonExistentRoot()\":[{\"notice\":\"Thrown when attempting to validate a root that has yet to be added to the root history.\"}],\"NotLatestRoot(uint256,uint256)\":[{\"notice\":\"Thrown when the provided root is not the very latest root.\"}],\"ProofValidationFailure()\":[{\"notice\":\"Thrown when the provided proof cannot be verified for the accompanying inputs.\"}],\"StateBridgeAlreadyDisabled()\":[{\"notice\":\"Thrown when attempting to disable the bridge when it is already disabled.\"}],\"StateBridgeAlreadyEnabled()\":[{\"notice\":\"Thrown when attempting to enable the bridge when it is already enabled.\"}],\"Unauthorized(address)\":[{\"notice\":\"Thrown when trying to execute a privileged action without being the contract manager.\"}],\"UnreducedElement(uint8,uint256)\":[{\"notice\":\"Thrown when encountering an element that should be reduced as a member of `Fr` but is not.\"}],\"UnsupportedTreeDepth(uint8)\":[{\"notice\":\"Thrown when Semaphore tree depth is not supported.\"}]},\"events\":{\"DependencyUpdated(uint8,address,address)\":{\"notice\":\"Emitted when a dependency's address is updated via an admin action.\"},\"IdentityOperatorChanged(address,address)\":{\"notice\":\"Emitted when the identity operator is changed.\"},\"RootHistoryExpirySet(uint256,uint256)\":{\"notice\":\"Emitted when the root history expiry time is changed.\"},\"StateBridgeStateChange(bool)\":{\"notice\":\"Emitted when the state bridge is enabled or disabled.\"},\"TreeChanged(uint256,uint8,uint256)\":{\"notice\":\"Emitted when the current root of the tree is updated.\"}},\"kind\":\"user\",\"methods\":{\"NO_SUCH_ROOT()\":{\"notice\":\"A constant representing a root that doesn't exist.\"},\"calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)\":{\"notice\":\"Calculates the input hash for the identity deletion verifier.\"},\"calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])\":{\"notice\":\"Calculates the input hash for the identity registration verifier.\"},\"calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])\":{\"notice\":\"Calculates the input hash for the identity update verifier.\"},\"deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)\":{\"notice\":\"Deletes identities from the WorldID system.\"},\"getDeleteIdentitiesVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for batch identity deletions.\"},\"getIdentityUpdateVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for identity updates.\"},\"getRegisterIdentitiesVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for identity registrations.\"},\"getRootHistoryExpiry()\":{\"notice\":\"Gets the current amount of time used to expire roots in the history.\"},\"getSemaphoreVerifierAddress()\":{\"notice\":\"Gets the address of the verifier used for verification of semaphore proofs.\"},\"getTreeDepth()\":{\"notice\":\"Gets the Semaphore tree depth the contract was initialized with.\"},\"identityOperator()\":{\"notice\":\"Gets the address that is authorised to perform identity operations on this identity manager instance.\"},\"initialize(uint8,uint256,address,address,address)\":{\"notice\":\"Initializes the contract.\"},\"initializeV2(address)\":{\"notice\":\"Initializes the V2 implementation contract.\"},\"latestRoot()\":{\"notice\":\"Allows a caller to query the latest root.\"},\"queryRoot(uint256)\":{\"notice\":\"Allows a caller to query the root history for information about a given root.\"},\"renounceOwnership()\":{\"notice\":\"Ensures that ownership of WorldID implementations cannot be renounced.\"},\"requireValidRoot(uint256)\":{\"notice\":\"Reverts if the provided root value is not valid.\"},\"setDeleteIdentitiesVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers used for identity deletions.\"},\"setIdentityOperator(address)\":{\"notice\":\"Sets the address that is authorised to perform identity operations on this identity manager instance.\"},\"setIdentityUpdateVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers to be used for verification of identity updates.\"},\"setRegisterIdentitiesVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers used for identity registrations.\"},\"setRootHistoryExpiry(uint256)\":{\"notice\":\"Sets the time to wait before expiring a root from the root history.\"},\"setSemaphoreVerifier(address)\":{\"notice\":\"Sets the address for the semaphore verifier to be used for verification of semaphore proofs.\"},\"verifyProof(uint256,uint256,uint256,uint256,uint256[8])\":{\"notice\":\"A verifier for the semaphore protocol.\"}},\"notice\":\"An implementation of a batch-based identity manager for the WorldID protocol.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/WorldIDIdentityManagerImplV2.sol\":\"WorldIDIdentityManagerImplV2\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@zk-kit/=lib/zk-kit/packages/\",\":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":ds-test/=lib/ds-test/src/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/\",\":openzeppelin/=lib/openzeppelin-contracts/contracts/\",\":semaphore/=lib/semaphore/packages/contracts/contracts/\",\":solmate/=lib/solmate/src/\",\":zk-kit/=lib/zk-kit/\"]},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol\":{\"keccak256\":\"0xd712fb45b3ea0ab49679164e3895037adc26ce12879d5184feb040e01c1c07a9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://79ecc0838b0649460c0a538a4adb55b2b530e726c5526afc5e09c8eea4f3af13\",\"dweb:/ipfs/QmUxugyGDGGeLzDFi8QDH2vQMtCFaheiujWv58SuGVx4bZ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol\":{\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053\",\"dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"keccak256\":\"0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2\",\"dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol\":{\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1\",\"dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8a313cf42389440e2706837c91370323b85971c06afd6d056d21e2bc86459618\",\"dweb:/ipfs/QmT8XUrUvQ9aZaPKrqgRU2JVGWnaxBcUYJA7Q7K5KcLBSZ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0x7967d130887c4b40666cd88f8744691d4527039a1b2a38aa0de41481ef646778\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40e60cbf0e2efede4d9c169e66336a64615af7b719a896ef1f37ae8cd4614ec1\",\"dweb:/ipfs/QmYNiwY22ifhfa8yK6mLCEKfj39caYUHLqe2VBtzDnvdsV\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06\",\"dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol\":{\"keccak256\":\"0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3\",\"dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0x923b9774b81c1abfb992262ae7763b6e6de77b077a7180d53c6ebb7b1c8bd648\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://53445dc0431f9b45c06f567c6091da961d4087bec0010cca5bd62100fa624a38\",\"dweb:/ipfs/QmNvBYpBv183czrAqNXr76E8M3LF93ouAJFeAcHfb59Rcx\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol\":{\"keccak256\":\"0x7cdab82b437a17902683a413c86d14f512674a0710007bf44c584a2d2d3ca833\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ffe4db7a9f3cdd5a5d019462c2859f4f98f7aae08704afdcb3ef0d08d966bbeb\",\"dweb:/ipfs/QmTCHSuoi22dAu55qv4TcENyTmv5mTpAoxmYWD8cRnEp3M\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"lib/semaphore/packages/contracts/contracts/base/Pairing.sol\":{\"keccak256\":\"0x44390032d1247a0e3931eb39f1220f170db653c6b3b4321b2e2b0034f5e07334\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://725cc4bdf047d17bf9d47c9a0205d90897c0da334de8e556c1a3049b1beb9aed\",\"dweb:/ipfs/QmSo7SXpqyrqHFhYi7F8SGjcVxCdVr6FNdgiw7Qfre1NGt\"]},\"lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol\":{\"keccak256\":\"0x5b5b1118ed7936014d3e410419d6048cc9c0ae69fd700442593f2c2cc782e1af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://601cf2c7e3c98735ff38eaff225af090ec847d63ec599ecc2340323145430668\",\"dweb:/ipfs/QmUoZYgge8GmQokXrYiRXn24s4HgBZetiNWQssiSoTFrdi\"]},\"src/WorldIDIdentityManagerImplV1.sol\":{\"keccak256\":\"0xa1065360c830348be5e6f45dfb766d9f415d0321170a804da0b2f56338c14b36\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cd10fbb5eaf1f57cfe026baf79ee8cb7ca9d7db50599b77062d2634a147e9645\",\"dweb:/ipfs/QmdtRnh5nPkRFynH2mNsYvaAur8QPwsuCg6A1AAQnKB291\"]},\"src/WorldIDIdentityManagerImplV2.sol\":{\"keccak256\":\"0xa88ed74cd795d2a9a7cbb99f88fa1393c25d7807525c6f081b57d163180f887b\",\"urls\":[\"bzz-raw://5e045ea6313140813d515f5ceb43624cba08cfd14657445a731ba76a1e8252f1\",\"dweb:/ipfs/Qmb4kfWzbV3gVjrhfVo2PphCijTXxdBUvz9N1mV3Mivcd5\"]},\"src/abstract/WorldIDImpl.sol\":{\"keccak256\":\"0xccfff2c5d7af4e505ed13b7d46011d5544317343ea92e7beb874e4d69358e6d0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://428860598ca38e42e29892a0b4759c4d3010378f54c3b3e4392f965ff091076e\",\"dweb:/ipfs/QmYPjcDRTr1UEeSbS7ssdGjbDHzAqjRNKBsYJqKJWeL8bZ\"]},\"src/data/VerifierLookupTable.sol\":{\"keccak256\":\"0xfd213b79aaec8d205c50ab3ed5c4ebed06ae602ed526a820340adc1c76745fbc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6af992a56a7cee8124af7f16d74dc8a2a7ae5f8b3059b92d46862e44c3804b83\",\"dweb:/ipfs/QmV9bQtJ9PjnwsiiZMUGJANB3znSxJ6ACTqWv9WkQeoeB3\"]},\"src/interfaces/IBaseWorldID.sol\":{\"keccak256\":\"0xcec58605726864d72e35d62c85e002acc98d3f8fa19d01b49fff461c2767c144\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://57714fcbceb0497f3fe8906778a837082939489fbb0bd930d015ad6e971913d5\",\"dweb:/ipfs/QmQVVmLr9CEkR727ByMF96a8MbwAeB4AQQWvxneg2Avkq8\"]},\"src/interfaces/IBridge.sol\":{\"keccak256\":\"0x0931c789450d21479da5d4de8c6435fca965660f6e1bd746fff958f4c20cf2ac\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0c564b4d4a15e8075555077a043d773bb20133548376402ff3dbc0eccb57435d\",\"dweb:/ipfs/QmXQRihAFdtfyjTNeHmx9nmNHiS1wy2658Y5aXCXo2tKSQ\"]},\"src/interfaces/ITreeVerifier.sol\":{\"keccak256\":\"0xb572aeae7331d96981d46b0dd4408db9ad507a06a2dbf0624386114b2244c8ad\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6159630f78e9e0b3a326d064772713f8c1e73172718c2a6d5af1fb36b35c5991\",\"dweb:/ipfs/QmPN5VyQvonPfPdTvrmP5wqsFT3QNW3RwC8DHYdEtwXZT4\"]},\"src/interfaces/IWorldID.sol\":{\"keccak256\":\"0x577908eff2d29d96354a06ab2602ffe6b97aa9d491330efcc2fcd0a88a8acbb1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa0a36a598a851b88cff364b4211dc32081f51940aa8076d9c9b7de8ab126b2f\",\"dweb:/ipfs/QmSne8aRiE8C8RuwEUSk4doETKAGaavrEYyUkwiJc5H8qc\"]},\"src/utils/CheckInitialized.sol\":{\"keccak256\":\"0xfab096b633efd580548007e97920f6088e6d8a5287db84b9aa3d595c02fefcf4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dee612c9dbad59d535e7a72b79191187fd91c06af9cb5b6f68d60274d0ee2c04\",\"dweb:/ipfs/QmVJbSQ8DAN6igasbgHjZTM4NRZ3EjrhK8wFcvUG1wPYtZ\"]},\"src/utils/SemaphoreTreeDepthValidator.sol\":{\"keccak256\":\"0x50140161de381aa963457cfd2ee8831a435bd79040f38794e6ef07365c49c872\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bcc5b8a3a6f5146aa3fdee550c3e80d828b55df63223485da3d5655a591ad661\",\"dweb:/ipfs/QmWfUzbeFoSaPV1E8QxagUnpt5zfmPXgiropUg1GcV6oZs\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.21+commit.d9974bed" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [], + "type": "error", + "name": "CannotRenounceOwnership" + }, + { + "inputs": [], + "type": "error", + "name": "ExpiredRoot" + }, + { + "inputs": [], + "type": "error", + "name": "ImplementationNotInitialized" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "type": "error", + "name": "InvalidCommitment" + }, + { + "inputs": [], + "type": "error", + "name": "InvalidStateBridgeAddress" + }, + { + "inputs": [], + "type": "error", + "name": "MismatchedInputLengths" + }, + { + "inputs": [], + "type": "error", + "name": "NonExistentRoot" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "providedRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "latestRoot", + "type": "uint256" + } + ], + "type": "error", + "name": "NotLatestRoot" + }, + { + "inputs": [], + "type": "error", + "name": "ProofValidationFailure" + }, + { + "inputs": [], + "type": "error", + "name": "StateBridgeAlreadyDisabled" + }, + { + "inputs": [], + "type": "error", + "name": "StateBridgeAlreadyEnabled" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "type": "error", + "name": "Unauthorized" + }, + { + "inputs": [ + { + "internalType": "enum WorldIDIdentityManagerImplV1.UnreducedElementType", + "name": "elementType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "element", + "type": "uint256" + } + ], + "type": "error", + "name": "UnreducedElement" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "depth", + "type": "uint8" + } + ], + "type": "error", + "name": "UnsupportedTreeDepth" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousAdmin", + "type": "address", + "indexed": false + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "AdminChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "BeaconUpgraded", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "enum WorldIDIdentityManagerImplV1.Dependency", + "name": "kind", + "type": "uint8", + "indexed": true + }, + { + "internalType": "address", + "name": "oldAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newAddress", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "DependencyUpdated", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oldOperator", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOperator", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "IdentityOperatorChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8", + "indexed": false + } + ], + "type": "event", + "name": "Initialized", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousOwner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "OwnershipTransferStarted", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousOwner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "OwnershipTransferred", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "oldExpiryTime", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256", + "indexed": true + } + ], + "type": "event", + "name": "RootHistoryExpirySet", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "isEnabled", + "type": "bool", + "indexed": true + } + ], + "type": "event", + "name": "StateBridgeStateChange", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256", + "indexed": true + }, + { + "internalType": "enum WorldIDIdentityManagerImplV1.TreeChange", + "name": "kind", + "type": "uint8", + "indexed": true + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256", + "indexed": true + } + ], + "type": "event", + "name": "TreeChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "Upgraded", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8", + "indexed": false + }, + { + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "WorldIDIdentityManagerImplInitialized", + "anonymous": false + }, + { + "inputs": [], + "stateMutability": "pure", + "type": "function", + "name": "NO_SUCH_ROOT", + "outputs": [ + { + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "rootInfo", + "type": "tuple", + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ] + } + ] + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "name": "acceptOwnership" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function", + "name": "calculateIdentityDeletionInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function", + "name": "calculateIdentityRegistrationInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function", + "name": "calculateIdentityUpdateInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "deletionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "deleteIdentities" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getDeleteIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getIdentityUpdateVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getRegisterIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getRootHistoryExpiry", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getSemaphoreVerifierAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getTreeDepth", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "identityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchInsertionVerifiers", + "type": "address" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + }, + { + "internalType": "contract ISemaphoreVerifier", + "name": "_semaphoreVerifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "initialize" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "initializeV2" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "latestRoot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "queryRoot", + "outputs": [ + { + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "", + "type": "tuple", + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ] + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "insertionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "registerIdentities" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "renounceOwnership" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "requireValidRoot" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setDeleteIdentitiesVerifierLookupTable" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newIdentityOperator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setIdentityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setIdentityUpdateVerifierLookupTable" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setRegisterIdentitiesVerifierLookupTable" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setRootHistoryExpiry" + }, + { + "inputs": [ + { + "internalType": "contract ISemaphoreVerifier", + "name": "newVerifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setSemaphoreVerifier" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferOwnership" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "updateProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "updateIdentities" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "upgradeTo" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function", + "name": "upgradeToAndCall" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "signalHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalNullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256[8]", + "name": "proof", + "type": "uint256[8]" + } + ], + "stateMutability": "view", + "type": "function", + "name": "verifyProof" + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "NO_SUCH_ROOT()": { + "details": "Can be checked against when querying for root data." + }, + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)": { + "details": "Implements the computation described below.the deletion indices are packed into bytes calldata where each deletion index is 32 bits wide. The indices are encoded using abi.encodePacked for testing. We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows: packedDeletionIndices || PreRoot || PostRoot 32 bits * batchSize || 256 || 256", + "params": { + "batchSize": "The number of identities that were deleted in this batch", + "packedDeletionIndices": "The indices of the identities that were deleted from the tree.", + "postRoot": "The root value of the tree after these insertions were made.", + "preRoot": "The root value of the tree before these insertions were made." + }, + "returns": { + "hash": "The input hash calculated as described below." + } + }, + "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": { + "details": "Implements the computation described below.", + "params": { + "identityCommitments": "The identities that were added to the tree to produce `postRoot`.", + "postRoot": "The root value of the tree after these insertions were made.", + "preRoot": "The root value of the tree before these insertions were made.", + "startIndex": "The index in the tree from which inserting started." + }, + "returns": { + "hash": "The input hash calculated as described below. We keccak hash all input to save verification gas. Inputs are arranged as follows: StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] 32\t || 256 || 256 || 256 || 256 || ... || 256 bits" + } + }, + "calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])": { + "details": "Implements the computation described below.", + "params": { + "leafIndices": "The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.", + "newIdentities": "The array of new values for the identities. Length must match that of `leafIndices`.", + "oldIdentities": "The array of old values for the identities. Length must match that of `leafIndices`.", + "postRoot": "The root value of the tree after the updates were made.", + "preRoot": "The root value of the tree before the updates were made." + }, + "returns": { + "hash": "The input hash calculated as described below. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation. We keccak hash all input to save verification gas. The inputs are arranged as follows: preRoot || postRoot || ix[0] || ... || ix[n] || oi[0] || ... || oi[n] || ni[0] || ... || ni[n] || 256 || 256 || 256 || ... || 256 || 256 || ... || 256 || 256 || ... || 256 || where: - `ix[i] == leafIndices[i]` - `oi[i] == oldIdentities[i]` - `ni[i] == newIdentities[i]` - `id[i] == identities[i]` - `n == batchSize - 1`" + } + }, + "deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)": { + "custom:reverts": "Unauthorized If the message sender is not authorised to add identities.InvalidCommitment If one or more of the provided commitments is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `deletionProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identityCommitments` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.", + "details": "Can only be called by the owner.Deletion is performed off-chain and verified on-chain via the `deletionProof`. This saves gas and time over deleting identities one at a time.", + "params": { + "batchSize": "The number of identities that are to be deleted in the current batch.", + "deletionProof": "The proof that given the conditions (`preRoot` and `packedDeletionIndices`), deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y` coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`, and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x` and `y` coordinates for `krs`.", + "packedDeletionIndices": "The indices of the identities that were deleted from the tree.", + "postRoot": "The root obtained after deleting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`.", + "preRoot": "The value for the root of the tree before the `identityCommitments` have been inserted. Must be an element of the field `Kr`." + } + }, + "getDeleteIdentitiesVerifierLookupTableAddress()": { + "details": "The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch.", + "returns": { + "_0": "addr The address of the contract being used as the verifier lookup table." + } + }, + "getIdentityUpdateVerifierLookupTableAddress()": { + "details": "The update verifier is also used for member removals.", + "returns": { + "_0": "addr The address of the contract being used as the verifier lookup table." + } + }, + "getRegisterIdentitiesVerifierLookupTableAddress()": { + "returns": { + "_0": "addr The address of the contract being used as the verifier lookup table." + } + }, + "getRootHistoryExpiry()": { + "returns": { + "_0": "expiryTime The amount of time it takes for a root to expire." + } + }, + "getSemaphoreVerifierAddress()": { + "returns": { + "_0": "addr The address of the contract being used as the verifier." + } + }, + "getTreeDepth()": { + "returns": { + "_0": "initializedTreeDepth Tree depth." + } + }, + "identityOperator()": { + "returns": { + "_0": "_ The address authorized to perform identity operations." + } + }, + "initialize(uint8,uint256,address,address,address)": { + "custom:reverts": "string If called more than once at the same initialisation number.UnsupportedTreeDepth If passed tree depth is not among defined values.", + "details": "Must be called exactly once.This is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead.", + "params": { + "_batchInsertionVerifiers": "The verifier lookup table for batch insertions.", + "_batchUpdateVerifiers": "The verifier lookup table for batch updates.", + "_semaphoreVerifier": "The verifier to use for semaphore protocol proofs.", + "_treeDepth": "The depth of the MerkeTree", + "initialRoot": "The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree." + } + }, + "initializeV2(address)": { + "details": "Must be called exactly onceThis is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead." + }, + "latestRoot()": { + "returns": { + "_0": "root The value of the latest tree root." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "proxiableUUID()": { + "details": "Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "queryRoot(uint256)": { + "details": "Should be used sparingly as the query can be quite expensive.", + "params": { + "root": "The root for which you are querying information." + }, + "returns": { + "_0": "rootInfo The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. Note that if the queried root is the current, the timestamp will be invalid as the root has not been superseded." + } + }, + "registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)": { + "custom:reverts": "Unauthorized If the message sender is not authorised to add identities.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `insertionProof` cannot be verified using the provided inputs.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.", + "params": { + "identityCommitments": "The identities that were inserted into the tree starting at `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be elements of the field `Kr`.", + "postRoot": "The root obtained after inserting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`. (alread in reduced form)", + "startIndex": "The position in the tree at which the insertions were made." + } + }, + "renounceOwnership()": { + "details": "This function is intentionally not `virtual` as we do not want it to be possible to renounce ownership for any WorldID implementation.This function is marked as `onlyOwner` to maintain the access restriction from the base contract." + }, + "requireValidRoot(uint256)": { + "custom:reverts": "ExpiredRoot If the provided `root` has expired.NonExistentRoot If the provided `root` does not exist in the history.", + "details": "A root is valid if it is either the latest root, or not the latest root but has not expired.", + "params": { + "root": "The root of the merkle tree to check for validity." + } + }, + "setDeleteIdentitiesVerifierLookupTable(address)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newTable": "The new verifier lookup table to be used for verifying identity deletions." + } + }, + "setIdentityOperator(address)": { + "params": { + "newIdentityOperator": "The address of the new identity operator." + }, + "returns": { + "_0": "_ The address of the old identity operator." + } + }, + "setIdentityUpdateVerifierLookupTable(address)": { + "details": "Only the owner of the contract can call this function.The update verifier is also used for member removals.", + "params": { + "newTable": "The new lookup table instance to be used for verifying identity updates." + } + }, + "setRegisterIdentitiesVerifierLookupTable(address)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newTable": "The new verifier lookup table to be used for verifying identity registrations." + } + }, + "setRootHistoryExpiry(uint256)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newExpiryTime": "The new time to use to expire roots." + } + }, + "setSemaphoreVerifier(address)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newVerifier": "The new verifier instance to be used for verifying semaphore proofs." + } + }, + "transferOwnership(address)": { + "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." + }, + "updateIdentities(uint256[8],uint256,uint32[],uint256[],uint256[],uint256)": { + "custom:reverts": "Unauthorized If the message sender is not authorised to update identities.NotLatestRoot If the provided `preRoot` is not the latest root.MismatchedInputLengths If the provided arrays for `leafIndices`, `oldIdentities` and `newIdentities` do not match in length.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.NoSuchVerifier If the batch sizes doesn't match a known verifier.", + "params": { + "leafIndices": "The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.", + "newIdentities": "The array of new values for the identities. Length must match that of `leafIndices`.", + "oldIdentities": "The array of old values for the identities. Length must match that of `leafIndices`.", + "postRoot": "The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation." + } + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": { + "custom:reverts": "string If the zero-knowledge proof cannot be verified for the public inputs.", + "details": "Note that a double-signaling check is not included here, and should be carried by the caller.", + "params": { + "externalNullifierHash": "A keccak256 hash of the external nullifier", + "nullifierHash": "The nullifier hash", + "proof": "The zero-knowledge proof", + "root": "The of the Merkle tree", + "signalHash": "A keccak256 hash of the Semaphore signal" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "NO_SUCH_ROOT()": { + "notice": "A constant representing a root that doesn't exist." + }, + "calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)": { + "notice": "Calculates the input hash for the identity deletion verifier." + }, + "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": { + "notice": "Calculates the input hash for the identity registration verifier." + }, + "calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])": { + "notice": "Calculates the input hash for the identity update verifier." + }, + "deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)": { + "notice": "Deletes identities from the WorldID system." + }, + "getDeleteIdentitiesVerifierLookupTableAddress()": { + "notice": "Gets the address for the lookup table of merkle tree verifiers used for batch identity deletions." + }, + "getIdentityUpdateVerifierLookupTableAddress()": { + "notice": "Gets the address for the lookup table of merkle tree verifiers used for identity updates." + }, + "getRegisterIdentitiesVerifierLookupTableAddress()": { + "notice": "Gets the address for the lookup table of merkle tree verifiers used for identity registrations." + }, + "getRootHistoryExpiry()": { + "notice": "Gets the current amount of time used to expire roots in the history." + }, + "getSemaphoreVerifierAddress()": { + "notice": "Gets the address of the verifier used for verification of semaphore proofs." + }, + "getTreeDepth()": { + "notice": "Gets the Semaphore tree depth the contract was initialized with." + }, + "identityOperator()": { + "notice": "Gets the address that is authorised to perform identity operations on this identity manager instance." + }, + "initialize(uint8,uint256,address,address,address)": { + "notice": "Initializes the contract." + }, + "initializeV2(address)": { + "notice": "Initializes the V2 implementation contract." + }, + "latestRoot()": { + "notice": "Allows a caller to query the latest root." + }, + "queryRoot(uint256)": { + "notice": "Allows a caller to query the root history for information about a given root." + }, + "renounceOwnership()": { + "notice": "Ensures that ownership of WorldID implementations cannot be renounced." + }, + "requireValidRoot(uint256)": { + "notice": "Reverts if the provided root value is not valid." + }, + "setDeleteIdentitiesVerifierLookupTable(address)": { + "notice": "Sets the address for the lookup table of merkle tree verifiers used for identity deletions." + }, + "setIdentityOperator(address)": { + "notice": "Sets the address that is authorised to perform identity operations on this identity manager instance." + }, + "setIdentityUpdateVerifierLookupTable(address)": { + "notice": "Sets the address for the lookup table of merkle tree verifiers to be used for verification of identity updates." + }, + "setRegisterIdentitiesVerifierLookupTable(address)": { + "notice": "Sets the address for the lookup table of merkle tree verifiers used for identity registrations." + }, + "setRootHistoryExpiry(uint256)": { + "notice": "Sets the time to wait before expiring a root from the root history." + }, + "setSemaphoreVerifier(address)": { + "notice": "Sets the address for the semaphore verifier to be used for verification of semaphore proofs." + }, + "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": { + "notice": "A verifier for the semaphore protocol." + } + }, + "version": 1 + } + }, + "settings": { + "remappings": [ + "@zk-kit/=lib/zk-kit/packages/", + "contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-std/=lib/forge-std/src/", + "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "semaphore/=lib/semaphore/packages/contracts/contracts/", + "solmate/=lib/solmate/src/", + "zk-kit/=lib/zk-kit/" + ], + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/WorldIDIdentityManagerImplV2.sol": "WorldIDIdentityManagerImplV2" + }, + "libraries": {} + }, + "sources": { + "lib/openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol": { + "keccak256": "0xd712fb45b3ea0ab49679164e3895037adc26ce12879d5184feb040e01c1c07a9", + "urls": [ + "bzz-raw://79ecc0838b0649460c0a538a4adb55b2b530e726c5526afc5e09c8eea4f3af13", + "dweb:/ipfs/QmUxugyGDGGeLzDFi8QDH2vQMtCFaheiujWv58SuGVx4bZ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol": { + "keccak256": "0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888", + "urls": [ + "bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a", + "dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol": { + "keccak256": "0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f", + "urls": [ + "bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053", + "dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "keccak256": "0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823", + "urls": [ + "bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2", + "dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol": { + "keccak256": "0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908", + "urls": [ + "bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1", + "dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": { + "keccak256": "0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271", + "urls": [ + "bzz-raw://8a313cf42389440e2706837c91370323b85971c06afd6d056d21e2bc86459618", + "dweb:/ipfs/QmT8XUrUvQ9aZaPKrqgRU2JVGWnaxBcUYJA7Q7K5KcLBSZ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol": { + "keccak256": "0x7967d130887c4b40666cd88f8744691d4527039a1b2a38aa0de41481ef646778", + "urls": [ + "bzz-raw://40e60cbf0e2efede4d9c169e66336a64615af7b719a896ef1f37ae8cd4614ec1", + "dweb:/ipfs/QmYNiwY22ifhfa8yK6mLCEKfj39caYUHLqe2VBtzDnvdsV" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": { + "keccak256": "0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183", + "urls": [ + "bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06", + "dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": { + "keccak256": "0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149", + "urls": [ + "bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c", + "dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol": { + "keccak256": "0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a", + "urls": [ + "bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3", + "dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/access/Ownable.sol": { + "keccak256": "0x923b9774b81c1abfb992262ae7763b6e6de77b077a7180d53c6ebb7b1c8bd648", + "urls": [ + "bzz-raw://53445dc0431f9b45c06f567c6091da961d4087bec0010cca5bd62100fa624a38", + "dweb:/ipfs/QmNvBYpBv183czrAqNXr76E8M3LF93ouAJFeAcHfb59Rcx" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol": { + "keccak256": "0x7cdab82b437a17902683a413c86d14f512674a0710007bf44c584a2d2d3ca833", + "urls": [ + "bzz-raw://ffe4db7a9f3cdd5a5d019462c2859f4f98f7aae08704afdcb3ef0d08d966bbeb", + "dweb:/ipfs/QmTCHSuoi22dAu55qv4TcENyTmv5mTpAoxmYWD8cRnEp3M" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "keccak256": "0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7", + "urls": [ + "bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92", + "dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3" + ], + "license": "MIT" + }, + "lib/semaphore/packages/contracts/contracts/base/Pairing.sol": { + "keccak256": "0x44390032d1247a0e3931eb39f1220f170db653c6b3b4321b2e2b0034f5e07334", + "urls": [ + "bzz-raw://725cc4bdf047d17bf9d47c9a0205d90897c0da334de8e556c1a3049b1beb9aed", + "dweb:/ipfs/QmSo7SXpqyrqHFhYi7F8SGjcVxCdVr6FNdgiw7Qfre1NGt" + ], + "license": "MIT" + }, + "lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol": { + "keccak256": "0x5b5b1118ed7936014d3e410419d6048cc9c0ae69fd700442593f2c2cc782e1af", + "urls": [ + "bzz-raw://601cf2c7e3c98735ff38eaff225af090ec847d63ec599ecc2340323145430668", + "dweb:/ipfs/QmUoZYgge8GmQokXrYiRXn24s4HgBZetiNWQssiSoTFrdi" + ], + "license": "MIT" + }, + "src/WorldIDIdentityManagerImplV1.sol": { + "keccak256": "0xa1065360c830348be5e6f45dfb766d9f415d0321170a804da0b2f56338c14b36", + "urls": [ + "bzz-raw://cd10fbb5eaf1f57cfe026baf79ee8cb7ca9d7db50599b77062d2634a147e9645", + "dweb:/ipfs/QmdtRnh5nPkRFynH2mNsYvaAur8QPwsuCg6A1AAQnKB291" + ], + "license": "MIT" + }, + "src/WorldIDIdentityManagerImplV2.sol": { + "keccak256": "0xa88ed74cd795d2a9a7cbb99f88fa1393c25d7807525c6f081b57d163180f887b", + "urls": [ + "bzz-raw://5e045ea6313140813d515f5ceb43624cba08cfd14657445a731ba76a1e8252f1", + "dweb:/ipfs/Qmb4kfWzbV3gVjrhfVo2PphCijTXxdBUvz9N1mV3Mivcd5" + ], + "license": null + }, + "src/abstract/WorldIDImpl.sol": { + "keccak256": "0xccfff2c5d7af4e505ed13b7d46011d5544317343ea92e7beb874e4d69358e6d0", + "urls": [ + "bzz-raw://428860598ca38e42e29892a0b4759c4d3010378f54c3b3e4392f965ff091076e", + "dweb:/ipfs/QmYPjcDRTr1UEeSbS7ssdGjbDHzAqjRNKBsYJqKJWeL8bZ" + ], + "license": "MIT" + }, + "src/data/VerifierLookupTable.sol": { + "keccak256": "0xfd213b79aaec8d205c50ab3ed5c4ebed06ae602ed526a820340adc1c76745fbc", + "urls": [ + "bzz-raw://6af992a56a7cee8124af7f16d74dc8a2a7ae5f8b3059b92d46862e44c3804b83", + "dweb:/ipfs/QmV9bQtJ9PjnwsiiZMUGJANB3znSxJ6ACTqWv9WkQeoeB3" + ], + "license": "MIT" + }, + "src/interfaces/IBaseWorldID.sol": { + "keccak256": "0xcec58605726864d72e35d62c85e002acc98d3f8fa19d01b49fff461c2767c144", + "urls": [ + "bzz-raw://57714fcbceb0497f3fe8906778a837082939489fbb0bd930d015ad6e971913d5", + "dweb:/ipfs/QmQVVmLr9CEkR727ByMF96a8MbwAeB4AQQWvxneg2Avkq8" + ], + "license": "MIT" + }, + "src/interfaces/IBridge.sol": { + "keccak256": "0x0931c789450d21479da5d4de8c6435fca965660f6e1bd746fff958f4c20cf2ac", + "urls": [ + "bzz-raw://0c564b4d4a15e8075555077a043d773bb20133548376402ff3dbc0eccb57435d", + "dweb:/ipfs/QmXQRihAFdtfyjTNeHmx9nmNHiS1wy2658Y5aXCXo2tKSQ" + ], + "license": "MIT" + }, + "src/interfaces/ITreeVerifier.sol": { + "keccak256": "0xb572aeae7331d96981d46b0dd4408db9ad507a06a2dbf0624386114b2244c8ad", + "urls": [ + "bzz-raw://6159630f78e9e0b3a326d064772713f8c1e73172718c2a6d5af1fb36b35c5991", + "dweb:/ipfs/QmPN5VyQvonPfPdTvrmP5wqsFT3QNW3RwC8DHYdEtwXZT4" + ], + "license": "MIT" + }, + "src/interfaces/IWorldID.sol": { + "keccak256": "0x577908eff2d29d96354a06ab2602ffe6b97aa9d491330efcc2fcd0a88a8acbb1", + "urls": [ + "bzz-raw://fa0a36a598a851b88cff364b4211dc32081f51940aa8076d9c9b7de8ab126b2f", + "dweb:/ipfs/QmSne8aRiE8C8RuwEUSk4doETKAGaavrEYyUkwiJc5H8qc" + ], + "license": "MIT" + }, + "src/utils/CheckInitialized.sol": { + "keccak256": "0xfab096b633efd580548007e97920f6088e6d8a5287db84b9aa3d595c02fefcf4", + "urls": [ + "bzz-raw://dee612c9dbad59d535e7a72b79191187fd91c06af9cb5b6f68d60274d0ee2c04", + "dweb:/ipfs/QmVJbSQ8DAN6igasbgHjZTM4NRZ3EjrhK8wFcvUG1wPYtZ" + ], + "license": "MIT" + }, + "src/utils/SemaphoreTreeDepthValidator.sol": { + "keccak256": "0x50140161de381aa963457cfd2ee8831a435bd79040f38794e6ef07365c49c872", + "urls": [ + "bzz-raw://bcc5b8a3a6f5146aa3fdee550c3e80d828b55df63223485da3d5655a591ad661", + "dweb:/ipfs/QmWfUzbeFoSaPV1E8QxagUnpt5zfmPXgiropUg1GcV6oZs" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "src/WorldIDIdentityManagerImplV2.sol", + "id": 34136, + "exportedSymbols": { + "IBridge": [ + 34450 + ], + "ISemaphoreVerifier": [ + 32716 + ], + "ITreeVerifier": [ + 34478 + ], + "IWorldID": [ + 34502 + ], + "SemaphoreTreeDepthValidator": [ + 47908 + ], + "VerifierLookupTable": [ + 34425 + ], + "WorldIDIdentityManagerImplV1": [ + 33896 + ], + "WorldIDIdentityManagerImplV2": [ + 34135 + ], + "WorldIDImpl": [ + 34190 + ] + }, + "nodeType": "SourceUnit", + "src": "0:12051:43", + "nodes": [ + { + "id": 33898, + "nodeType": "PragmaDirective", + "src": "0:24:43", + "nodes": [], + "literals": [ + "solidity", + "^", + "0.8", + ".21" + ] + }, + { + "id": 33899, + "nodeType": "ImportDirective", + "src": "26:44:43", + "nodes": [], + "absolutePath": "src/WorldIDIdentityManagerImplV1.sol", + "file": "./WorldIDIdentityManagerImplV1.sol", + "nameLocation": "-1:-1:-1", + "scope": 34136, + "sourceUnit": 33897, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 34135, + "nodeType": "ContractDefinition", + "src": "443:11607:43", + "nodes": [ + { + "id": 33906, + "nodeType": "VariableDeclaration", + "src": "3108:51:43", + "nodes": [], + "constant": false, + "documentation": { + "id": 33903, + "nodeType": "StructuredDocumentation", + "src": "3029:74:43", + "text": "@notice The table of verifiers for verifying batch identity deletions." + }, + "mutability": "mutable", + "name": "batchDeletionVerifiers", + "nameLocation": "3137:22:43", + "scope": 34135, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 33905, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 33904, + "name": "VerifierLookupTable", + "nameLocations": [ + "3108:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "3108:19:43" + }, + "referencedDeclaration": 34425, + "src": "3108:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + }, + { + "id": 33921, + "nodeType": "FunctionDefinition", + "src": "3800:152:43", + "nodes": [], + "body": { + "id": 33920, + "nodeType": "Block", + "src": "3889:63:43", + "nodes": [], + "statements": [ + { + "expression": { + "id": 33918, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 33916, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "3899:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 33917, + "name": "_batchUpdateVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33910, + "src": "3924:21:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "src": "3899:46:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "id": 33919, + "nodeType": "ExpressionStatement", + "src": "3899:46:43" + } + ] + }, + "documentation": { + "id": 33907, + "nodeType": "StructuredDocumentation", + "src": "3166:629:43", + "text": "@notice Initializes the V2 implementation contract.\n @dev Must be called exactly once\n @dev This is marked `reinitializer()` to allow for updated initialisation steps when working\n with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed)\n initialisations allowed, so decide carefully when to use them. Many cases can safely be\n replaced by use of setters.\n @dev This function is explicitly not virtual as it does not make sense to override even when\n upgrading. Create a separate initializer function instead." + }, + "functionSelector": "29b6eca9", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": [ + { + "hexValue": "32", + "id": 33913, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3886:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + } + ], + "id": 33914, + "kind": "modifierInvocation", + "modifierName": { + "id": 33912, + "name": "reinitializer", + "nameLocations": [ + "3872:13:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29736, + "src": "3872:13:43" + }, + "nodeType": "ModifierInvocation", + "src": "3872:16:43" + } + ], + "name": "initializeV2", + "nameLocation": "3809:12:43", + "parameters": { + "id": 33911, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 33910, + "mutability": "mutable", + "name": "_batchUpdateVerifiers", + "nameLocation": "3842:21:43", + "nodeType": "VariableDeclaration", + "scope": 33921, + "src": "3822:41:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 33909, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 33908, + "name": "VerifierLookupTable", + "nameLocations": [ + "3822:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "3822:19:43" + }, + "referencedDeclaration": 34425, + "src": "3822:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + } + ], + "src": "3821:43:43" + }, + "returnParameters": { + "id": 33915, + "nodeType": "ParameterList", + "parameters": [], + "src": "3889:0:43" + }, + "scope": 34135, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 34062, + "nodeType": "FunctionDefinition", + "src": "6380:2438:43", + "nodes": [], + "body": { + "id": 34061, + "nodeType": "Block", + "src": "6640:2178:43", + "nodes": [], + "statements": [ + { + "condition": { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 33945, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 33943, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "6654:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "id": 33944, + "name": "_latestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32764, + "src": "6665:11:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6654:22:43", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 33952, + "nodeType": "IfStatement", + "src": "6650:95:43", + "trueBody": { + "id": 33951, + "nodeType": "Block", + "src": "6678:67:43", + "statements": [ + { + "errorCall": { + "arguments": [ + { + "id": 33947, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "6713:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "id": 33948, + "name": "_latestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32764, + "src": "6722:11:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 33946, + "name": "NotLatestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32868, + "src": "6699:13:43", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$_t_uint256_$_t_uint256_$returns$__$", + "typeString": "function (uint256,uint256) pure" + } + }, + "id": 33949, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "6699:35:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 33950, + "nodeType": "RevertStatement", + "src": "6692:42:43" + } + ] + } + }, + { + "assignments": [ + 33954 + ], + "declarations": [ + { + "constant": false, + "id": 33954, + "mutability": "mutable", + "name": "inputHash", + "nameLocation": "6844:9:43", + "nodeType": "VariableDeclaration", + "scope": 34061, + "src": "6836:17:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 33953, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "6836:7:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "id": 33961, + "initialValue": { + "arguments": [ + { + "id": 33956, + "name": "packedDeletionIndices", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33930, + "src": "6903:21:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + { + "id": 33957, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "6926:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "id": 33958, + "name": "postRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33934, + "src": "6935:8:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "id": 33959, + "name": "batchSize", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33928, + "src": "6945:9:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + ], + "id": 33955, + "name": "calculateIdentityDeletionInputHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34134, + "src": "6868:34:43", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_bytes_calldata_ptr_$_t_uint256_$_t_uint256_$_t_uint32_$returns$_t_bytes32_$", + "typeString": "function (bytes calldata,uint256,uint256,uint32) view returns (bytes32)" + } + }, + "id": 33960, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "6868:87:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6836:119:43" + }, + { + "assignments": [ + 33963 + ], + "declarations": [ + { + "constant": false, + "id": 33963, + "mutability": "mutable", + "name": "reducedElement", + "nameLocation": "7234:14:43", + "nodeType": "VariableDeclaration", + "scope": 34061, + "src": "7226:22:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33962, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7226:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 33970, + "initialValue": { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 33969, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "arguments": [ + { + "id": 33966, + "name": "inputHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33954, + "src": "7259:9:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "id": 33965, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "7251:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 33964, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7251:7:43", + "typeDescriptions": {} + } + }, + "id": 33967, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7251:18:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "%", + "rightExpression": { + "id": 33968, + "name": "SNARK_SCALAR_FIELD", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32776, + "src": "7272:18:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7251:39:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7226:64:43" + }, + { + "assignments": [ + 33973 + ], + "declarations": [ + { + "constant": false, + "id": 33973, + "mutability": "mutable", + "name": "deletionVerifier", + "nameLocation": "7388:16:43", + "nodeType": "VariableDeclaration", + "scope": 34061, + "src": "7374:30:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + }, + "typeName": { + "id": 33972, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 33971, + "name": "ITreeVerifier", + "nameLocations": [ + "7374:13:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34478, + "src": "7374:13:43" + }, + "referencedDeclaration": 34478, + "src": "7374:13:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + } + }, + "visibility": "internal" + } + ], + "id": 33978, + "initialValue": { + "arguments": [ + { + "id": 33976, + "name": "batchSize", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33928, + "src": "7445:9:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + ], + "expression": { + "id": 33974, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "7407:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "id": 33975, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "7430:14:43", + "memberName": "getVerifierFor", + "nodeType": "MemberAccess", + "referencedDeclaration": 34297, + "src": "7407:37:43", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_uint256_$returns$_t_contract$_ITreeVerifier_$34478_$", + "typeString": "function (uint256) view external returns (contract ITreeVerifier)" + } + }, + "id": 33977, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7407:48:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7374:81:43" + }, + { + "clauses": [ + { + "block": { + "id": 34044, + "nodeType": "Block", + "src": "7813:634:43", + "statements": [ + { + "condition": { + "id": 34017, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "7901:15:43", + "subExpression": { + "id": 34016, + "name": "verifierResult", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34014, + "src": "7902:14:43", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 34022, + "nodeType": "IfStatement", + "src": "7897:85:43", + "trueBody": { + "id": 34021, + "nodeType": "Block", + "src": "7918:64:43", + "statements": [ + { + "errorCall": { + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 34018, + "name": "ProofValidationFailure", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32861, + "src": "7943:22:43", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 34019, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7943:24:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34020, + "nodeType": "RevertStatement", + "src": "7936:31:43" + } + ] + } + }, + { + "expression": { + "id": 34025, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 34023, + "name": "_latestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32764, + "src": "8150:11:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 34024, + "name": "postRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33934, + "src": "8164:8:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "8150:22:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 34026, + "nodeType": "ExpressionStatement", + "src": "8150:22:43" + }, + { + "expression": { + "id": 34035, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "baseExpression": { + "id": 34027, + "name": "rootHistory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32769, + "src": "8318:11:43", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", + "typeString": "mapping(uint256 => uint128)" + } + }, + "id": 34029, + "indexExpression": { + "id": 34028, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "8330:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "8318:20:43", + "typeDescriptions": { + "typeIdentifier": "t_uint128", + "typeString": "uint128" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "arguments": [ + { + "expression": { + "id": 34032, + "name": "block", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -4, + "src": "8349:5:43", + "typeDescriptions": { + "typeIdentifier": "t_magic_block", + "typeString": "block" + } + }, + "id": 34033, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "8355:9:43", + "memberName": "timestamp", + "nodeType": "MemberAccess", + "src": "8349:15:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 34031, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8341:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint128_$", + "typeString": "type(uint128)" + }, + "typeName": { + "id": 34030, + "name": "uint128", + "nodeType": "ElementaryTypeName", + "src": "8341:7:43", + "typeDescriptions": {} + } + }, + "id": 34034, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8341:24:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint128", + "typeString": "uint128" + } + }, + "src": "8318:47:43", + "typeDescriptions": { + "typeIdentifier": "t_uint128", + "typeString": "uint128" + } + }, + "id": 34036, + "nodeType": "ExpressionStatement", + "src": "8318:47:43" + }, + { + "eventCall": { + "arguments": [ + { + "id": 34038, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "8397:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "expression": { + "id": 34039, + "name": "TreeChange", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32819, + "src": "8406:10:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_TreeChange_$32819_$", + "typeString": "type(enum WorldIDIdentityManagerImplV1.TreeChange)" + } + }, + "id": 34040, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "8417:8:43", + "memberName": "Deletion", + "nodeType": "MemberAccess", + "referencedDeclaration": 32817, + "src": "8406:19:43", + "typeDescriptions": { + "typeIdentifier": "t_enum$_TreeChange_$32819", + "typeString": "enum WorldIDIdentityManagerImplV1.TreeChange" + } + }, + { + "id": 34041, + "name": "postRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33934, + "src": "8427:8:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_enum$_TreeChange_$32819", + "typeString": "enum WorldIDIdentityManagerImplV1.TreeChange" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 34037, + "name": "TreeChanged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32895, + "src": "8385:11:43", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_enum$_TreeChange_$32819_$_t_uint256_$returns$__$", + "typeString": "function (uint256,enum WorldIDIdentityManagerImplV1.TreeChange,uint256)" + } + }, + "id": 34042, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8385:51:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34043, + "nodeType": "EmitStatement", + "src": "8380:56:43" + } + ] + }, + "errorName": "", + "id": 34045, + "nodeType": "TryCatchClause", + "parameters": { + "id": 34015, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34014, + "mutability": "mutable", + "name": "verifierResult", + "nameLocation": "7797:14:43", + "nodeType": "VariableDeclaration", + "scope": 34045, + "src": "7792:19:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 34013, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "7792:4:43", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "src": "7791:21:43" + }, + "src": "7783:664:43" + }, + { + "block": { + "id": 34053, + "nodeType": "Block", + "src": "8485:100:43", + "statements": [ + { + "documentation": "This is not the revert we're looking for.", + "expression": { + "arguments": [ + { + "id": 34050, + "name": "errString", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34047, + "src": "8564:9:43", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 34049, + "name": "revert", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -19, + -19 + ], + "referencedDeclaration": -19, + "src": "8557:6:43", + "typeDescriptions": { + "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", + "typeString": "function (string memory) pure" + } + }, + "id": 34051, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8557:17:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34052, + "nodeType": "ExpressionStatement", + "src": "8557:17:43" + } + ] + }, + "errorName": "Error", + "id": 34054, + "nodeType": "TryCatchClause", + "parameters": { + "id": 34048, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34047, + "mutability": "mutable", + "name": "errString", + "nameLocation": "8474:9:43", + "nodeType": "VariableDeclaration", + "scope": 34054, + "src": "8460:23:43", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 34046, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "8460:6:43", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "8459:25:43" + }, + "src": "8448:137:43" + }, + { + "block": { + "id": 34058, + "nodeType": "Block", + "src": "8592:220:43", + "statements": [ + { + "errorCall": { + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 34055, + "name": "ProofValidationFailure", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32861, + "src": "8777:22:43", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 34056, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8777:24:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34057, + "nodeType": "RevertStatement", + "src": "8770:31:43" + } + ] + }, + "errorName": "", + "id": 34059, + "nodeType": "TryCatchClause", + "src": "8586:226:43" + } + ], + "externalCall": { + "arguments": [ + { + "components": [ + { + "baseExpression": { + "id": 33981, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7567:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33983, + "indexExpression": { + "hexValue": "30", + "id": 33982, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7581:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7567:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 33984, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7585:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33986, + "indexExpression": { + "hexValue": "31", + "id": 33985, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7599:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7585:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 33987, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7566:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + }, + { + "components": [ + { + "components": [ + { + "baseExpression": { + "id": 33988, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7618:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33990, + "indexExpression": { + "hexValue": "32", + "id": 33989, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7632:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7618:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 33991, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7636:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33993, + "indexExpression": { + "hexValue": "33", + "id": 33992, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7650:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + }, + "value": "3" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7636:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 33994, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7617:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + }, + { + "components": [ + { + "baseExpression": { + "id": 33995, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7656:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33997, + "indexExpression": { + "hexValue": "34", + "id": 33996, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7670:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_4_by_1", + "typeString": "int_const 4" + }, + "value": "4" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7656:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 33998, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7674:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 34000, + "indexExpression": { + "hexValue": "35", + "id": 33999, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7688:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_5_by_1", + "typeString": "int_const 5" + }, + "value": "5" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7674:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 34001, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7655:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + } + ], + "id": 34002, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7616:76:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", + "typeString": "uint256[2] memory[2] memory" + } + }, + { + "components": [ + { + "baseExpression": { + "id": 34003, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7707:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 34005, + "indexExpression": { + "hexValue": "36", + "id": 34004, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7721:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_6_by_1", + "typeString": "int_const 6" + }, + "value": "6" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7707:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 34006, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7725:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 34008, + "indexExpression": { + "hexValue": "37", + "id": 34007, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7739:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_7_by_1", + "typeString": "int_const 7" + }, + "value": "7" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7725:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 34009, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7706:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + }, + { + "components": [ + { + "id": 34010, + "name": "reducedElement", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33963, + "src": "7757:14:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 34011, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7756:16:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", + "typeString": "uint256[1] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + }, + { + "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", + "typeString": "uint256[2] memory[2] memory" + }, + { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + }, + { + "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", + "typeString": "uint256[1] memory" + } + ], + "expression": { + "id": 33979, + "name": "deletionVerifier", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33973, + "src": "7524:16:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + } + }, + "id": 33980, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "7541:11:43", + "memberName": "verifyProof", + "nodeType": "MemberAccess", + "referencedDeclaration": 34477, + "src": "7524:28:43", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr_$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_uint256_$1_memory_ptr_$returns$_t_bool_$", + "typeString": "function (uint256[2] memory,uint256[2] memory[2] memory,uint256[2] memory,uint256[1] memory) external returns (bool)" + } + }, + "id": 34012, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7524:258:43", + "tryCall": true, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 34060, + "nodeType": "TryStatement", + "src": "7520:1292:43" + } + ] + }, + "documentation": { + "id": 33922, + "nodeType": "StructuredDocumentation", + "src": "4175:2200:43", + "text": "@notice Deletes identities from the WorldID system.\n @dev Can only be called by the owner.\n @dev Deletion is performed off-chain and verified on-chain via the `deletionProof`.\n This saves gas and time over deleting identities one at a time.\n @param deletionProof The proof that given the conditions (`preRoot` and `packedDeletionIndices`),\n deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y`\n coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`,\n and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x`\n and `y` coordinates for `krs`.\n @param batchSize The number of identities that are to be deleted in the current batch.\n @param packedDeletionIndices The indices of the identities that were deleted from the tree.\n @param preRoot The value for the root of the tree before the `identityCommitments` have been\n inserted. Must be an element of the field `Kr`.\n @param postRoot The root obtained after deleting all of `identityCommitments` into the tree\n described by `preRoot`. Must be an element of the field `Kr`.\n @custom:reverts Unauthorized If the message sender is not authorised to add identities.\n @custom:reverts InvalidCommitment If one or more of the provided commitments is invalid.\n @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root.\n @custom:reverts ProofValidationFailure If `deletionProof` cannot be verified using the\n provided inputs.\n @custom:reverts UnreducedElement If any of the `preRoot`, `postRoot` and\n `identityCommitments` is not an element of the field `Kr`. It describes the\n type and value of the unreduced element.\n @custom:reverts VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known\n verifier.\n @custom:reverts VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum\n batch size." + }, + "functionSelector": "23cfdba5", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 33937, + "kind": "modifierInvocation", + "modifierName": { + "id": 33936, + "name": "onlyProxy", + "nameLocations": [ + "6593:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "6593:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "6593:9:43" + }, + { + "id": 33939, + "kind": "modifierInvocation", + "modifierName": { + "id": 33938, + "name": "onlyInitialized", + "nameLocations": [ + "6603:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "6603:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "6603:15:43" + }, + { + "id": 33941, + "kind": "modifierInvocation", + "modifierName": { + "id": 33940, + "name": "onlyIdentityOperator", + "nameLocations": [ + "6619:20:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 33895, + "src": "6619:20:43" + }, + "nodeType": "ModifierInvocation", + "src": "6619:20:43" + } + ], + "name": "deleteIdentities", + "nameLocation": "6389:16:43", + "parameters": { + "id": 33935, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 33926, + "mutability": "mutable", + "name": "deletionProof", + "nameLocation": "6435:13:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6415:33:43", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8]" + }, + "typeName": { + "baseType": { + "id": 33923, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6415:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 33925, + "length": { + "hexValue": "38", + "id": 33924, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6423:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_8_by_1", + "typeString": "int_const 8" + }, + "value": "8" + }, + "nodeType": "ArrayTypeName", + "src": "6415:10:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_storage_ptr", + "typeString": "uint256[8]" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33928, + "mutability": "mutable", + "name": "batchSize", + "nameLocation": "6465:9:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6458:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + }, + "typeName": { + "id": 33927, + "name": "uint32", + "nodeType": "ElementaryTypeName", + "src": "6458:6:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33930, + "mutability": "mutable", + "name": "packedDeletionIndices", + "nameLocation": "6499:21:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6484:36:43", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 33929, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "6484:5:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33932, + "mutability": "mutable", + "name": "preRoot", + "nameLocation": "6538:7:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6530:15:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33931, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6530:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33934, + "mutability": "mutable", + "name": "postRoot", + "nameLocation": "6563:8:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6555:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33933, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6555:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "6405:172:43" + }, + "returnParameters": { + "id": 33942, + "nodeType": "ParameterList", + "parameters": [], + "src": "6640:0:43" + }, + "scope": 34135, + "stateMutability": "nonpayable", + "virtual": true, + "visibility": "public" + }, + { + "id": 34078, + "nodeType": "FunctionDefinition", + "src": "9156:228:43", + "nodes": [], + "body": { + "id": 34077, + "nodeType": "Block", + "src": "9329:55:43", + "nodes": [], + "statements": [ + { + "expression": { + "arguments": [ + { + "id": 34074, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "9354:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + ], + "id": 34073, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "9346:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 34072, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9346:7:43", + "typeDescriptions": {} + } + }, + "id": 34075, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "9346:31:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 34071, + "id": 34076, + "nodeType": "Return", + "src": "9339:38:43" + } + ] + }, + "documentation": { + "id": 34063, + "nodeType": "StructuredDocumentation", + "src": "8824:327:43", + "text": "@notice Gets the address for the lookup table of merkle tree verifiers used for batch identity\n deletions.\n @dev The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch.\n @return addr The address of the contract being used as the verifier lookup table." + }, + "functionSelector": "3e8919b6", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 34066, + "kind": "modifierInvocation", + "modifierName": { + "id": 34065, + "name": "onlyProxy", + "nameLocations": [ + "9265:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "9265:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "9265:9:43" + }, + { + "id": 34068, + "kind": "modifierInvocation", + "modifierName": { + "id": 34067, + "name": "onlyInitialized", + "nameLocations": [ + "9283:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "9283:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "9283:15:43" + } + ], + "name": "getDeleteIdentitiesVerifierLookupTableAddress", + "nameLocation": "9165:45:43", + "parameters": { + "id": 34064, + "nodeType": "ParameterList", + "parameters": [], + "src": "9210:2:43" + }, + "returnParameters": { + "id": 34071, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34070, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 34078, + "src": "9316:7:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 34069, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9316:7:43", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "9315:9:43" + }, + "scope": 34135, + "stateMutability": "view", + "virtual": true, + "visibility": "public" + }, + { + "id": 34114, + "nodeType": "FunctionDefinition", + "src": "9704:418:43", + "nodes": [], + "body": { + "id": 34113, + "nodeType": "Block", + "src": "9877:245:43", + "nodes": [], + "statements": [ + { + "assignments": [ + 34093 + ], + "declarations": [ + { + "constant": false, + "id": 34093, + "mutability": "mutable", + "name": "oldTable", + "nameLocation": "9907:8:43", + "nodeType": "VariableDeclaration", + "scope": 34113, + "src": "9887:28:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 34092, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 34091, + "name": "VerifierLookupTable", + "nameLocations": [ + "9887:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "9887:19:43" + }, + "referencedDeclaration": 34425, + "src": "9887:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + } + ], + "id": 34095, + "initialValue": { + "id": 34094, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "9918:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "9887:53:43" + }, + { + "expression": { + "id": 34098, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 34096, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "9950:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 34097, + "name": "newTable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34082, + "src": "9975:8:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "src": "9950:33:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "id": 34099, + "nodeType": "ExpressionStatement", + "src": "9950:33:43" + }, + { + "eventCall": { + "arguments": [ + { + "expression": { + "id": 34101, + "name": "Dependency", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32826, + "src": "10029:10:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_Dependency_$32826_$", + "typeString": "type(enum WorldIDIdentityManagerImplV1.Dependency)" + } + }, + "id": 34102, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "10040:27:43", + "memberName": "DeletionVerifierLookupTable", + "nodeType": "MemberAccess", + "referencedDeclaration": 32823, + "src": "10029:38:43", + "typeDescriptions": { + "typeIdentifier": "t_enum$_Dependency_$32826", + "typeString": "enum WorldIDIdentityManagerImplV1.Dependency" + } + }, + { + "arguments": [ + { + "id": 34105, + "name": "oldTable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34093, + "src": "10077:8:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + ], + "id": 34104, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "10069:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 34103, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10069:7:43", + "typeDescriptions": {} + } + }, + "id": 34106, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "10069:17:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "arguments": [ + { + "id": 34109, + "name": "newTable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34082, + "src": "10096:8:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + ], + "id": 34108, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "10088:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 34107, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10088:7:43", + "typeDescriptions": {} + } + }, + "id": 34110, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "10088:17:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_enum$_Dependency_$32826", + "typeString": "enum WorldIDIdentityManagerImplV1.Dependency" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 34100, + "name": "DependencyUpdated", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32905, + "src": "9998:17:43", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_enum$_Dependency_$32826_$_t_address_$_t_address_$returns$__$", + "typeString": "function (enum WorldIDIdentityManagerImplV1.Dependency,address,address)" + } + }, + "id": 34111, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "9998:117:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34112, + "nodeType": "EmitStatement", + "src": "9993:122:43" + } + ] + }, + "documentation": { + "id": 34079, + "nodeType": "StructuredDocumentation", + "src": "9390:309:43", + "text": "@notice Sets the address for the lookup table of merkle tree verifiers used for identity\n deletions.\n @dev Only the owner of the contract can call this function.\n @param newTable The new verifier lookup table to be used for verifying identity\n deletions." + }, + "functionSelector": "aa4a729e", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 34085, + "kind": "modifierInvocation", + "modifierName": { + "id": 34084, + "name": "onlyProxy", + "nameLocations": [ + "9821:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "9821:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "9821:9:43" + }, + { + "id": 34087, + "kind": "modifierInvocation", + "modifierName": { + "id": 34086, + "name": "onlyInitialized", + "nameLocations": [ + "9839:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "9839:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "9839:15:43" + }, + { + "id": 34089, + "kind": "modifierInvocation", + "modifierName": { + "id": 34088, + "name": "onlyOwner", + "nameLocations": [ + "9863:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29157, + "src": "9863:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "9863:9:43" + } + ], + "name": "setDeleteIdentitiesVerifierLookupTable", + "nameLocation": "9713:38:43", + "parameters": { + "id": 34083, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34082, + "mutability": "mutable", + "name": "newTable", + "nameLocation": "9772:8:43", + "nodeType": "VariableDeclaration", + "scope": 34114, + "src": "9752:28:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 34081, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 34080, + "name": "VerifierLookupTable", + "nameLocations": [ + "9752:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "9752:19:43" + }, + "referencedDeclaration": 34425, + "src": "9752:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + } + ], + "src": "9751:30:43" + }, + "returnParameters": { + "id": 34090, + "nodeType": "ParameterList", + "parameters": [], + "src": "9877:0:43" + }, + "scope": 34135, + "stateMutability": "nonpayable", + "virtual": true, + "visibility": "public" + }, + { + "id": 34134, + "nodeType": "FunctionDefinition", + "src": "11363:685:43", + "nodes": [], + "body": { + "id": 34133, + "nodeType": "Block", + "src": "11605:443:43", + "nodes": [], + "statements": [ + { + "AST": { + "nativeSrc": "11624:418:43", + "nodeType": "YulBlock", + "src": "11624:418:43", + "statements": [ + { + "nativeSrc": "11638:30:43", + "nodeType": "YulVariableDeclaration", + "src": "11638:30:43", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "11663:4:43", + "nodeType": "YulLiteral", + "src": "11663:4:43", + "type": "", + "value": "0x40" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "11657:5:43", + "nodeType": "YulIdentifier", + "src": "11657:5:43" + }, + "nativeSrc": "11657:11:43", + "nodeType": "YulFunctionCall", + "src": "11657:11:43" + }, + "variables": [ + { + "name": "startOffset", + "nativeSrc": "11642:11:43", + "nodeType": "YulTypedName", + "src": "11642:11:43", + "type": "" + } + ] + }, + { + "nativeSrc": "11681:40:43", + "nodeType": "YulVariableDeclaration", + "src": "11681:40:43", + "value": { + "arguments": [ + { + "name": "batchSize", + "nativeSrc": "11708:9:43", + "nodeType": "YulIdentifier", + "src": "11708:9:43" + }, + { + "kind": "number", + "nativeSrc": "11719:1:43", + "nodeType": "YulLiteral", + "src": "11719:1:43", + "type": "", + "value": "4" + } + ], + "functionName": { + "name": "mul", + "nativeSrc": "11704:3:43", + "nodeType": "YulIdentifier", + "src": "11704:3:43" + }, + "nativeSrc": "11704:17:43", + "nodeType": "YulFunctionCall", + "src": "11704:17:43" + }, + "variables": [ + { + "name": "indicesByteSize", + "nativeSrc": "11685:15:43", + "nodeType": "YulTypedName", + "src": "11685:15:43", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "startOffset", + "nativeSrc": "11747:11:43", + "nodeType": "YulIdentifier", + "src": "11747:11:43" + }, + { + "name": "packedDeletionIndices.offset", + "nativeSrc": "11760:28:43", + "nodeType": "YulIdentifier", + "src": "11760:28:43" + }, + { + "name": "indicesByteSize", + "nativeSrc": "11790:15:43", + "nodeType": "YulIdentifier", + "src": "11790:15:43" + } + ], + "functionName": { + "name": "calldatacopy", + "nativeSrc": "11734:12:43", + "nodeType": "YulIdentifier", + "src": "11734:12:43" + }, + "nativeSrc": "11734:72:43", + "nodeType": "YulFunctionCall", + "src": "11734:72:43" + }, + "nativeSrc": "11734:72:43", + "nodeType": "YulExpressionStatement", + "src": "11734:72:43" + }, + { + "nativeSrc": "11819:52:43", + "nodeType": "YulVariableDeclaration", + "src": "11819:52:43", + "value": { + "arguments": [ + { + "name": "startOffset", + "nativeSrc": "11842:11:43", + "nodeType": "YulIdentifier", + "src": "11842:11:43" + }, + { + "name": "indicesByteSize", + "nativeSrc": "11855:15:43", + "nodeType": "YulIdentifier", + "src": "11855:15:43" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "11838:3:43", + "nodeType": "YulIdentifier", + "src": "11838:3:43" + }, + "nativeSrc": "11838:33:43", + "nodeType": "YulFunctionCall", + "src": "11838:33:43" + }, + "variables": [ + { + "name": "rootsOffset", + "nativeSrc": "11823:11:43", + "nodeType": "YulTypedName", + "src": "11823:11:43", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "rootsOffset", + "nativeSrc": "11891:11:43", + "nodeType": "YulIdentifier", + "src": "11891:11:43" + }, + { + "name": "preRoot", + "nativeSrc": "11904:7:43", + "nodeType": "YulIdentifier", + "src": "11904:7:43" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "11884:6:43", + "nodeType": "YulIdentifier", + "src": "11884:6:43" + }, + "nativeSrc": "11884:28:43", + "nodeType": "YulFunctionCall", + "src": "11884:28:43" + }, + "nativeSrc": "11884:28:43", + "nodeType": "YulExpressionStatement", + "src": "11884:28:43" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "rootsOffset", + "nativeSrc": "11936:11:43", + "nodeType": "YulIdentifier", + "src": "11936:11:43" + }, + { + "kind": "number", + "nativeSrc": "11949:2:43", + "nodeType": "YulLiteral", + "src": "11949:2:43", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "11932:3:43", + "nodeType": "YulIdentifier", + "src": "11932:3:43" + }, + "nativeSrc": "11932:20:43", + "nodeType": "YulFunctionCall", + "src": "11932:20:43" + }, + { + "name": "postRoot", + "nativeSrc": "11954:8:43", + "nodeType": "YulIdentifier", + "src": "11954:8:43" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "11925:6:43", + "nodeType": "YulIdentifier", + "src": "11925:6:43" + }, + "nativeSrc": "11925:38:43", + "nodeType": "YulFunctionCall", + "src": "11925:38:43" + }, + "nativeSrc": "11925:38:43", + "nodeType": "YulExpressionStatement", + "src": "11925:38:43" + }, + { + "nativeSrc": "11976:56:43", + "nodeType": "YulAssignment", + "src": "11976:56:43", + "value": { + "arguments": [ + { + "name": "startOffset", + "nativeSrc": "11994:11:43", + "nodeType": "YulIdentifier", + "src": "11994:11:43" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "12011:2:43", + "nodeType": "YulLiteral", + "src": "12011:2:43", + "type": "", + "value": "64" + }, + { + "name": "indicesByteSize", + "nativeSrc": "12015:15:43", + "nodeType": "YulIdentifier", + "src": "12015:15:43" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "12007:3:43", + "nodeType": "YulIdentifier", + "src": "12007:3:43" + }, + "nativeSrc": "12007:24:43", + "nodeType": "YulFunctionCall", + "src": "12007:24:43" + } + ], + "functionName": { + "name": "keccak256", + "nativeSrc": "11984:9:43", + "nodeType": "YulIdentifier", + "src": "11984:9:43" + }, + "nativeSrc": "11984:48:43", + "nodeType": "YulFunctionCall", + "src": "11984:48:43" + }, + "variableNames": [ + { + "name": "hash", + "nativeSrc": "11976:4:43", + "nodeType": "YulIdentifier", + "src": "11976:4:43" + } + ] + } + ] + }, + "evmVersion": "paris", + "externalReferences": [ + { + "declaration": 34123, + "isOffset": false, + "isSlot": false, + "src": "11708:9:43", + "valueSize": 1 + }, + { + "declaration": 34130, + "isOffset": false, + "isSlot": false, + "src": "11976:4:43", + "valueSize": 1 + }, + { + "declaration": 34117, + "isOffset": true, + "isSlot": false, + "src": "11760:28:43", + "suffix": "offset", + "valueSize": 1 + }, + { + "declaration": 34121, + "isOffset": false, + "isSlot": false, + "src": "11954:8:43", + "valueSize": 1 + }, + { + "declaration": 34119, + "isOffset": false, + "isSlot": false, + "src": "11904:7:43", + "valueSize": 1 + } + ], + "id": 34132, + "nodeType": "InlineAssembly", + "src": "11615:427:43" + } + ] + }, + "documentation": { + "id": 34115, + "nodeType": "StructuredDocumentation", + "src": "10381:977:43", + "text": "@notice Calculates the input hash for the identity deletion verifier.\n @dev Implements the computation described below.\n @param packedDeletionIndices The indices of the identities that were deleted from the tree.\n @param preRoot The root value of the tree before these insertions were made.\n @param postRoot The root value of the tree after these insertions were made.\n @param batchSize The number of identities that were deleted in this batch\n @return hash The input hash calculated as described below.\n @dev the deletion indices are packed into bytes calldata where each deletion index is 32 bits\n wide. The indices are encoded using abi.encodePacked for testing.\n We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows:\n packedDeletionIndices || PreRoot || PostRoot\n 32 bits * batchSize || 256 || 256" + }, + "functionSelector": "31e4e992", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 34126, + "kind": "modifierInvocation", + "modifierName": { + "id": 34125, + "name": "onlyProxy", + "nameLocations": [ + "11556:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "11556:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "11556:9:43" + }, + { + "id": 34128, + "kind": "modifierInvocation", + "modifierName": { + "id": 34127, + "name": "onlyInitialized", + "nameLocations": [ + "11566:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "11566:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "11566:15:43" + } + ], + "name": "calculateIdentityDeletionInputHash", + "nameLocation": "11372:34:43", + "parameters": { + "id": 34124, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34117, + "mutability": "mutable", + "name": "packedDeletionIndices", + "nameLocation": "11431:21:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11416:36:43", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 34116, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "11416:5:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34119, + "mutability": "mutable", + "name": "preRoot", + "nameLocation": "11470:7:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11462:15:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 34118, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "11462:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34121, + "mutability": "mutable", + "name": "postRoot", + "nameLocation": "11495:8:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11487:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 34120, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "11487:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34123, + "mutability": "mutable", + "name": "batchSize", + "nameLocation": "11520:9:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11513:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + }, + "typeName": { + "id": 34122, + "name": "uint32", + "nodeType": "ElementaryTypeName", + "src": "11513:6:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + }, + "visibility": "internal" + } + ], + "src": "11406:129:43" + }, + "returnParameters": { + "id": 34131, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34130, + "mutability": "mutable", + "name": "hash", + "nameLocation": "11599:4:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11591:12:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 34129, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "11591:7:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "src": "11590:14:43" + }, + "scope": 34135, + "stateMutability": "view", + "virtual": true, + "visibility": "public" + } + ], + "abstract": false, + "baseContracts": [ + { + "baseName": { + "id": 33901, + "name": "WorldIDIdentityManagerImplV1", + "nameLocations": [ + "484:28:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 33896, + "src": "484:28:43" + }, + "id": 33902, + "nodeType": "InheritanceSpecifier", + "src": "484:28:43" + } + ], + "canonicalName": "WorldIDIdentityManagerImplV2", + "contractDependencies": [], + "contractKind": "contract", + "documentation": { + "id": 33900, + "nodeType": "StructuredDocumentation", + "src": "72:371:43", + "text": "@title WorldID Identity Manager Implementation Version 2\n @author Worldcoin\n @notice An implementation of a batch-based identity manager for the WorldID protocol.\n @dev The manager is based on the principle of verifying externally-created Zero Knowledge Proofs\n to perform the insertions.\n @dev This is the implementation delegated to by a proxy." + }, + "fullyImplemented": true, + "linearizedBaseContracts": [ + 34135, + 33896, + 34502, + 34435, + 34190, + 47879, + 29937, + 29622, + 29253, + 29111, + 29243, + 30263, + 29801 + ], + "name": "WorldIDIdentityManagerImplV2", + "nameLocation": "452:28:43", + "scope": 34136, + "usedErrors": [ + 32848, + 32853, + 32858, + 32861, + 32868, + 32871, + 32874, + 32877, + 32882, + 32885, + 34166, + 34431, + 34434, + 47850 + ], + "usedEvents": [ + 29037, + 29128, + 29287, + 29431, + 29496, + 29647, + 32895, + 32905, + 32910, + 32917, + 32924, + 32931 + ] + } + ] + }, + "id": 43 +} \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index dcaca85c..77257d85 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::time::Instant; use anyhow::Result as AnyhowResult; -use chrono::{DateTime, Utc}; +use chrono::{Utc}; use clap::Parser; use hyper::StatusCode; use ruint::Uint; @@ -326,7 +326,7 @@ impl App { } self.database - .insert_new_identity(commitment, DateTime::from(Utc::now())) + .insert_new_identity(commitment, Utc::now()) .await?; Ok(()) @@ -349,10 +349,14 @@ impl App { return Err(ServerError::NoProversOnIdDeletion); } + if !self.database.identity_exists(*commitment).await? { + return Err(ServerError::IdentityCommitmentNotFound); + } + // Get the leaf index for the id commitment let leaf_index = self .database - .get_identity_leaf_index(&commitment) + .get_identity_leaf_index(commitment) .await? .ok_or(ServerError::IdentityCommitmentNotFound)? .leaf_index; @@ -380,7 +384,7 @@ impl App { // If the id has not been deleted, insert into the deletions table self.database - .insert_new_deletion(leaf_index, &commitment) + .insert_new_deletion(leaf_index, commitment) .await?; Ok(()) @@ -408,10 +412,10 @@ impl App { } // Delete the existing id and insert the commitments into the recovery table - self.delete_identity(&existing_commitment).await?; + self.delete_identity(existing_commitment).await?; self.database - .insert_new_recovery(&existing_commitment, &new_commitment) + .insert_new_recovery(existing_commitment, new_commitment) .await?; Ok(()) @@ -526,7 +530,11 @@ impl App { .await? .ok_or(ServerError::IdentityCommitmentNotFound)?; - let proof = self.tree_state.get_proof_for(&item); + let (leaf, proof) = self.tree_state.get_proof_for(&item); + + if leaf != *commitment { + return Err(ServerError::InvalidCommitment); + } Ok(InclusionProofResponse(proof)) } @@ -540,7 +548,7 @@ impl App { request: &VerifySemaphoreProofRequest, ) -> Result { let Some(root_state) = self.database.get_root_state(&request.root).await? else { - return Err(ServerError::InvalidRoot) + return Err(ServerError::InvalidRoot); }; let checked = verify_proof( diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index 07e69fe7..e0bc9be0 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -7,7 +7,7 @@ abigen!( r#"[ struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual - function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, bytes calldata deletionIndices, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint32 batchSize, bytes calldata packedDeletionIndices, uint256 preRoot, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 504353c5..8a9f375f 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -6,9 +6,10 @@ use std::sync::Arc; use anyhow::anyhow; use clap::Parser; -use ethers::abi::ethabi::Bytes; + use ethers::providers::Middleware; use ethers::types::{Address, U256}; + use semaphore::Field; use tokio::sync::RwLockReadGuard; use tracing::{error, info, instrument, warn}; @@ -227,7 +228,7 @@ impl IdentityManager { pub async fn prepare_deletion_proof( prover: ReadOnlyProver<'_, Prover>, pre_root: U256, - deletion_indices: &[u32], + packed_deletion_indices: Vec, identity_commitments: Vec, post_root: U256, ) -> anyhow::Result { @@ -238,7 +239,12 @@ impl IdentityManager { ); let proof_data: Proof = prover - .generate_deletion_proof(pre_root, post_root, deletion_indices, identity_commitments) + .generate_deletion_proof( + pre_root, + post_root, + packed_deletion_indices, + identity_commitments, + ) .await?; Ok(proof_data) @@ -286,26 +292,20 @@ impl IdentityManager { pub async fn delete_identities( &self, deletion_proof: Proof, + batch_size: u32, + packed_deletion_indices: Vec, pre_root: U256, - deletion_indices: Vec, post_root: U256, ) -> anyhow::Result { let proof_points_array: [U256; 8] = deletion_proof.into(); - // We want to send the transaction through our ethereum provider rather than - // directly now. To that end, we create it, and then send it later, waiting for - // it to complete. - let deletion_indices = deletion_indices - .iter() - .flat_map(|&idx| idx.to_be_bytes().to_vec()) - .collect::>(); - let register_identities_transaction = self .abi .delete_identities( proof_points_array, + batch_size, + packed_deletion_indices.into(), pre_root, - deletion_indices.into(), post_root, ) .tx; @@ -319,6 +319,7 @@ impl IdentityManager { #[instrument(level = "debug", skip(self))] pub async fn mine_identities(&self, transaction_id: TransactionId) -> anyhow::Result { let result = self.ethereum.mine_transaction(transaction_id).await?; + Ok(result) } diff --git a/src/database/mod.rs b/src/database/mod.rs index 61b226c8..738190d5 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -19,7 +19,7 @@ use self::types::{DeletionEntry, LatestDeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod types; -use crate::prover::{self, ProverConfiguration, ProverType, Provers}; +use crate::prover::{ProverConfiguration, ProverType, Provers}; use crate::secret::SecretUrl; // Statically link in migration files @@ -190,9 +190,7 @@ impl Database { let root_leaf_index = Self::get_leaf_index_by_root(&mut tx, root).await?; let Some(root_leaf_index) = root_leaf_index else { - return Err(Error::MissingRoot { - root: *root - }); + return Err(Error::MissingRoot { root: *root }); }; let root_leaf_index = root_leaf_index as i64; @@ -240,9 +238,7 @@ impl Database { let root_leaf_index = Self::get_leaf_index_by_root(&mut tx, root).await?; let Some(root_leaf_index) = root_leaf_index else { - return Err(Error::MissingRoot { - root: *root - }); + return Err(Error::MissingRoot { root: *root }); }; let root_leaf_index = root_leaf_index as i64; @@ -291,6 +287,7 @@ impl Database { SELECT leaf_index, status FROM identities WHERE commitment = $1 + ORDER BY id DESC LIMIT 1; "#, ) @@ -411,12 +408,7 @@ impl Database { let url = row.get::(1); let timeout_s = row.get::(2) as u64; let prover_type = row.get::(3); - ProverConfiguration { - url, - batch_size, - timeout_s, - prover_type, - } + ProverConfiguration { url, timeout_s, batch_size, prover_type } }) .collect::()) } @@ -536,7 +528,7 @@ impl Database { }) } else { Ok(LatestDeletionEntry { - timestamp: DateTime::from(Utc::now()), + timestamp: Utc::now(), }) } } @@ -549,11 +541,11 @@ impl Database { r#" INSERT INTO latest_deletion_root (Lock, deletion_timestamp) VALUES ('X', $1) - ON CONFLICT (Lock) + ON CONFLICT (Lock) DO UPDATE SET deletion_timestamp = EXCLUDED.deletion_timestamp; "#, ) - .bind(&deletion_timestamp); + .bind(deletion_timestamp); self.pool.execute(query).await?; Ok(()) @@ -635,7 +627,7 @@ impl Database { let mut query = sqlx::query(&query); - for commitment in commitments.iter() { + for commitment in &commitments { query = query.bind(commitment); } @@ -779,7 +771,7 @@ mod test { use ruint::Uint; use semaphore::Field; use sqlx::types::chrono::DateTime; - use sqlx::{PgPool, Row}; + use sqlx::{Row}; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; @@ -856,7 +848,7 @@ mod test { .expect("cant convert to u256") .into(); - let eligibility_timestamp = DateTime::from(Utc::now()); + let eligibility_timestamp = Utc::now(); let hash = db .insert_new_identity(commit_hash, eligibility_timestamp) @@ -882,6 +874,28 @@ mod test { Ok(()) } + #[tokio::test] + async fn insert_and_delete_identity() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let zero: Hash = U256::zero().into(); + let zero_root: Hash = U256::from_dec_str("6789")?.into(); + let root: Hash = U256::from_dec_str("54321")?.into(); + let commitment: Hash = U256::from_dec_str("12345")?.into(); + + db.insert_pending_identity(0, &commitment, &root).await?; + db.insert_pending_identity(0, &zero, &zero_root).await?; + + let leaf_index = db + .get_identity_leaf_index(&commitment) + .await? + .context("Missing identity")?; + + assert_eq!(leaf_index.leaf_index, 0); + + Ok(()) + } + fn mock_provers() -> HashSet { let mut provers = HashSet::new(); @@ -1009,13 +1023,13 @@ mod test { async fn test_get_eligible_unprocessed_commitments() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let commitment_0: Uint<256, 4> = Uint::from(1); - let eligibility_timestamp_0 = DateTime::from(Utc::now()); + let eligibility_timestamp_0 = Utc::now(); db.insert_new_identity(commitment_0, eligibility_timestamp_0) .await?; let commitment_1: Uint<256, 4> = Uint::from(2); - let eligibility_timestamp_1 = DateTime::from(Utc::now()) + let eligibility_timestamp_1 = Utc::now() .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); @@ -1040,13 +1054,13 @@ mod test { // Insert new identity with a valid eligibility timestamp let commitment_0: Uint<256, 4> = Uint::from(1); - let eligibility_timestamp_0 = DateTime::from(Utc::now()); + let eligibility_timestamp_0 = Utc::now(); db.insert_new_identity(commitment_0, eligibility_timestamp_0) .await?; // Insert new identity with eligibility timestamp in the future let commitment_1: Uint<256, 4> = Uint::from(2); - let eligibility_timestamp_1 = DateTime::from(Utc::now()) + let eligibility_timestamp_1 = Utc::now() .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); db.insert_new_identity(commitment_1, eligibility_timestamp_1) @@ -1061,11 +1075,6 @@ mod test { unprocessed_commitments[0].eligibility_timestamp, eligibility_timestamp_0 ); - assert_eq!(unprocessed_commitments[1].commitment, commitment_1); - assert_eq!( - unprocessed_commitments[1].eligibility_timestamp, - eligibility_timestamp_1 - ); Ok(()) } @@ -1094,7 +1103,7 @@ mod test { .into(); // Set eligibility to Utc::now() day and check db entries - let eligibility_timestamp = DateTime::from(Utc::now()); + let eligibility_timestamp = Utc::now(); db.insert_new_identity(commit_hash, eligibility_timestamp) .await?; @@ -1105,7 +1114,7 @@ mod test { assert_eq!(eligible_commitments.len(), 1); // Set eligibility to Utc::now() + 7 days and check db entries - let eligibility_timestamp = DateTime::from(Utc::now()) + let eligibility_timestamp = Utc::now() .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); @@ -1520,7 +1529,7 @@ mod test { assert!(!db.identity_exists(identities[0]).await?); // When there's only unprocessed identity - let eligibility_timestamp = DateTime::from(Utc::now()); + let eligibility_timestamp = Utc::now(); db.insert_new_identity(identities[0], eligibility_timestamp) .await diff --git a/src/identity_tree.rs b/src/identity_tree.rs index 510f6a4b..1ec7087d 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -185,7 +185,7 @@ where /// Gets the leaf value at a given index. fn get_leaf(&self, leaf: usize) -> Hash { - self.get_leaf(leaf) + self.tree.get_leaf(leaf) } /// Gets the proof of the given leaf index element @@ -197,7 +197,9 @@ where /// Returns _up to_ `maximum_update_count` contiguous deletion or insertion /// updates that are to be applied to the tree. fn peek_next_updates(&self, maximum_update_count: usize) -> Vec { - let Some(next) = self.next.as_ref() else { return vec![]; }; + let Some(next) = self.next.as_ref() else { + return vec![]; + }; let next = next.get_data(); let first_is_zero = match next.metadata.diff.first() { @@ -226,7 +228,9 @@ where } fn apply_updates_up_to(&mut self, root: Hash) -> usize { - let Some(next) = self.next.clone() else { return 0; }; + let Some(next) = self.next.clone() else { + return 0; + }; let num_updates; { @@ -262,7 +266,9 @@ impl BasicTreeOps for TreeVersionData { take_mut::take(&mut self.tree, |tree| { tree.update_with_mutation(leaf_index, &element) }); - self.next_leaf = leaf_index + 1; + if element != Hash::ZERO { + self.next_leaf = leaf_index + 1; + } self.metadata.count_since_last_flatten += 1; } @@ -314,7 +320,9 @@ impl BasicTreeOps for TreeVersionData { self.tree = updated_tree.clone(); - self.next_leaf = leaf_index + 1; + if element != Hash::ZERO { + self.next_leaf = leaf_index + 1; + } self.metadata.diff.push(AppliedTreeUpdate { update: TreeUpdate { leaf_index, @@ -331,7 +339,10 @@ impl BasicTreeOps for TreeVersionData { if let Some(last) = last { self.tree = last.result.clone(); - self.next_leaf = last.update.leaf_index + 1; + + if last.update.element != Hash::ZERO { + self.next_leaf = last.update.leaf_index + 1; + } } } @@ -417,6 +428,8 @@ pub trait TreeVersionReadOps { fn get_root(&self) -> Hash; /// Returns the next free leaf. fn next_leaf(&self) -> usize; + /// Returns the given leaf value, the root of the tree and the proof + fn get_leaf_and_proof(&self, leaf: usize) -> (Hash, Hash, Proof); /// Returns the merkle proof and element at the given leaf. fn get_proof(&self, leaf: usize) -> (Hash, Proof); /// Gets the leaf value at a given index. @@ -435,6 +448,15 @@ where self.get_data().next_leaf } + fn get_leaf_and_proof(&self, leaf: usize) -> (Hash, Hash, Proof) { + let tree = self.get_data(); + + let (root, proof) = tree.get_proof(leaf); + let leaf = tree.get_leaf(leaf); + + (leaf, root, proof) + } + fn get_proof(&self, leaf: usize) -> (Hash, Proof) { let tree = self.get_data(); tree.get_proof(leaf) @@ -476,7 +498,7 @@ impl TreeVersion { /// Deletes many identities from the tree, returns a list with the root /// and proof of inclusion - pub fn delete_many(&self, leaf_indices: &[usize]) -> Vec<(Hash, Proof)> { + #[must_use] pub fn delete_many(&self, leaf_indices: &[usize]) -> Vec<(Hash, Proof)> { let mut data = self.get_data(); let mut output = Vec::with_capacity(leaf_indices.len()); @@ -558,21 +580,23 @@ impl TreeState { } #[must_use] - pub fn get_proof_for(&self, item: &TreeItem) -> InclusionProof { - let (root, proof) = match item.status { + pub fn get_proof_for(&self, item: &TreeItem) -> (Field, InclusionProof) { + let (leaf, root, proof) = match item.status { Status::Pending | Status::New | Status::Failed => { - self.latest.get_proof(item.leaf_index) + self.latest.get_leaf_and_proof(item.leaf_index) } - Status::Processed => self.processed.get_proof(item.leaf_index), - Status::Mined => self.mined.get_proof(item.leaf_index), + Status::Processed => self.processed.get_leaf_and_proof(item.leaf_index), + Status::Mined => self.mined.get_leaf_and_proof(item.leaf_index), }; - InclusionProof { + let proof = InclusionProof { status: item.status, root: Some(root), proof: Some(proof), message: None, - } + }; + + (leaf, proof) } } @@ -701,18 +725,17 @@ impl DerivedTreeBuilder

{ #[cfg(test)] mod tests { - use semaphore::lazy_merkle_tree::{Canonical, LazyMerkleTree}; - use semaphore::poseidon_tree::PoseidonHash; + + use super::{ - AppliedTreeUpdate, CanonicalTreeBuilder, DerivedTreeBuilder, Hash, PoseidonTree, - TreeVersion, TreeWithNextVersion, + CanonicalTreeBuilder, Hash, TreeWithNextVersion, }; #[test] fn test_peek_next_updates() { let (canonical_tree, processed_builder) = - CanonicalTreeBuilder::new(10, 10, 0, Hash::ZERO, &vec![]).seal(); + CanonicalTreeBuilder::new(10, 10, 0, Hash::ZERO, &[]).seal(); let processed_tree = processed_builder.seal(); let insertion_updates = processed_tree.append_many(&vec![ Hash::from(1), @@ -724,7 +747,7 @@ mod tests { Hash::from(7), ]); - let _deletion_updates = processed_tree.delete_many(&vec![0, 1, 2]); + let _deletion_updates = processed_tree.delete_many(&[0, 1, 2]); let next_updates = canonical_tree.peek_next_updates(10); assert_eq!(next_updates.len(), 7); @@ -736,12 +759,10 @@ mod tests { .0, ); - let _ = processed_tree.append_many(&vec![ - Hash::from(5), + let _ = processed_tree.append_many(&[Hash::from(5), Hash::from(6), Hash::from(7), - Hash::from(8), - ]); + Hash::from(8)]); let next_updates = canonical_tree.peek_next_updates(10); diff --git a/src/prover/map.rs b/src/prover/map.rs index 8712b90c..29263374 100644 --- a/src/prover/map.rs +++ b/src/prover/map.rs @@ -1,5 +1,5 @@ use std::collections::BTreeMap; -use std::hash::{Hash, Hasher}; + use tokio::sync::{RwLock, RwLockReadGuard}; diff --git a/src/prover/mod.rs b/src/prover/mod.rs index f1ab1b9c..e0c1b45a 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -12,7 +12,7 @@ pub mod map; pub mod proof; use std::collections::HashSet; -use std::default; + use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; use std::mem::size_of; @@ -250,7 +250,7 @@ impl Prover { &self, pre_root: U256, post_root: U256, - deletion_indices: &[u32], + packed_deletion_indices: Vec, identities: Vec, ) -> anyhow::Result { if identities.len() != self.batch_size { @@ -267,13 +267,13 @@ impl Prover { .unzip(); let input_hash = - compute_deletion_proof_input_hash(pre_root, post_root, &identity_commitments); + compute_deletion_proof_input_hash(packed_deletion_indices.clone(), pre_root, post_root); let proof_input = DeletionProofInput { input_hash, pre_root, post_root, - deletion_indices: deletion_indices.to_vec(), + packed_deletion_indices, identity_commitments, merkle_proofs, }; @@ -354,26 +354,29 @@ pub fn compute_insertion_proof_input_hash( } // TODO: check this and update docs + pub fn compute_deletion_proof_input_hash( + packed_deletion_indices: Vec, pre_root: U256, post_root: U256, - identity_commitments: &[U256], ) -> U256 { - let mut pre_root_bytes: [u8; size_of::()] = Default::default(); - pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); - let mut post_root_bytes: [u8; size_of::()] = Default::default(); - post_root.to_big_endian(post_root_bytes.as_mut_slice()); + // Convert pre_root and post_root to bytes + let mut pre_root_bytes = vec![0u8; 32]; + pre_root.to_big_endian(&mut pre_root_bytes); - let mut bytes: Vec = vec![]; - bytes.extend(pre_root_bytes.iter()); - bytes.extend(post_root_bytes.iter()); + let mut post_root_bytes = vec![0u8; 32]; + post_root.to_big_endian(&mut post_root_bytes); - for commitment in identity_commitments.iter() { - let mut commitment_bytes: [u8; size_of::()] = Default::default(); - commitment.to_big_endian(commitment_bytes.as_mut_slice()); - bytes.extend(commitment_bytes.iter()); - } + let mut bytes = vec![]; + + // Append packed_deletion_indices + bytes.extend_from_slice(&packed_deletion_indices); + + // Append pre_root and post_root bytes + bytes.extend_from_slice(&pre_root_bytes); + bytes.extend_from_slice(&post_root_bytes); + // Compute and return the Keccak-256 hash keccak256(bytes).into() } @@ -408,12 +411,12 @@ struct InsertionProofInput { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct DeletionProofInput { - input_hash: U256, - pre_root: U256, - post_root: U256, - deletion_indices: Vec, - identity_commitments: Vec, - merkle_proofs: Vec>, + input_hash: U256, + pre_root: U256, + post_root: U256, + packed_deletion_indices: Vec, + identity_commitments: Vec, + merkle_proofs: Vec>, } #[cfg(test)] diff --git a/src/server/mod.rs b/src/server/mod.rs index 05527903..4ff37c63 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -101,9 +101,9 @@ pub struct DeletionRequest { #[serde(deny_unknown_fields)] pub struct RecoveryRequest { /// The leaf index of the identity commitment to delete. - prev_identity_commitment: Hash, + previous_identity_commitment: Hash, /// The new identity commitment to insert. - new_identity_commitment: Hash, + new_identity_commitment: Hash, } pub trait ToResponseCode { @@ -179,8 +179,11 @@ async fn recover_identity( State(app): State>, Json(req): Json, ) -> Result<(), Error> { - app.recover_identity(&req.prev_identity_commitment, &req.new_identity_commitment) - .await?; + app.recover_identity( + &req.previous_identity_commitment, + &req.new_identity_commitment, + ) + .await?; Ok(()) } diff --git a/src/task_monitor.rs b/src/task_monitor.rs index 5f61e5fd..04364a4f 100644 --- a/src/task_monitor.rs +++ b/src/task_monitor.rs @@ -18,7 +18,7 @@ use self::tasks::process_identities::ProcessIdentities; use crate::contracts::SharedIdentityManager; use crate::database::Database; use crate::ethereum::write::TransactionId; -use crate::identity_tree::{Hash, TreeState}; +use crate::identity_tree::{TreeState}; use crate::utils::async_queue::AsyncQueue; pub mod tasks; @@ -134,12 +134,13 @@ impl RunningInstance { pub struct Options { /// The maximum number of seconds the sequencer will wait before sending a /// batch of identities to the chain, even if the batch is not full. + // TODO: do we want to change this to batch_insertion_timeout_secs #[clap(long, env, default_value = "180")] pub batch_timeout_seconds: u64, /// TODO: #[clap(long, env, default_value = "3600")] - pub deletion_time_interval: i64, + pub batch_deletion_timeout_seconds: i64, /// TODO: #[clap(long, env, default_value = "100")] @@ -185,7 +186,7 @@ pub struct TaskMonitor { pending_identities_capacity: usize, mined_roots_capacity: usize, // TODO: docs - deletion_time_interval: i64, + batch_deletion_timeout_secs: i64, // TODO: docs min_batch_deletion_size: usize, } @@ -208,7 +209,7 @@ impl TaskMonitor { batch_insert_timeout_secs, pending_identities_capacity, mined_roots_capacity, - deletion_time_interval: options.deletion_time_interval, + batch_deletion_timeout_secs: options.batch_deletion_timeout_seconds, min_batch_deletion_size: options.min_batch_deletion_size, } } @@ -304,7 +305,7 @@ impl TaskMonitor { let delete_identities = DeleteIdentities::new( self.database.clone(), self.tree_state.get_latest_tree(), - self.deletion_time_interval, + self.batch_deletion_timeout_secs, self.min_batch_deletion_size, wake_up_notify, ); diff --git a/src/task_monitor/tasks/delete_identities.rs b/src/task_monitor/tasks/delete_identities.rs index 79487cf9..0af44c78 100644 --- a/src/task_monitor/tasks/delete_identities.rs +++ b/src/task_monitor/tasks/delete_identities.rs @@ -2,11 +2,11 @@ use std::collections::HashSet; use std::sync::Arc; use anyhow::Result as AnyhowResult; -use chrono::{DateTime, Utc}; +use chrono::{Utc}; use tokio::sync::Notify; use tracing::info; -use crate::contracts::SharedIdentityManager; + use crate::database::types::DeletionEntry; use crate::database::Database; use crate::identity_tree::{Hash, Latest, TreeVersion}; @@ -63,11 +63,14 @@ async fn delete_identities( let deletions = database.get_deletions().await?; if deletions.is_empty() { // Sleep for one hour - tokio::time::sleep(tokio::time::Duration::from_secs(3600)).await; + // TODO: should we make this dynamic? This causes an issue with tests so its set + // to 1 sec atm + tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; continue; } let last_deletion_timestamp = database.get_latest_deletion().await?.timestamp; + // If the minimum deletions batch size is reached or the deletion time interval // has elapsed, run a batch of deletions if deletions.len() >= min_deletion_batch_size @@ -76,7 +79,6 @@ async fn delete_identities( // Dedup deletion entries let deletions = deletions .into_iter() - .map(|f| f) .collect::>(); let (leaf_indices, previous_commitments): (Vec, Vec) = deletions diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs index 49ff3681..fc5e9163 100644 --- a/src/task_monitor/tasks/mine_identities.rs +++ b/src/task_monitor/tasks/mine_identities.rs @@ -2,18 +2,18 @@ use std::collections::HashMap; use std::sync::Arc; use anyhow::{Context, Result as AnyhowResult}; -use chrono::{DateTime, Days, Utc}; +use chrono::{DateTime, Utc}; use ethers::types::U256; use tracing::{info, instrument}; -use crate::contracts::abi::WorldId; + use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; use crate::identity_tree::{Hash, Intermediate, TreeVersion, TreeWithNextVersion}; use crate::task_monitor::{ PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, }; -use crate::utils::async_queue::{AsyncPopGuard, AsyncQueue}; +use crate::utils::async_queue::{AsyncQueue}; pub struct MineIdentities { database: Arc, diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 0f8fad56..7f70928a 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -1,15 +1,15 @@ -use std::collections::HashMap; + use std::sync::Arc; use std::time::{Duration, SystemTime}; use anyhow::{Context, Result as AnyhowResult}; -use chrono::{Days, Utc}; + use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{register_histogram, Histogram}; use ruint::Uint; use semaphore::merkle_tree::Proof; -use semaphore::poseidon_tree::{Branch, PoseidonHash}; +use semaphore::poseidon_tree::{Branch}; use tokio::sync::Notify; use tokio::{select, time}; use tracing::{debug, error, info, instrument, warn}; @@ -20,7 +20,7 @@ use crate::identity_tree::{ AppliedTreeUpdate, Hash, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, }; use crate::prover::identity::Identity; -use crate::prover::map::ReadOnlyInsertionProver; + use crate::prover::{Prover, ReadOnlyProver}; use crate::task_monitor::{ PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, @@ -228,7 +228,7 @@ async fn commit_identities( identity_manager, batching_tree, pending_batch_submissions_queue, - &updates, + updates, prover, ) .await?; @@ -248,7 +248,7 @@ async fn commit_identities( identity_manager, batching_tree, pending_batch_submissions_queue, - &updates, + updates, prover, ) .await?; @@ -466,10 +466,19 @@ pub async fn delete_identities( // Grab the initial conditions before the updates are applied to the tree. let pre_root: U256 = batching_tree.get_root().into(); - let mut commitments: Vec = updates + + let mut deletion_indices = updates .iter() - .map(|update| update.update.element.into()) - .collect(); + .map(|f| f.update.leaf_index as u32) + .collect::>(); + + // TODO: note that using `batching_tree.get_leaf()` locks the tree every time + // to speed this up we could write a new function that takes an input array, + // locks it once and gets all the commitments + let mut commitments = deletion_indices + .iter() + .map(|i| batching_tree.get_leaf(*i as usize).into()) + .collect::>(); let latest_tree_from_updates = updates .last() @@ -501,16 +510,11 @@ pub async fn delete_identities( let batch_size = prover.batch_size(); - let mut deletion_indices = updates - .iter() - .map(|f| f.update.leaf_index as u32) - .collect::>(); - // The verifier and prover can only work with a given batch size, so we need to // ensure that our batches match that size. We do this by padding deletion // indices with tree.depth() ^ 2. The deletion prover will skip the proof for // any deletion with an index greater than the max tree depth - let pad_index = latest_tree_from_updates.depth().pow(2) as u32; + let pad_index = 2_u32.pow(latest_tree_from_updates.depth() as u32); if commitment_count != batch_size { let padding = batch_size - commitment_count; @@ -534,6 +538,8 @@ pub async fn delete_identities( // With the updates applied we can grab the value of the tree's new root and // build our identities for sending to the identity manager. let post_root: U256 = latest_tree_from_updates.root().into(); + + // Get the previous identity let identity_commitments: Vec = commitments .iter() .zip(merkle_proofs) @@ -552,11 +558,16 @@ pub async fn delete_identities( identity_manager.validate_merkle_proofs(&identity_commitments)?; + let mut packed_deletion_indices = vec![]; + for &index in &deletion_indices { + packed_deletion_indices.extend_from_slice(&index.to_be_bytes()); + } + // We prepare the proof before reserving a slot in the pending identities let proof = IdentityManager::prepare_deletion_proof( prover, pre_root, - &deletion_indices, + packed_deletion_indices.clone(), identity_commitments, post_root, ) @@ -575,7 +586,13 @@ pub async fn delete_identities( // With all the data prepared we can submit the identities to the on-chain // identity manager and wait for that transaction to be mined. let transaction_id = identity_manager - .delete_identities(proof, pre_root, deletion_indices, post_root) + .delete_identities( + proof, + batch_size as u32, + packed_deletion_indices, + pre_root, + post_root, + ) .await .map_err(|e| { error!(?e, "Failed to insert identity to contract."); diff --git a/tests/common/abi.rs b/tests/common/abi.rs index 2f43f7fc..f857132e 100644 --- a/tests/common/abi.rs +++ b/tests/common/abi.rs @@ -18,7 +18,9 @@ abigen!( error NoSuchVerifier() error MismatchedInputLengths() constructor(address _logic, bytes memory data) payable - function initialize(uint8 treeDepth, uint256 initialRoot, address _batchInsertionVerifiers, address _batchUpdateVerifiers, address _semaphoreVerifier, bool _enableStateBridge, address stateBridge) public virtual + function initialize(uint8 treeDepth, uint256 initialRoot, address _batchInsertionVerifiers, address _batchUpdateVerifiers, address _semaphoreVerifier) public virtual + function initializeV2(address _batchDeletionVerifiers) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, bytes calldata deletionIndices, uint256 postRoot) public virtual function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual function updateIdentities(uint256[8] calldata updateProof, uint256 preRoot, uint32[] calldata leafIndices, uint256[] calldata oldIdentities, uint256[] calldata newIdentities, uint256 postRoot) public virtual function calculateIdentityRegistrationInputHash(uint32 startIndex, uint256 preRoot, uint256 postRoot, uint256[] identityCommitments) public view virtual returns (bytes32 hash) diff --git a/tests/common/chain_mock.rs b/tests/common/chain_mock.rs index 9c7ff0ed..2f6ddd97 100644 --- a/tests/common/chain_mock.rs +++ b/tests/common/chain_mock.rs @@ -29,7 +29,8 @@ pub struct MockChain { #[instrument(skip_all)] pub async fn spawn_mock_chain( initial_root: U256, - batch_sizes: &[usize], + insertion_batch_sizes: &[usize], + deletion_batch_sizes: &[usize], tree_depth: u8, ) -> anyhow::Result { let chain = Anvil::new().block_time(2u64).spawn(); @@ -95,16 +96,6 @@ pub async fn spawn_mock_chain( .send() .await?; - // The rest of the contracts can be deployed to the mock chain normally. - let mock_state_bridge_factory = - load_and_build_contract("./sol/SimpleStateBridge.json", client.clone())?; - - let mock_state_bridge = mock_state_bridge_factory - .deploy(())? - .confirmations(0usize) - .send() - .await?; - let mock_verifier_factory = load_and_build_contract("./sol/SequencerVerifier.json", client.clone())?; @@ -126,32 +117,34 @@ pub async fn spawn_mock_chain( let verifier_lookup_table_factory = load_and_build_contract("./sol/VerifierLookupTable.json", client.clone())?; - let first_batch_size = batch_sizes[0]; + let first_insertion_batch_size = insertion_batch_sizes.first().copied().unwrap_or(1); + let first_deletion_batch_size = deletion_batch_sizes.first().copied().unwrap_or(1); let insert_verifiers = verifier_lookup_table_factory .clone() - .deploy((first_batch_size as u64, mock_verifier.address()))? + .deploy((first_insertion_batch_size as u64, mock_verifier.address()))? .confirmations(0usize) .send() .await?; let update_verifiers = verifier_lookup_table_factory - .deploy((first_batch_size as u64, unimplemented_verifier.address()))? + .clone() + .deploy(( + first_insertion_batch_size as u64, + unimplemented_verifier.address(), + ))? .confirmations(0usize) .send() .await?; - let identity_manager_impl_factory = - load_and_build_contract("./sol/WorldIDIdentityManagerImplV1.json", client.clone())?; - - let identity_manager_impl = identity_manager_impl_factory - .deploy(())? + let delete_verifiers = verifier_lookup_table_factory + .deploy((first_deletion_batch_size as u64, mock_verifier.address()))? .confirmations(0usize) .send() .await?; - for batch_size in &batch_sizes[1..] { - let batch_size = *batch_size as u64; + for batch_size in insertion_batch_sizes.iter().skip(1).copied() { + let batch_size = batch_size as u64; info!("Adding verifier for batch size {}", batch_size); insert_verifiers @@ -161,10 +154,29 @@ pub async fn spawn_mock_chain( .await?; } + for batch_size in deletion_batch_sizes.iter().skip(1).copied() { + let batch_size = batch_size as u64; + + info!("Adding verifier for batch size {}", batch_size); + delete_verifiers + .method::<_, ()>("addVerifier", (batch_size, mock_verifier.address()))? + .send() + .await? + .await?; + } + + let identity_manager_impl_factory = + load_and_build_contract("./sol/WorldIDIdentityManagerImplV2.json", client.clone())?; + + let identity_manager_impl = identity_manager_impl_factory + .deploy(())? + .confirmations(0usize) + .send() + .await?; + let identity_manager_factory = load_and_build_contract("./sol/WorldIDIdentityManager.json", client.clone())?; - let state_bridge_address = mock_state_bridge.address(); - let enable_state_bridge = true; + let identity_manager_impl_address = identity_manager_impl.address(); let init_call_data = ContractAbi::InitializeCall { @@ -173,8 +185,6 @@ pub async fn spawn_mock_chain( batch_insertion_verifiers: insert_verifiers.address(), batch_update_verifiers: update_verifiers.address(), semaphore_verifier: semaphore_verifier.address(), - enable_state_bridge, - state_bridge: state_bridge_address, }; let init_call_encoded: Bytes = Bytes::from(init_call_data.encode()); @@ -190,6 +200,12 @@ pub async fn spawn_mock_chain( client.clone(), ); + identity_manager + .method::<_, ()>("initializeV2", delete_verifiers.address())? + .send() + .await? + .await?; + Ok(MockChain { anvil: chain, private_key, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 370b25e3..cfd8116e 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -48,18 +48,21 @@ pub mod prelude { pub use super::prover_mock::ProverService; pub use super::{ abi as ContractAbi, generate_reference_proof_json, generate_test_identities, - init_tracing_subscriber, spawn_app, spawn_deps, spawn_mock_prover, test_inclusion_proof, - test_insert_identity, test_verify_proof, test_verify_proof_on_chain, + init_tracing_subscriber, spawn_app, spawn_deps, spawn_mock_deletion_prover, + spawn_mock_insertion_prover, test_inclusion_proof, test_insert_identity, test_verify_proof, + test_verify_proof_on_chain, }; } use std::collections::HashMap; use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener}; +use std::str::FromStr; use std::sync::Arc; use futures::stream::FuturesUnordered; use futures::StreamExt; use hyper::StatusCode; +use signup_sequencer::identity_tree::Status; use self::chain_mock::{spawn_mock_chain, MockChain, SpecialisedContract}; use self::prelude::*; @@ -203,6 +206,134 @@ pub async fn test_inclusion_proof( } } +#[instrument(skip_all)] +pub async fn test_inclusion_status( + uri: &str, + client: &Client, + leaf: &Hash, + expected_status: Status, +) { + for _i in 1..21 { + let body = construct_inclusion_proof_body(leaf); + info!(?uri, "Contacting"); + let req = Request::builder() + .method("POST") + .uri(uri.to_owned() + "/inclusionProof") + .header("Content-Type", "application/json") + .body(body) + .expect("Failed to create inclusion proof hyper::Body"); + + let mut response = client + .request(req) + .await + .expect("Failed to execute request."); + + let bytes = hyper::body::to_bytes(response.body_mut()) + .await + .expect("Failed to convert response body to bytes"); + let result = String::from_utf8(bytes.into_iter().collect()) + .expect("Could not parse response bytes to utf-8"); + let result_json = serde_json::from_str::(&result) + .expect("Failed to parse response as json"); + let status = result_json["status"] + .as_str() + .expect("Failed to get status"); + + assert_eq!( + expected_status, + Status::from_str(status).expect("Could not convert str to Status") + ); + } +} + +#[instrument(skip_all)] +pub async fn test_delete_identity( + uri: &str, + client: &Client, + ref_tree: &mut PoseidonTree, + test_leaves: &[Field], + leaf_index: usize, + expect_failure: bool, +) -> (merkle_tree::Proof, Field) { + let body = construct_delete_identity_body(&test_leaves[leaf_index]); + + let req = Request::builder() + .method("POST") + .uri(uri.to_owned() + "/deleteIdentity") + .header("Content-Type", "application/json") + .body(body) + .expect("Failed to create insert identity hyper::Body"); + + let mut response = client + .request(req) + .await + .expect("Failed to execute request."); + let bytes = hyper::body::to_bytes(response.body_mut()) + .await + .expect("Failed to convert response body to bytes"); + + if expect_failure { + assert!(!response.status().is_success()); + } else { + assert!(response.status().is_success()); + assert!(bytes.is_empty()); + } + + ref_tree.set(leaf_index, Hash::ZERO); + (ref_tree.proof(leaf_index).unwrap(), ref_tree.root()) +} + +#[instrument(skip_all)] +pub async fn test_recover_identity( + uri: &str, + client: &Client, + ref_tree: &mut PoseidonTree, + test_leaves: &[Field], + previous_leaf_index: usize, + new_leaf: Field, + new_leaf_index: usize, + expect_failure: bool, +) -> (merkle_tree::Proof, Field) { + let previous_leaf = test_leaves[previous_leaf_index]; + + let body = construct_recover_identity_body(&previous_leaf, &new_leaf); + + let req = Request::builder() + .method("POST") + .uri(uri.to_owned() + "/recoverIdentity") + .header("Content-Type", "application/json") + .body(body) + .expect("Failed to create insert identity hyper::Body"); + + let mut response = client + .request(req) + .await + .expect("Failed to execute request."); + + let bytes = hyper::body::to_bytes(response.body_mut()) + .await + .expect("Failed to convert response body to bytes"); + + if expect_failure { + assert!(!response.status().is_success()); + } else { + assert!(response.status().is_success()); + assert!(bytes.is_empty()); + } + + // TODO: Note that recovery order is non-deterministic and therefore we cannot + // easily keep the ref_tree in sync with the sequencer's version of the + // tree. In the future, we could consider tracking updates to the tree in a + // different way like listening to event emission. + ref_tree.set(previous_leaf_index, Hash::ZERO); + // Continuing on the note above, while the replacement identity is be + // inserted as a new identity, it is not deterministic and if there are multiple + // recovery requests, it is possible that the sequencer tree is ordered in a + // different way than the ref_tree + ref_tree.set(new_leaf_index, new_leaf); + (ref_tree.proof(new_leaf_index).unwrap(), ref_tree.root()) +} + #[instrument(skip_all)] pub async fn test_add_batch_size( uri: impl Into, @@ -314,6 +445,28 @@ fn construct_inclusion_proof_body(identity_commitment: &Hash) -> Body { ) } +fn construct_delete_identity_body(identity_commitment: &Hash) -> Body { + Body::from( + json!({ + "identityCommitment": identity_commitment, + }) + .to_string(), + ) +} + +fn construct_recover_identity_body( + prev_identity_commitment: &Hash, + new_identity_commitment: &Hash, +) -> Body { + Body::from( + json!({ + "previousIdentityCommitment":prev_identity_commitment , + "newIdentityCommitment": new_identity_commitment, + }) + .to_string(), + ) +} + fn construct_insert_identity_body(identity_commitment: &Field) -> Body { Body::from( json!({ @@ -378,38 +531,72 @@ struct CompiledContract { pub async fn spawn_deps( initial_root: U256, - batch_sizes: &[usize], + insertion_batch_sizes: &[usize], + deletion_batch_sizes: &[usize], tree_depth: u8, ) -> anyhow::Result<( MockChain, DockerContainerGuard, HashMap, + HashMap, micro_oz::ServerHandle, )> { - let chain = spawn_mock_chain(initial_root, batch_sizes, tree_depth); + let chain = spawn_mock_chain( + initial_root, + insertion_batch_sizes, + deletion_batch_sizes, + tree_depth, + ); + let db_container = spawn_db(); - let prover_futures = FuturesUnordered::new(); - for batch_size in batch_sizes { - prover_futures.push(spawn_mock_prover(*batch_size)); + let insertion_prover_futures = FuturesUnordered::new(); + for batch_size in insertion_batch_sizes { + insertion_prover_futures.push(spawn_mock_insertion_prover(*batch_size, tree_depth)); + } + + let deletion_prover_futures = FuturesUnordered::new(); + for batch_size in deletion_batch_sizes { + deletion_prover_futures.push(spawn_mock_deletion_prover(*batch_size, tree_depth)); } - let (chain, db_container, provers) = - tokio::join!(chain, db_container, prover_futures.collect::>()); + let (chain, db_container, insertion_provers, deletion_provers) = tokio::join!( + chain, + db_container, + insertion_prover_futures.collect::>(), + deletion_prover_futures.collect::>() + ); let chain = chain?; let signing_key = SigningKey::from_bytes(chain.private_key.as_bytes())?; let micro_oz = micro_oz::spawn(chain.anvil.endpoint(), signing_key).await?; - let provers = provers.into_iter().collect::, _>>()?; + let insertion_provers = insertion_provers + .into_iter() + .collect::, _>>()?; - let prover_map = provers + let insertion_prover_map = insertion_provers .into_iter() .map(|prover| (prover.batch_size(), prover)) - .collect(); + .collect::>(); + + let deletion_provers = deletion_provers + .into_iter() + .collect::, _>>()?; - Ok((chain, db_container?, prover_map, micro_oz)) + let deletion_prover_map = deletion_provers + .into_iter() + .map(|prover| (prover.batch_size(), prover)) + .collect::>(); + + Ok(( + chain, + db_container?, + insertion_prover_map, + deletion_prover_map, + micro_oz, + )) } async fn spawn_db() -> anyhow::Result { @@ -418,9 +605,24 @@ async fn spawn_db() -> anyhow::Result { Ok(db_container) } -pub async fn spawn_mock_prover(batch_size: usize) -> anyhow::Result { +pub async fn spawn_mock_insertion_prover( + batch_size: usize, + tree_depth: u8, +) -> anyhow::Result { + let mock_prover_service = + prover_mock::ProverService::new(batch_size, tree_depth, prover_mock::ProverType::Insertion) + .await?; + + Ok(mock_prover_service) +} + +pub async fn spawn_mock_deletion_prover( + batch_size: usize, + tree_depth: u8, +) -> anyhow::Result { let mock_prover_service = - prover_mock::ProverService::new(batch_size, prover_mock::ProverType::Insertion).await?; + prover_mock::ProverService::new(batch_size, tree_depth, prover_mock::ProverType::Deletion) + .await?; Ok(mock_prover_service) } diff --git a/tests/common/prover_mock.rs b/tests/common/prover_mock.rs index f7ab189e..6aaa4fb8 100644 --- a/tests/common/prover_mock.rs +++ b/tests/common/prover_mock.rs @@ -36,7 +36,7 @@ impl Display for ProverError { /// The input to the prover. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -struct ProofInput { +struct InsertionProofInput { input_hash: U256, start_index: u32, pre_root: U256, @@ -45,6 +45,22 @@ struct ProofInput { merkle_proofs: Vec>, } +// TODO: ideally we just import the InsertionProofInput and DeletionProofInput +// from the signup sequencer so that we can know e2e breaks when any interface +// changes occur + +/// The input to the prover. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct DeletionProofInput { + input_hash: U256, + pre_root: U256, + post_root: U256, + packed_deletion_indices: Vec, + identity_commitments: Vec, + merkle_proofs: Vec>, +} + /// The proof response from the prover. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Proof { @@ -119,6 +135,7 @@ impl std::fmt::Display for ProverType { struct Prover { is_available: bool, + tree_depth: u8, } impl ProverService { @@ -128,17 +145,41 @@ impl ProverService { /// It provides only a single endpoint for now, `/prove` in order to match /// the full service (`semaphore-mtb`). This can be extended in the future /// if needed. - pub async fn new(batch_size: usize, prover_type: ProverType) -> anyhow::Result { + pub async fn new( + batch_size: usize, + tree_depth: u8, + prover_type: ProverType, + ) -> anyhow::Result { async fn prove( - State(state): State>>, - Json(input): Json, + state: State>>, + Json(input): Json, ) -> Result, StatusCode> { let state = state.lock().await; - state.prove(input).map(Json) + // Attempt to deserialize into InsertionProofInput + if let Ok(deserialized_insertion_input) = + serde_json::from_value::(input.clone()) + { + return state + .prove_insertion(deserialized_insertion_input) + .map(Json); + } + + // If the above fails, attempt to deserialize into DeletionProofInput + if let Ok(deserialized_deletion_input) = + serde_json::from_value::(input) + { + return state.prove_deletion(deserialized_deletion_input).map(Json); + } + + // If both fail, return an error + Err(StatusCode::BAD_REQUEST) } - let inner = Arc::new(Mutex::new(Prover { is_available: true })); + let inner = Arc::new(Mutex::new(Prover { + is_available: true, + tree_depth, + })); let state = inner.clone(); let app = Router::new().route("/prove", post(prove)).with_state(state); @@ -217,7 +258,7 @@ impl ProverService { } impl Prover { - fn prove(&self, input: ProofInput) -> Result { + fn prove_insertion(&self, input: InsertionProofInput) -> Result { if !self.is_available { return Err(StatusCode::SERVICE_UNAVAILABLE); } @@ -271,6 +312,66 @@ impl Prover { ])) } + fn prove_deletion(&self, input: DeletionProofInput) -> Result { + if !self.is_available { + return Err(StatusCode::SERVICE_UNAVAILABLE); + } + + // Calculate the input hash based on the prover parameters. + let input_hash = Self::compute_deletion_proof_input_hash( + input.packed_deletion_indices.clone(), + input.pre_root, + input.post_root, + ); + + // If the hashes aren't the same something's wrong so we return an error. + if input_hash != input.input_hash { + return Ok(ProveResponse::failure("42", "Input hash mismatch.")); + } + + // Next we verify the merkle proofs. + let empty_leaf = U256::zero(); + let mut last_root = input.pre_root; + + let mut deletion_indices = vec![]; + + for bytes in input.packed_deletion_indices.chunks(4) { + let mut val: [u8; 4] = Default::default(); + val.copy_from_slice(bytes); + deletion_indices.push(u32::from_be_bytes(val)); + } + + for (leaf_index, merkle_proof) in deletion_indices.iter().zip(input.merkle_proofs) { + if *leaf_index == 2u32.pow(self.tree_depth as u32) { + continue; + } + + let proof = + Self::reconstruct_proof_with_directions(*leaf_index as usize, &merkle_proof); + + last_root = proof.root(empty_leaf.into()).into(); + } + + // If the final root doesn't match the post root something's broken so we error. + if last_root != input.post_root { + return Ok(ProveResponse::failure( + "43", + "Merkle proof verification failure.", + )); + } + + Ok(ProveResponse::success([ + "0x2".into(), + input_hash, + "0x2413396a2af3add6fbe8137cfe7657917e31a5cdab0b7d1d645bd5eeb47ba601".into(), + "0x1ad029539528b32ba70964ce43dbf9bba2501cdb3aaa04e4d58982e2f6c34752".into(), + "0x5bb975296032b135458bd49f92d5e9d363367804440d4692708de92e887cf17".into(), + "0x14932600f53a1ceb11d79a7bdd9688a2f8d1919176f257f132587b2b3274c41e".into(), + "0x13d7b19c7b67bf5d3adf2ac2d3885fd5d49435b6069c0656939cd1fb7bef9dc9".into(), + "0x142e14f90c49c79b4edf5f6b7acbcdb0b0f376a4311fc036f1006679bd53ca9e".into(), + ])) + } + /// Reconstructs the proof with directions as required by `semaphore-rs`. /// /// This allows us to utilise the proof verification procedure from that @@ -308,7 +409,7 @@ impl Prover { /// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] /// 32 || 256 || 256 || 256 || 256 || ... || 256 bits /// ``` - fn calculate_identity_registration_input_hash(input: &ProofInput) -> U256 { + fn calculate_identity_registration_input_hash(input: &InsertionProofInput) -> U256 { // Calculate the input hash as described by the prover. let mut hashable_bytes: Vec = vec![]; let mut buffer: [u8; size_of::()] = Default::default(); @@ -325,4 +426,37 @@ impl Prover { keccak256(hashable_bytes).into() } + + /// Calculates the input hash based on the `input` parameters to the prover. + /// + /// We keccak hash all input to save verification gas. Inputs are arranged + /// as follows: + /// ``` + /// PackedDeletionIndices || PreRoot || PostRoot + /// 32 bits * batchSize || 256 || 256 + /// ``` + pub fn compute_deletion_proof_input_hash( + packed_deletion_indices: Vec, + pre_root: U256, + post_root: U256, + ) -> U256 { + // Convert pre_root and post_root to bytes + let mut pre_root_bytes = vec![0u8; 32]; + pre_root.to_big_endian(&mut pre_root_bytes); + + let mut post_root_bytes = vec![0u8; 32]; + post_root.to_big_endian(&mut post_root_bytes); + + let mut bytes = vec![]; + + // Append packed_deletion_indices + bytes.extend_from_slice(&packed_deletion_indices); + + // Append pre_root and post_root bytes + bytes.extend_from_slice(&pre_root_bytes); + bytes.extend_from_slice(&post_root_bytes); + + // Compute and return the Keccak-256 hash + keccak256(bytes).into() + } } diff --git a/tests/delete_identity.rs b/tests/delete_identity.rs new file mode 100644 index 00000000..dbc88b48 --- /dev/null +++ b/tests/delete_identity.rs @@ -0,0 +1,160 @@ +mod common; + +use common::prelude::*; + +use crate::common::test_delete_identity; + +const SUPPORTED_DEPTH: usize = 18; +const IDLE_TIME: u64 = 7; + +#[tokio::test] +#[serial_test::serial] +async fn delete_identities() -> anyhow::Result<()> { + // Initialize logging for the test. + init_tracing_subscriber(); + info!("Starting integration test"); + + let insertion_batch_size: usize = 8; + let deletion_batch_size: usize = 3; + let batch_deletion_timeout_seconds: usize = 10; + + #[allow(clippy::cast_possible_truncation)] + let tree_depth: u8 = SUPPORTED_DEPTH as u8; + + let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); + let initial_root: U256 = ref_tree.root().into(); + + let (mock_chain, db_container, insertion_prover_map, deletion_prover_map, micro_oz) = + spawn_deps( + initial_root, + &[insertion_batch_size], + &[deletion_batch_size], + tree_depth, + ) + .await?; + + let mock_insertion_prover = &insertion_prover_map[&insertion_batch_size]; + let mock_deletion_prover = &deletion_prover_map[&deletion_batch_size]; + + let port = db_container.port(); + let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); + + let mut options = Options::try_parse_from([ + "signup-sequencer", + "--identity-manager-address", + "0x0000000000000000000000000000000000000000", // placeholder, updated below + "--database", + &db_url, + "--database-max-connections", + "1", + "--tree-depth", + &format!("{tree_depth}"), + "--prover-urls", + &format!( + "[{}, {}]", + mock_insertion_prover.arg_string_single(), + mock_deletion_prover.arg_string_single() + ), + "--batch-timeout-seconds", + "10", + "--batch-deletion-timeout-seconds", + &format!("{batch_deletion_timeout_seconds}"), + "--min-batch-deletion-size", + &format!("{deletion_batch_size}"), + "--dense-tree-prefix-depth", + "10", + "--tree-gc-threshold", + "1", + "--oz-api-key", + "", + "--oz-api-secret", + "", + "--oz-api-url", + µ_oz.endpoint(), + "--oz-address", + &format!("{:?}", micro_oz.address()), + ]) + .context("Failed to create options")?; + + options.server.server = Url::parse("http://127.0.0.1:0/").expect("Failed to parse URL"); + + options.app.contracts.identity_manager_address = mock_chain.identity_manager.address(); + options.app.ethereum.ethereum_provider = Url::parse(&mock_chain.anvil.endpoint()).expect( + " + Failed to parse Anvil url", + ); + + let (app, local_addr) = spawn_app(options.clone()) + .await + .expect("Failed to spawn app."); + + let test_identities = generate_test_identities(insertion_batch_size * 3); + let identities_ref: Vec = test_identities + .iter() + .map(|i| Hash::from_str_radix(i, 16).unwrap()) + .collect(); + + let uri = "http://".to_owned() + &local_addr.to_string(); + let client = Client::new(); + + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in 0..insertion_batch_size { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME)).await; + + // Check that we can also get these inclusion proofs back. + for i in 0..insertion_batch_size { + test_inclusion_proof( + &uri, + &client, + i, + &ref_tree, + &Hash::from_str_radix(&test_identities[i], 16) + .expect("Failed to parse Hash from test leaf"), + false, + ) + .await; + } + + // Delete enough identities to trigger a batch + for i in 0..deletion_batch_size { + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, i, false).await; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + + // Ensure that identities have been deleted + for i in 0..deletion_batch_size { + test_inclusion_proof( + &uri, + &client, + i, + &ref_tree, + &Hash::from_str_radix(&test_identities[i], 16) + .expect("Failed to parse Hash from test leaf"), + true, + ) + .await; + } + + // Expect failure when deleting an identity that has already been deleted + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 0, true).await; + + // Expect failure when deleting an identity that can not be found + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 12, true).await; + + // Shutdown the app properly for the final time + shutdown(); + app.await.unwrap(); + for (_, prover) in insertion_prover_map.into_iter() { + prover.stop(); + } + for (_, prover) in deletion_prover_map.into_iter() { + prover.stop(); + } + reset_shutdown(); + + Ok(()) +} diff --git a/tests/delete_padded_identity.rs b/tests/delete_padded_identity.rs new file mode 100644 index 00000000..298b8832 --- /dev/null +++ b/tests/delete_padded_identity.rs @@ -0,0 +1,182 @@ +mod common; + +use common::prelude::*; + +use crate::common::test_delete_identity; + +const SUPPORTED_DEPTH: u8 = 18; +const IDLE_TIME: u64 = 7; + +#[tokio::test] +#[serial_test::serial] +async fn delete_padded_identity() -> anyhow::Result<()> { + // Initialize logging for the test. + init_tracing_subscriber(); + info!("Starting integration test"); + + let insertion_batch_size: usize = 8; + let deletion_batch_size: usize = 3; + let batch_deletion_timeout_seconds: usize = 10; + + #[allow(clippy::cast_possible_truncation)] + let tree_depth: u8 = SUPPORTED_DEPTH; + + let mut ref_tree = PoseidonTree::new((SUPPORTED_DEPTH + 1).into(), ruint::Uint::ZERO); + let initial_root: U256 = ref_tree.root().into(); + + let (mock_chain, db_container, insertion_prover_map, deletion_prover_map, micro_oz) = + spawn_deps( + initial_root, + &[insertion_batch_size], + &[deletion_batch_size], + tree_depth, + ) + .await?; + + let mock_insertion_prover = &insertion_prover_map[&insertion_batch_size]; + let mock_deletion_prover = &deletion_prover_map[&deletion_batch_size]; + + let port = db_container.port(); + let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); + + let mut options = Options::try_parse_from([ + "signup-sequencer", + "--identity-manager-address", + "0x0000000000000000000000000000000000000000", // placeholder, updated below + "--database", + &db_url, + "--database-max-connections", + "1", + "--tree-depth", + &format!("{tree_depth}"), + "--prover-urls", + &format!( + "[{}, {}]", + mock_insertion_prover.arg_string_single(), + mock_deletion_prover.arg_string_single() + ), + "--batch-timeout-seconds", + "10", + "--batch-deletion-timeout-seconds", + &format!("{batch_deletion_timeout_seconds}"), + "--min-batch-deletion-size", + &format!("{deletion_batch_size}"), + "--dense-tree-prefix-depth", + "10", + "--tree-gc-threshold", + "1", + "--oz-api-key", + "", + "--oz-api-secret", + "", + "--oz-api-url", + µ_oz.endpoint(), + "--oz-address", + &format!("{:?}", micro_oz.address()), + ]) + .context("Failed to create options")?; + + options.server.server = Url::parse("http://127.0.0.1:0/").expect("Failed to parse URL"); + + options.app.contracts.identity_manager_address = mock_chain.identity_manager.address(); + options.app.ethereum.ethereum_provider = Url::parse(&mock_chain.anvil.endpoint()).expect( + " + Failed to parse Anvil url", + ); + + let (app, local_addr) = spawn_app(options.clone()) + .await + .expect("Failed to spawn app."); + + let test_identities = generate_test_identities(insertion_batch_size * 3); + let identities_ref: Vec = test_identities + .iter() + .map(|i| Hash::from_str_radix(i, 16).unwrap()) + .collect(); + + let uri = "http://".to_owned() + &local_addr.to_string(); + let client = Client::new(); + + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in 0..insertion_batch_size { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME)).await; + + // Check that we can also get these inclusion proofs back. + for i in 0..insertion_batch_size { + test_inclusion_proof( + &uri, + &client, + i, + &ref_tree, + &Hash::from_str_radix(&test_identities[i], 16) + .expect("Failed to parse Hash from test leaf"), + false, + ) + .await; + } + + // delete only the first and second identities + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 0, false).await; + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 1, false).await; + + tokio::time::sleep(Duration::from_secs( + batch_deletion_timeout_seconds as u64 * 3, + )) + .await; + + // make sure that identity 3 wasn't deleted + test_inclusion_proof( + &uri, + &client, + 2, + &ref_tree, + &Hash::from_str_radix(&test_identities[2], 16) + .expect("Failed to parse Hash from test leaf"), + false, + ) + .await; + + // Ensure that the first and second identities were deleted + test_inclusion_proof( + &uri, + &client, + 0, + &ref_tree, + &Hash::from_str_radix(&test_identities[0], 16) + .expect("Failed to parse Hash from test leaf"), + true, + ) + .await; + test_inclusion_proof( + &uri, + &client, + 1, + &ref_tree, + &Hash::from_str_radix(&test_identities[1], 16) + .expect("Failed to parse Hash from test leaf"), + true, + ) + .await; + + // Expect failure when deleting an identity that has already been deleted + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 0, true).await; + + // Expect failure when deleting an identity that can not be found + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 12, true).await; + + // Shutdown the app properly for the final time + shutdown(); + app.await.unwrap(); + for (_, prover) in insertion_prover_map.into_iter() { + prover.stop(); + } + for (_, prover) in deletion_prover_map.into_iter() { + prover.stop(); + } + reset_shutdown(); + + Ok(()) +} diff --git a/tests/dynamic_batch_sizes.rs b/tests/dynamic_batch_sizes.rs index 43370340..585af42a 100644 --- a/tests/dynamic_batch_sizes.rs +++ b/tests/dynamic_batch_sizes.rs @@ -25,10 +25,10 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); let initial_root: U256 = ref_tree.root().into(); - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size, second_batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -125,7 +125,7 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { .await; // Add a new prover for batch sizes of two. - let second_prover = spawn_mock_prover(second_batch_size).await?; + let second_prover = spawn_mock_insertion_prover(second_batch_size, tree_depth).await?; test_add_batch_size( &uri, @@ -261,7 +261,7 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/insert_identity_and_proofs.rs b/tests/insert_identity_and_proofs.rs index 49feae1b..8ce0b6d5 100644 --- a/tests/insert_identity_and_proofs.rs +++ b/tests/insert_identity_and_proofs.rs @@ -19,10 +19,10 @@ async fn insert_identity_and_proofs() -> anyhow::Result<()> { let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); let initial_root: U256 = ref_tree.root().into(); - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -241,7 +241,7 @@ async fn insert_identity_and_proofs() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/malformed_payload.rs b/tests/malformed_payload.rs index ac07fdb1..2478f3c5 100644 --- a/tests/malformed_payload.rs +++ b/tests/malformed_payload.rs @@ -17,10 +17,10 @@ async fn malformed_payload() -> anyhow::Result<()> { let batch_size: usize = 3; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -95,7 +95,7 @@ async fn malformed_payload() -> anyhow::Result<()> { shutdown(); app.await?; - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/multi_prover.rs b/tests/multi_prover.rs index 19bec43b..61398df3 100644 --- a/tests/multi_prover.rs +++ b/tests/multi_prover.rs @@ -19,11 +19,16 @@ async fn multi_prover() -> anyhow::Result<()> { let batch_size_3: usize = 3; let batch_size_10: usize = 10; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size_3, batch_size_10], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = spawn_deps( + initial_root, + &[batch_size_3, batch_size_10], + &[], + tree_depth, + ) + .await?; - let prover_mock_batch_size_3 = &prover_map[&batch_size_3]; - let prover_mock_batch_size_10 = &prover_map[&batch_size_10]; + let prover_mock_batch_size_3 = &insertion_prover_map[&batch_size_3]; + let prover_mock_batch_size_10 = &insertion_prover_map[&batch_size_10]; let prover_arg_string = format!( "[{},{}]", @@ -130,7 +135,7 @@ async fn multi_prover() -> anyhow::Result<()> { shutdown(); app.await?; - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/recover_identity.rs b/tests/recover_identity.rs new file mode 100644 index 00000000..dee53013 --- /dev/null +++ b/tests/recover_identity.rs @@ -0,0 +1,201 @@ +mod common; + +use common::prelude::*; +use signup_sequencer::identity_tree::Status; + +use crate::common::{test_inclusion_status, test_recover_identity}; +const SUPPORTED_DEPTH: usize = 18; +const IDLE_TIME: u64 = 7; + +#[tokio::test] +#[serial_test::serial] +async fn recover_identities() -> anyhow::Result<()> { + // Initialize logging for the test. + init_tracing_subscriber(); + info!("Starting integration test"); + + let insertion_batch_size: usize = 8; + let deletion_batch_size: usize = 3; + let batch_deletion_timeout_seconds: usize = 10; + + #[allow(clippy::cast_possible_truncation)] + let tree_depth: u8 = SUPPORTED_DEPTH as u8; + + let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); + let initial_root: U256 = ref_tree.root().into(); + + let (mock_chain, db_container, insertion_prover_map, deletion_prover_map, micro_oz) = + spawn_deps( + initial_root, + &[insertion_batch_size], + &[deletion_batch_size], + tree_depth, + ) + .await?; + + // Set the root history expirty to 15 seconds + let updated_root_history_expiry = U256::from(15); + mock_chain + .identity_manager + .method::<_, ()>("setRootHistoryExpiry", updated_root_history_expiry)? + .send() + .await? + .await?; + + let mock_insertion_prover = &insertion_prover_map[&insertion_batch_size]; + let mock_deletion_prover = &deletion_prover_map[&deletion_batch_size]; + + let port = db_container.port(); + let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); + + let mut options = Options::try_parse_from([ + "signup-sequencer", + "--identity-manager-address", + "0x0000000000000000000000000000000000000000", // placeholder, updated below + "--database", + &db_url, + "--database-max-connections", + "1", + "--tree-depth", + &format!("{tree_depth}"), + "--prover-urls", + &format!( + "[{}, {}]", + mock_insertion_prover.arg_string_single(), + mock_deletion_prover.arg_string_single() + ), + "--batch-timeout-seconds", + "10", + "--batch-deletion-timeout-seconds", + &format!("{batch_deletion_timeout_seconds}"), + "--min-batch-deletion-size", + &format!("{deletion_batch_size}"), + "--dense-tree-prefix-depth", + "10", + "--tree-gc-threshold", + "1", + "--oz-api-key", + "", + "--oz-api-secret", + "", + "--oz-api-url", + µ_oz.endpoint(), + "--oz-address", + &format!("{:?}", micro_oz.address()), + ]) + .context("Failed to create options")?; + + options.server.server = Url::parse("http://127.0.0.1:0/").expect("Failed to parse URL"); + + options.app.contracts.identity_manager_address = mock_chain.identity_manager.address(); + options.app.ethereum.ethereum_provider = Url::parse(&mock_chain.anvil.endpoint()).expect( + " + Failed to parse Anvil url", + ); + + let (app, local_addr) = spawn_app(options.clone()) + .await + .expect("Failed to spawn app."); + + let test_identities = generate_test_identities(insertion_batch_size * 3); + let identities_ref: Vec = test_identities + .iter() + .map(|i| Hash::from_str_radix(i, 16).unwrap()) + .collect(); + + let uri = "http://".to_owned() + &local_addr.to_string(); + let client = Client::new(); + + let mut next_leaf_index = 0; + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in 0..insertion_batch_size { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + + next_leaf_index += 1; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME)).await; + // Check that we can also get these inclusion proofs back. + for i in 0..insertion_batch_size { + test_inclusion_proof(&uri, &client, i, &ref_tree, &identities_ref[i], false).await; + } + + // Insert enough recoveries to trigger a batch + for i in 0..deletion_batch_size { + // Delete the identity at i and replace it with an identity at the back of the + // test identities array + // TODO: we should update to a much cleaner approach + let recovery_leaf_index = test_identities.len() - i - 1; + + test_recover_identity( + &uri, + &client, + &mut ref_tree, + &identities_ref, + i, + identities_ref[recovery_leaf_index], + next_leaf_index, + false, + ) + .await; + + next_leaf_index += 1; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + + // Ensure that identities have been deleted + for i in 0..deletion_batch_size { + let recovery_leaf_index = test_identities.len() - i - 1; + + test_inclusion_proof(&uri, &client, i, &ref_tree, &identities_ref[i], true).await; + + // Check that the replacement identity has not been inserted yet + test_inclusion_status( + &uri, + &client, + &identities_ref[recovery_leaf_index], + Status::New, + ) + .await; + } + + // Sleep for root expiry + tokio::time::sleep(Duration::from_secs(updated_root_history_expiry.as_u64())).await; + + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in insertion_batch_size..insertion_batch_size * 2 { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + next_leaf_index += 1; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + + // Check that the replacement identities have been inserted + for i in 0..deletion_batch_size { + let recovery_leaf_index = test_identities.len() - i - 1; + + // Check that the replacement identity has a mined status after an insertion + // batch has completed + test_inclusion_status( + &uri, + &client, + &identities_ref[recovery_leaf_index], + Status::Mined, + ) + .await; + } + + // Shutdown the app properly for the final time + shutdown(); + app.await.unwrap(); + for (_, prover) in insertion_prover_map.into_iter() { + prover.stop(); + } + for (_, prover) in deletion_prover_map.into_iter() { + prover.stop(); + } + reset_shutdown(); + + Ok(()) +} diff --git a/tests/unavailable_prover.rs b/tests/unavailable_prover.rs index f0c38a87..8f8d40f0 100644 --- a/tests/unavailable_prover.rs +++ b/tests/unavailable_prover.rs @@ -16,10 +16,10 @@ async fn unavailable_prover() -> anyhow::Result<()> { let batch_size: usize = 3; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; prover_mock.set_availability(false).await; @@ -96,7 +96,7 @@ async fn unavailable_prover() -> anyhow::Result<()> { shutdown(); app.await?; - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/validate_proofs.rs b/tests/validate_proofs.rs index 02067871..ef40e12f 100644 --- a/tests/validate_proofs.rs +++ b/tests/validate_proofs.rs @@ -19,10 +19,10 @@ async fn validate_proofs() -> anyhow::Result<()> { let tree_depth: u8 = SUPPORTED_DEPTH as u8; let batch_size = 3; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let identity_manager = mock_chain.identity_manager.clone(); @@ -222,7 +222,7 @@ async fn validate_proofs() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); From 652079534bc2a55269a2040b41cc7a1552e5bea4 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 01:21:48 -0400 Subject: [PATCH 17/45] updated existing tables, added new tables for recoveries, deletions --- schemas/database/001_deletions.sql | 3 +++ schemas/database/001_recoveries.sql | 4 ++++ schemas/database/002.init.down.sql | 8 ++++++++ schemas/database/002_init.up.sql | 14 ++++++++++++++ schemas/database/004_unprocessed_identities..sql | 8 ++++++++ 5 files changed, 37 insertions(+) create mode 100644 schemas/database/001_deletions.sql create mode 100644 schemas/database/001_recoveries.sql create mode 100644 schemas/database/002.init.down.sql create mode 100644 schemas/database/002_init.up.sql create mode 100644 schemas/database/004_unprocessed_identities..sql diff --git a/schemas/database/001_deletions.sql b/schemas/database/001_deletions.sql new file mode 100644 index 00000000..1b354d75 --- /dev/null +++ b/schemas/database/001_deletions.sql @@ -0,0 +1,3 @@ +CREATE TABLE deletions ( + leaf_index BIGINT, NOT NULL PRIMARY KEY, +) \ No newline at end of file diff --git a/schemas/database/001_recoveries.sql b/schemas/database/001_recoveries.sql new file mode 100644 index 00000000..2631b5fe --- /dev/null +++ b/schemas/database/001_recoveries.sql @@ -0,0 +1,4 @@ +CREATE TABLE recoveries ( + existing_commitment BYTEA NOT NULL UNIQUE, + new_commitment BYTEA NOT NULL UNIQUE, +) diff --git a/schemas/database/002.init.down.sql b/schemas/database/002.init.down.sql new file mode 100644 index 00000000..9a6dc981 --- /dev/null +++ b/schemas/database/002.init.down.sql @@ -0,0 +1,8 @@ +-- Drop the new primary key constraint +ALTER TABLE identities DROP CONSTRAINT identities_pkey; + +-- Restore the old primary key +ALTER TABLE identities ADD PRIMARY KEY (leaf_index); + +-- Drop the new 'id' column +ALTER TABLE identities DROP COLUMN id; diff --git a/schemas/database/002_init.up.sql b/schemas/database/002_init.up.sql new file mode 100644 index 00000000..b0e627cb --- /dev/null +++ b/schemas/database/002_init.up.sql @@ -0,0 +1,14 @@ +-- Add the new 'id' column +ALTER TABLE identities ADD COLUMN id BIGINT; + +-- Populate the new 'id' column (assuming leaf_index can be used) +UPDATE identities SET id = leaf_index; + +-- Set the new 'id' column as NOT NULL +ALTER TABLE identities ALTER COLUMN id SET NOT NULL; + +-- Drop the existing primary key +ALTER TABLE identities DROP CONSTRAINT identities_pkey; + +-- Set the new 'id' column as the primary key +ALTER TABLE identities ADD PRIMARY KEY (id); \ No newline at end of file diff --git a/schemas/database/004_unprocessed_identities..sql b/schemas/database/004_unprocessed_identities..sql new file mode 100644 index 00000000..355e9812 --- /dev/null +++ b/schemas/database/004_unprocessed_identities..sql @@ -0,0 +1,8 @@ +CREATE TABLE unprocessed_identities ( + commitment BYTEA NOT NULL UNIQUE, + status VARCHAR(50) NOT NULL, + created_at TIMESTAMPTZ NOT NULL, + processed_at TIMESTAMPTZ, + error_message TEXT + eligibility_timestamp TIMESTAMPTZ +) \ No newline at end of file From c9b617725b4f228757778ddb73608cf24ad06d2a Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 13:25:07 -0400 Subject: [PATCH 18/45] updated schemas --- schemas/database/002.init.down.sql | 8 -------- schemas/database/{002_init.up.sql => 004_init.up.sql} | 0 ...sed_identities..sql => 005_unprocessed_identities.sql} | 0 schemas/database/{001_deletions.sql => 006_deletions.sql} | 0 .../database/{001_recoveries.sql => 007_recoveries.sql} | 0 src/database/mod.rs | 8 +++++++- 6 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 schemas/database/002.init.down.sql rename schemas/database/{002_init.up.sql => 004_init.up.sql} (100%) rename schemas/database/{004_unprocessed_identities..sql => 005_unprocessed_identities.sql} (100%) rename schemas/database/{001_deletions.sql => 006_deletions.sql} (100%) rename schemas/database/{001_recoveries.sql => 007_recoveries.sql} (100%) diff --git a/schemas/database/002.init.down.sql b/schemas/database/002.init.down.sql deleted file mode 100644 index 9a6dc981..00000000 --- a/schemas/database/002.init.down.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Drop the new primary key constraint -ALTER TABLE identities DROP CONSTRAINT identities_pkey; - --- Restore the old primary key -ALTER TABLE identities ADD PRIMARY KEY (leaf_index); - --- Drop the new 'id' column -ALTER TABLE identities DROP COLUMN id; diff --git a/schemas/database/002_init.up.sql b/schemas/database/004_init.up.sql similarity index 100% rename from schemas/database/002_init.up.sql rename to schemas/database/004_init.up.sql diff --git a/schemas/database/004_unprocessed_identities..sql b/schemas/database/005_unprocessed_identities.sql similarity index 100% rename from schemas/database/004_unprocessed_identities..sql rename to schemas/database/005_unprocessed_identities.sql diff --git a/schemas/database/001_deletions.sql b/schemas/database/006_deletions.sql similarity index 100% rename from schemas/database/001_deletions.sql rename to schemas/database/006_deletions.sql diff --git a/schemas/database/001_recoveries.sql b/schemas/database/007_recoveries.sql similarity index 100% rename from schemas/database/001_recoveries.sql rename to schemas/database/007_recoveries.sql diff --git a/src/database/mod.rs b/src/database/mod.rs index a3389d35..bfb24ea4 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -610,6 +610,8 @@ mod test { use ethers::types::U256; use postgres_docker_utils::DockerContainerGuard; use semaphore::Field; + use sqlx::types::chrono::DateTime; + use sqlx::{PgPool, Row}; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; @@ -636,9 +638,13 @@ mod test { } async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { + dbg!("here"); + let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); + dbg!(&port); + let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { @@ -1058,7 +1064,7 @@ mod test { } #[tokio::test] - async fn check_identity_existance() -> anyhow::Result<()> { + async fn check_identity_existence() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let identities = mock_identities(2); From 221f718baee7284a9b988e19f0febaa533fac765 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 13:50:41 -0400 Subject: [PATCH 19/45] updated schemas --- .../{004_init.up.sql => 004_identities.up.sql} | 0 ...entities.sql => 005_add_elligibility_timestamp.sql} | 2 +- src/database/mod.rs | 10 +++------- 3 files changed, 4 insertions(+), 8 deletions(-) rename schemas/database/{004_init.up.sql => 004_identities.up.sql} (100%) rename schemas/database/{005_unprocessed_identities.sql => 005_add_elligibility_timestamp.sql} (90%) diff --git a/schemas/database/004_init.up.sql b/schemas/database/004_identities.up.sql similarity index 100% rename from schemas/database/004_init.up.sql rename to schemas/database/004_identities.up.sql diff --git a/schemas/database/005_unprocessed_identities.sql b/schemas/database/005_add_elligibility_timestamp.sql similarity index 90% rename from schemas/database/005_unprocessed_identities.sql rename to schemas/database/005_add_elligibility_timestamp.sql index 355e9812..3a0505af 100644 --- a/schemas/database/005_unprocessed_identities.sql +++ b/schemas/database/005_add_elligibility_timestamp.sql @@ -3,6 +3,6 @@ CREATE TABLE unprocessed_identities ( status VARCHAR(50) NOT NULL, created_at TIMESTAMPTZ NOT NULL, processed_at TIMESTAMPTZ, - error_message TEXT + error_message TEXT, eligibility_timestamp TIMESTAMPTZ ) \ No newline at end of file diff --git a/src/database/mod.rs b/src/database/mod.rs index bfb24ea4..f3c6f167 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -325,7 +325,7 @@ impl Database { .into_iter() .map(|row| TreeUpdate { leaf_index: row.get::(0) as usize, - element: row.get::(1), + element: row.get::(1), }) .collect::>()) } @@ -638,18 +638,14 @@ mod test { } async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { - dbg!("here"); - let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); - dbg!(&port); - let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { - database: SecretUrl::from_str(&url)?, - database_migrate: true, + database: SecretUrl::from_str(&url)?, + database_migrate: true, database_max_connections: 1, }) .await?; From eacb089cf6a4f1a4106bba51b15b5200b9827b9f Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 16:12:18 -0400 Subject: [PATCH 20/45] updated tables, added db functions to insert deletions and recoveries --- schemas/database/004_identities.up.sql | 8 +- .../005_add_elligibility_timestamp.sql | 9 +- schemas/database/006_deletions.sql | 2 +- schemas/database/007_recoveries.sql | 2 +- src/database/mod.rs | 102 ++++++++++++++++++ src/database/types.rs | 13 ++- 6 files changed, 118 insertions(+), 18 deletions(-) diff --git a/schemas/database/004_identities.up.sql b/schemas/database/004_identities.up.sql index b0e627cb..3c824bcf 100644 --- a/schemas/database/004_identities.up.sql +++ b/schemas/database/004_identities.up.sql @@ -1,12 +1,12 @@ -- Add the new 'id' column -ALTER TABLE identities ADD COLUMN id BIGINT; - --- Populate the new 'id' column (assuming leaf_index can be used) -UPDATE identities SET id = leaf_index; +ALTER TABLE identities ADD COLUMN id BIGSERIAL; -- Set the new 'id' column as NOT NULL ALTER TABLE identities ALTER COLUMN id SET NOT NULL; +-- Set the id to be unique +ALTER TABLE identities ADD CONSTRAINT id_unique UNIQUE(id); + -- Drop the existing primary key ALTER TABLE identities DROP CONSTRAINT identities_pkey; diff --git a/schemas/database/005_add_elligibility_timestamp.sql b/schemas/database/005_add_elligibility_timestamp.sql index 3a0505af..7473fe86 100644 --- a/schemas/database/005_add_elligibility_timestamp.sql +++ b/schemas/database/005_add_elligibility_timestamp.sql @@ -1,8 +1 @@ -CREATE TABLE unprocessed_identities ( - commitment BYTEA NOT NULL UNIQUE, - status VARCHAR(50) NOT NULL, - created_at TIMESTAMPTZ NOT NULL, - processed_at TIMESTAMPTZ, - error_message TEXT, - eligibility_timestamp TIMESTAMPTZ -) \ No newline at end of file +ALTER TABLE unprocessed_identities ADD COLUMN eligibility TIMESTAMPTZ; diff --git a/schemas/database/006_deletions.sql b/schemas/database/006_deletions.sql index 1b354d75..7166fb18 100644 --- a/schemas/database/006_deletions.sql +++ b/schemas/database/006_deletions.sql @@ -1,3 +1,3 @@ CREATE TABLE deletions ( - leaf_index BIGINT, NOT NULL PRIMARY KEY, + leaf_index BIGINT NOT NULL PRIMARY KEY ) \ No newline at end of file diff --git a/schemas/database/007_recoveries.sql b/schemas/database/007_recoveries.sql index 2631b5fe..bc731507 100644 --- a/schemas/database/007_recoveries.sql +++ b/schemas/database/007_recoveries.sql @@ -1,4 +1,4 @@ CREATE TABLE recoveries ( existing_commitment BYTEA NOT NULL UNIQUE, - new_commitment BYTEA NOT NULL UNIQUE, + new_commitment BYTEA NOT NULL UNIQUE ) diff --git a/src/database/mod.rs b/src/database/mod.rs index f3c6f167..147e0794 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -15,6 +15,7 @@ use thiserror::Error; use tracing::{error, info, instrument, warn}; use self::prover::ProverConfiguration; +use self::types::RecoveryCommitments; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod prover; @@ -488,6 +489,73 @@ impl Database { Ok(identity) } + pub async fn insert_new_recovery( + &self, + existing_commitment: Hash, + new_commitment: Hash, + ) -> Result<(), Error> { + let query = sqlx::query( + r#" + INSERT INTO recoveries (existing_commitment, new_commitment) + VALUES ($1, $2) + "#, + ) + .bind(existing_commitment) + .bind(new_commitment); + self.pool.execute(query).await?; + Ok(()) + } + + //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + pub async fn get_recoveries(&self) -> Result, Error> { + let query = sqlx::query( + r#" + SELECT * + FROM recoveries + "#, + ); + + let result = self.pool.fetch_all(query).await?; + + Ok(result + .into_iter() + .map(|row| RecoveryCommitments { + existing_commitment: row.get::(0), + new_commitment: row.get::(1), + }) + .collect::>()) + } + + pub async fn insert_new_deletion(&self, leaf_index: i64) -> Result<(), Error> { + let query = sqlx::query( + r#" + INSERT INTO deletions (leaf_index) + VALUES ($1) + "#, + ) + .bind(leaf_index); + + self.pool.execute(query).await?; + Ok(()) + } + + //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + pub async fn get_deletions(&self) -> Result, Error> { + let query = sqlx::query( + r#" + SELECT * + FROM deletions + "#, + ); + + let result = self.pool.fetch_all(query).await?; + + Ok(result + .into_iter() + .map(|row| row.get::(0)) + .collect::>()) + } + pub async fn get_unprocessed_commitments( &self, status: Status, @@ -640,6 +708,7 @@ mod test { async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); + dbg!(&db_container.port()); let url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -703,6 +772,39 @@ mod test { Ok(()) } + #[tokio::test] + async fn insert_deletion() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + db.insert_new_deletion(0).await?; + db.insert_new_deletion(1).await?; + db.insert_new_deletion(2).await?; + db.insert_new_deletion(3).await?; + + let deletions = db.get_deletions().await?; + + assert_eq!(deletions.len(), 4); + + Ok(()) + } + + #[tokio::test] + async fn insert_recovery() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let old_identities = mock_identities(3); + let new_identities = mock_identities(3); + + for (old, new) in old_identities.into_iter().zip(new_identities) { + db.insert_new_recovery(old, new).await?; + } + + let recoveries = db.get_recoveries().await?; + assert_eq!(recoveries.len(), 3); + + Ok(()) + } + #[tokio::test] async fn get_last_leaf_index() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; diff --git a/src/database/types.rs b/src/database/types.rs index c59c2e79..54be0307 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -3,9 +3,14 @@ use chrono::{DateTime, Utc}; use crate::identity_tree::{Hash, Status}; pub struct UnprocessedCommitment { - pub commitment: Hash, - pub status: Status, - pub created_at: DateTime, - pub processed_at: Option>, + pub commitment: Hash, + pub status: Status, + pub created_at: DateTime, + pub processed_at: Option>, pub error_message: Option, } + +pub struct RecoveryCommitments { + pub existing_commitment: Hash, + pub new_commitment: Hash, +} From 64782bba967e587d0ca454bbd0d483f74cb330fb Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 16:43:15 -0400 Subject: [PATCH 21/45] added eligibility_timestamp to UnprocessedCommitment, added method to update eligibility_timestamp --- src/database/mod.rs | 54 ++++++++++++++++++++++++++++++++++++++++++- src/database/types.rs | 1 + 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 147e0794..44b3f102 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,6 +7,7 @@ use std::collections::HashSet; use anyhow::{anyhow, Context, Error as ErrReport}; +use chrono::Utc; use clap::Parser; use sqlx::migrate::{Migrate, MigrateDatabase, Migrator}; use sqlx::pool::PoolOptions; @@ -580,6 +581,8 @@ impl Database { created_at: row.get::<_, _>(2), processed_at: row.get::<_, _>(3), error_message: row.get::<_, _>(4), + + eligibility_timestamp: row.get::<_, _>(5), }) .collect::>()) } @@ -639,6 +642,25 @@ impl Database { Ok(()) } + pub async fn update_eligibility_timestamp( + &self, + commitment: Hash, + eligibility_timestamp: sqlx::types::chrono::DateTime, + ) -> Result<(), Error> { + let query = sqlx::query( + r#" + UPDATE unprocessed_identities SET eligibility = $1 + WHERE commitment = $3 + "#, + ) + .bind(eligibility_timestamp) + .bind(commitment); + + self.pool.execute(query).await?; + + Ok(()) + } + pub async fn identity_exists(&self, commitment: Hash) -> Result { let query_unprocessed_identity = sqlx::query( r#"SELECT exists(SELECT 1 from unprocessed_identities where commitment = $1)"#, @@ -674,7 +696,7 @@ mod test { use std::time::Duration; use anyhow::Context; - use chrono::Utc; + use chrono::{Days, Utc}; use ethers::types::U256; use postgres_docker_utils::DockerContainerGuard; use semaphore::Field; @@ -772,6 +794,36 @@ mod test { Ok(()) } + #[tokio::test] + async fn test_update_eligibility_timestamp() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let dec = "1234500000000000000"; + let commit_hash: Hash = U256::from_dec_str(dec) + .expect("cant convert to u256") + .into(); + + db.insert_new_identity(commit_hash).await?; + + let eligibility_timestamp = DateTime::from(Utc::now()) + .checked_add_days(Days::new(7)) + .expect("Could not create eligibility timestamp"); + + db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) + .await?; + + let commitments = db.get_unprocessed_commitments(Status::Pending).await?; + assert_eq!(commitments.len(), 1); + + assert_eq!( + commitments[0] + .eligibility_timestamp + .expect("Could not get eligibility_timestamp from commitment"), + eligibility_timestamp + ); + + Ok(()) + } + #[tokio::test] async fn insert_deletion() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; diff --git a/src/database/types.rs b/src/database/types.rs index 54be0307..40cc6de5 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -8,6 +8,7 @@ pub struct UnprocessedCommitment { pub created_at: DateTime, pub processed_at: Option>, pub error_message: Option, + pub eligibility_timestamp: Option>, } pub struct RecoveryCommitments { From f76a16165f278e29cf9c7296d1212158f28d9251 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 16:43:34 -0400 Subject: [PATCH 22/45] chore: remove dbg --- src/database/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 44b3f102..e169a81a 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -730,8 +730,6 @@ mod test { async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); - dbg!(&db_container.port()); - let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { From 2eb9f15e8ac3dad072446fc0259b151ac0149a1a Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 17:32:16 -0400 Subject: [PATCH 23/45] updated deletions table, added type to represent deletion and recovery entries --- schemas/database/006_deletions.sql | 3 ++- src/database/mod.rs | 35 +++++++++++++++++------------- src/database/types.rs | 7 +++++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/schemas/database/006_deletions.sql b/schemas/database/006_deletions.sql index 7166fb18..9aa00e06 100644 --- a/schemas/database/006_deletions.sql +++ b/schemas/database/006_deletions.sql @@ -1,3 +1,4 @@ CREATE TABLE deletions ( - leaf_index BIGINT NOT NULL PRIMARY KEY + leaf_index BIGINT NOT NULL PRIMARY KEY + commitment BYTEA NOT NULL UNIQUE, ) \ No newline at end of file diff --git a/src/database/mod.rs b/src/database/mod.rs index e169a81a..e31d7aa9 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -16,7 +16,7 @@ use thiserror::Error; use tracing::{error, info, instrument, warn}; use self::prover::ProverConfiguration; -use self::types::RecoveryCommitments; +use self::types::{DeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod prover; @@ -508,7 +508,7 @@ impl Database { } //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 - pub async fn get_recoveries(&self) -> Result, Error> { + pub async fn get_recoveries(&self) -> Result, Error> { let query = sqlx::query( r#" SELECT * @@ -520,28 +520,29 @@ impl Database { Ok(result .into_iter() - .map(|row| RecoveryCommitments { + .map(|row| RecoveryEntry { existing_commitment: row.get::(0), new_commitment: row.get::(1), }) - .collect::>()) + .collect::>()) } - pub async fn insert_new_deletion(&self, leaf_index: i64) -> Result<(), Error> { + pub async fn insert_new_deletion(&self, leaf_index: i64, identity: &Hash) -> Result<(), Error> { let query = sqlx::query( r#" - INSERT INTO deletions (leaf_index) - VALUES ($1) + INSERT INTO deletions (leaf_index, commitment) + VALUES ($1, $2) "#, ) - .bind(leaf_index); + .bind(leaf_index) + .bind(identity); self.pool.execute(query).await?; Ok(()) } //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 - pub async fn get_deletions(&self) -> Result, Error> { + pub async fn get_deletions(&self) -> Result, Error> { let query = sqlx::query( r#" SELECT * @@ -553,8 +554,11 @@ impl Database { Ok(result .into_iter() - .map(|row| row.get::(0)) - .collect::>()) + .map(|row| DeletionEntry { + leaf_index: row.get::(0), + commitment: row.get::(1), + }) + .collect::>()) } pub async fn get_unprocessed_commitments( @@ -825,11 +829,12 @@ mod test { #[tokio::test] async fn insert_deletion() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; + let identities = mock_identities(3); - db.insert_new_deletion(0).await?; - db.insert_new_deletion(1).await?; - db.insert_new_deletion(2).await?; - db.insert_new_deletion(3).await?; + db.insert_new_deletion(0, &identities[0]).await?; + db.insert_new_deletion(1, &identities[1]).await?; + db.insert_new_deletion(2, &identities[2]).await?; + db.insert_new_deletion(3, &identities[3]).await?; let deletions = db.get_deletions().await?; diff --git a/src/database/types.rs b/src/database/types.rs index 40cc6de5..6ba69505 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -11,7 +11,12 @@ pub struct UnprocessedCommitment { pub eligibility_timestamp: Option>, } -pub struct RecoveryCommitments { +pub struct RecoveryEntry { pub existing_commitment: Hash, pub new_commitment: Hash, } + +pub struct DeletionEntry { + pub leaf_index: i64, //TODO: consider using a larger type for leaf indices + pub commitment: Hash, +} From cdb88f83406e84d2fd947a9eb5a5b6a3fdbc20d6 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 17:59:27 -0400 Subject: [PATCH 24/45] updated deletion table, updated insert deletion test --- ...y_timestamp.sql => 005_add_eligibility_timestamp.sql} | 0 schemas/database/006_deletions.sql | 4 ++-- src/database/mod.rs | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) rename schemas/database/{005_add_elligibility_timestamp.sql => 005_add_eligibility_timestamp.sql} (100%) diff --git a/schemas/database/005_add_elligibility_timestamp.sql b/schemas/database/005_add_eligibility_timestamp.sql similarity index 100% rename from schemas/database/005_add_elligibility_timestamp.sql rename to schemas/database/005_add_eligibility_timestamp.sql diff --git a/schemas/database/006_deletions.sql b/schemas/database/006_deletions.sql index 9aa00e06..c5ec8ef6 100644 --- a/schemas/database/006_deletions.sql +++ b/schemas/database/006_deletions.sql @@ -1,4 +1,4 @@ CREATE TABLE deletions ( - leaf_index BIGINT NOT NULL PRIMARY KEY - commitment BYTEA NOT NULL UNIQUE, + leaf_index BIGINT NOT NULL PRIMARY KEY, + commitment BYTEA NOT NULL UNIQUE ) \ No newline at end of file diff --git a/src/database/mod.rs b/src/database/mod.rs index e31d7aa9..bce28975 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -654,7 +654,7 @@ impl Database { let query = sqlx::query( r#" UPDATE unprocessed_identities SET eligibility = $1 - WHERE commitment = $3 + WHERE commitment = $2 "#, ) .bind(eligibility_timestamp) @@ -827,24 +827,23 @@ mod test { } #[tokio::test] - async fn insert_deletion() -> anyhow::Result<()> { + async fn test_insert_deletion() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let identities = mock_identities(3); db.insert_new_deletion(0, &identities[0]).await?; db.insert_new_deletion(1, &identities[1]).await?; db.insert_new_deletion(2, &identities[2]).await?; - db.insert_new_deletion(3, &identities[3]).await?; let deletions = db.get_deletions().await?; - assert_eq!(deletions.len(), 4); + assert_eq!(deletions.len(), 3); Ok(()) } #[tokio::test] - async fn insert_recovery() -> anyhow::Result<()> { + async fn test_insert_recovery() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let old_identities = mock_identities(3); From eaef3ae09f94ca1e1717bb0c9714d0bf0d668a83 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 28 Aug 2023 18:02:57 -0400 Subject: [PATCH 25/45] updated get_unprocessed_commitments to only get entries that are eligible --- src/database/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index bce28975..e3bf3ff1 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -568,7 +568,7 @@ impl Database { let query = sqlx::query( r#" SELECT * FROM unprocessed_identities - WHERE status = $1 + WHERE status = $1 AND CURRENT_TIMESTAMP > eligibility LIMIT $2 "#, ) From 6771ceb0965efe1082c46dee7a4a2c8f77b54bc0 Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:58:07 -0400 Subject: [PATCH 26/45] Feat: Deletion/Recovery API Updates (#586) * added deletion and recovery endpoints, added app functions for deletion * added deletion prover map * added prover_type to separate deletion and insertion provers * added prover_type during batch size removal * moved custom middleware * updated prover table migration * patching tests, added get_eligible_unprocessed_commitments * patched test_update_eligibility_timestamp * patched dynamic_batch_sizes * chore: cargo fmt * updated delete_identity to check if id has already been deleted or queued for deletion * updated recover_identity to delete existing commitment, and insert data in to recoveries table * removed unused function * added new tests for new database/identity manager logic * added new tests * fix: imported IdentityManager into test mod * updated IdentityManager tests * updated database tests * patched test_remove_prover * separated generate_proof into generate_insertion_proof and generate_deletion_proof * patched test_insert_provers * updated provers db schema, updated insert_prover_configuration test * removed commented out tests, will reimplement * removed todo --- schemas/database/008_prover_type.sql | 28 + src/app.rs | 155 ++++- src/contracts/mod.rs | 50 +- src/database/mod.rs | 367 ++++++++-- src/database/prover.rs | 25 - src/database/types.rs | 16 +- src/identity_tree.rs | 12 + src/prover/{batch_insertion => }/identity.rs | 0 src/prover/map.rs | 50 +- src/prover/mod.rs | 634 +++++++++++++++++- .../mod.rs} | 0 src/server/error.rs | 6 + src/server/mod.rs | 57 +- src/task_monitor/tasks/process_identities.rs | 4 +- tests/common/mod.rs | 13 +- tests/common/prover_mock.rs | 42 +- tests/dynamic_batch_sizes.rs | 34 +- 17 files changed, 1332 insertions(+), 161 deletions(-) create mode 100644 schemas/database/008_prover_type.sql delete mode 100644 src/database/prover.rs rename src/prover/{batch_insertion => }/identity.rs (100%) rename src/server/{custom_middleware.rs => custom_middleware/mod.rs} (100%) diff --git a/schemas/database/008_prover_type.sql b/schemas/database/008_prover_type.sql new file mode 100644 index 00000000..651c9ce0 --- /dev/null +++ b/schemas/database/008_prover_type.sql @@ -0,0 +1,28 @@ +-- Create ENUM for prover type +CREATE TYPE prover_enum AS ENUM('Insertion', 'Deletion'); + +-- Add new column with the enum +ALTER TABLE provers ADD COLUMN prover_type prover_enum; + +-- Update the new column, setting all existing provers as insertions +UPDATE provers SET prover_type = 'Insertion' WHERE prover_type IS NULL; + +-- Make the column NOT NULL +ALTER TABLE provers ALTER COLUMN prover_type SET NOT NULL; + +-- Drop batch size as the primary key +ALTER TABLE provers DROP CONSTRAINT provers_pkey; + +-- Drop the url uniqueness constraint +ALTER TABLE provers DROP CONSTRAINT IF EXISTS provers_url_key; + + + + + + + + + + + diff --git a/src/app.rs b/src/app.rs index c8fea0e4..35f5ece3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,24 +3,23 @@ use std::sync::Arc; use std::time::Instant; use anyhow::Result as AnyhowResult; -use chrono::Duration; +use chrono::{DateTime, Duration, Utc}; use clap::Parser; use hyper::StatusCode; +use ruint::Uint; use semaphore::poseidon_tree::LazyPoseidonTree; use semaphore::protocol::verify_proof; use serde::Serialize; use tracing::{info, instrument, warn}; use crate::contracts::{IdentityManager, SharedIdentityManager}; -use crate::database::prover::{ProverConfiguration as DbProverConf, Provers}; use crate::database::{self, Database}; use crate::ethereum::{self, Ethereum}; use crate::identity_tree::{ CanonicalTreeBuilder, Hash, InclusionProof, RootItem, Status, TreeState, TreeVersionReadOps, }; -use crate::prover::batch_insertion::ProverConfiguration; -use crate::prover::map::make_insertion_map; -use crate::prover::{self, batch_insertion}; +use crate::prover::map::initialize_prover_maps; +use crate::prover::{self, ProverConfiguration, ProverType, Provers}; use crate::server::error::Error as ServerError; use crate::server::{ToResponseCode, VerifySemaphoreProofQuery, VerifySemaphoreProofRequest}; use crate::task_monitor::TaskMonitor; @@ -111,7 +110,7 @@ pub struct Options { pub database: database::Options, #[clap(flatten)] - pub batch_provers: prover::batch_insertion::Options, + pub batch_provers: prover::Options, #[clap(flatten)] pub committer: task_monitor::Options, @@ -154,14 +153,22 @@ impl App { let (ethereum, db) = tokio::try_join!(ethereum, db)?; let database = Arc::new(db); - let mut provers = database.get_provers().await?; + let mut provers: HashSet = database.get_provers().await?; + + // TODO: need to update this let non_inserted_provers = Self::merge_env_provers(options.batch_provers, &mut provers); database.insert_provers(non_inserted_provers).await?; - let insertion_prover_map = make_insertion_map(provers)?; - let identity_manager = - IdentityManager::new(options.contracts, ethereum.clone(), insertion_prover_map).await?; + let (insertion_prover_map, deletion_prover_map) = initialize_prover_maps(provers)?; + + let identity_manager = IdentityManager::new( + options.contracts, + ethereum.clone(), + insertion_prover_map, + deletion_prover_map, + ) + .await?; let identity_manager = Arc::new(identity_manager); @@ -297,10 +304,11 @@ impl App { return Err(ServerError::InvalidCommitment); } - if !self.identity_manager.has_provers().await { + if !self.identity_manager.has_insertion_provers().await { warn!( ?commitment, - "Identity Manager has no provers. Add provers with /addBatchSize request." + "Identity Manager has no insertion provers. Add provers with /addBatchSize \ + request." ); return Err(ServerError::NoProversOnIdInsert); } @@ -318,23 +326,109 @@ impl App { return Err(ServerError::DuplicateCommitment); } - self.database.insert_new_identity(commitment).await?; + self.database + .insert_new_identity(commitment, DateTime::from(Utc::now())) + .await?; Ok(()) } - fn merge_env_provers( - options: batch_insertion::Options, - existing_provers: &mut Provers, - ) -> Provers { - let options_set: HashSet = options + /// Queues a deletion from the merkle tree. + /// + /// # Errors + /// + /// Will return `Err` if identity is already queued, not in the tree, or the + /// queue malfunctions. + #[instrument(level = "debug", skip(self))] + pub async fn delete_identity(&self, commitment: &Hash) -> Result<(), ServerError> { + // Ensure that deletion provers exist + if !self.identity_manager.has_deletion_provers().await { + warn!( + ?commitment, + "Identity Manager has no deletion provers. Add provers with /addBatchSize request." + ); + return Err(ServerError::NoProversOnIdDeletion); + } + + // Get the leaf index for the id commitment + let leaf_index = self + .database + .get_identity_leaf_index(&commitment) + .await? + .ok_or(ServerError::IdentityCommitmentNotFound)? + .leaf_index; + + // Check if the id has already been deleted + if self.tree_state.get_latest_tree().get_leaf(leaf_index) == Uint::ZERO { + return Err(ServerError::IdentityAlreadyDeleted); + } + + // Check if the id is already queued for deletion + if self + .database + .identity_is_queued_for_deletion(commitment) + .await? + { + return Err(ServerError::IdentityQueuedForDeletion); + } + + // If the id has not been deleted, insert into the deletions table + self.database + .insert_new_deletion(leaf_index, &commitment) + .await?; + + Ok(()) + } + + /// Queues a deletion from the merkle tree. + /// + /// # Errors + /// + /// Will return `Err` if identity is already queued, not in the tree, or the + /// queue malfunctions. + #[instrument(level = "debug", skip(self))] + pub async fn recover_identity( + &self, + existing_commitment: &Hash, + new_commitment: &Hash, + ) -> Result<(), ServerError> { + // Ensure that insertion provers exist + if !self.identity_manager.has_insertion_provers().await { + warn!( + ?new_commitment, + "Identity Manager has no provers. Add provers with /addBatchSize request." + ); + return Err(ServerError::NoProversOnIdInsert); + } + + // Ensure that deletion provers exist + if !self.identity_manager.has_deletion_provers().await { + warn!( + ?new_commitment, + "Identity Manager has no deletion provers. Add provers with /addBatchSize request." + ); + return Err(ServerError::NoProversOnIdDeletion); + } + + // Delete the existing id and insert the commitments into the recovery table + self.delete_identity(&existing_commitment).await?; + self.database + .insert_new_recovery(&existing_commitment, &new_commitment) + .await?; + + Ok(()) + } + + fn merge_env_provers(options: prover::Options, existing_provers: &mut Provers) -> Provers { + let options_set: HashSet = options .prover_urls .0 .into_iter() - .map(|opt| DbProverConf { - url: opt.url, - batch_size: opt.batch_size, - timeout_s: opt.timeout_s, + .map(|opt| ProverConfiguration { + url: opt.url, + batch_size: opt.batch_size, + timeout_s: opt.timeout_s, + prover_type: opt.prover_type, }) .collect(); @@ -361,13 +455,14 @@ impl App { url: String, batch_size: usize, timeout_seconds: u64, + prover_type: ProverType, ) -> Result<(), ServerError> { self.identity_manager - .add_batch_size(&url, batch_size, timeout_seconds) + .add_batch_size(&url, batch_size, timeout_seconds, prover_type) .await?; self.database - .insert_prover_configuration(batch_size, url, timeout_seconds) + .insert_prover_configuration(batch_size, url, timeout_seconds, prover_type) .await?; Ok(()) @@ -378,10 +473,16 @@ impl App { /// Will return `Err` if the requested batch size does not exist. /// Will return `Err` if batch size fails to be removed from database. #[instrument(level = "debug", skip(self))] - pub async fn remove_batch_size(&self, batch_size: usize) -> Result<(), ServerError> { - self.identity_manager.remove_batch_size(batch_size).await?; + pub async fn remove_batch_size( + &self, + batch_size: usize, + prover_type: ProverType, + ) -> Result<(), ServerError> { + self.identity_manager + .remove_batch_size(batch_size, prover_type) + .await?; - self.database.remove_prover(batch_size).await?; + self.database.remove_prover(batch_size, prover_type).await?; Ok(()) } diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 044c5f1f..6a5aae08 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -16,9 +16,9 @@ use tracing::{error, info, instrument, warn}; use self::abi::{BridgedWorldId, WorldId}; use crate::ethereum::write::TransactionId; use crate::ethereum::{Ethereum, ReadProvider}; -use crate::prover::batch_insertion::ProverConfiguration; -use crate::prover::map::{InsertionProverMap, ReadOnlyInsertionProver}; -use crate::prover::{batch_insertion, Proof, ReadOnlyProver}; +use crate::prover::identity::Identity; +use crate::prover::map::{DeletionProverMap, InsertionProverMap, ReadOnlyInsertionProver}; +use crate::prover::{Proof, Prover, ProverConfiguration, ProverType, ReadOnlyProver}; use crate::serde_utils::JsonStrWrapper; use crate::server::error::Error as ServerError; @@ -58,6 +58,7 @@ pub struct Options { pub struct IdentityManager { ethereum: Ethereum, insertion_prover_map: InsertionProverMap, + deletion_prover_map: DeletionProverMap, abi: WorldId, secondary_abis: Vec>, initial_leaf_value: Field, @@ -79,6 +80,7 @@ impl IdentityManager { options: Options, ethereum: Ethereum, insertion_prover_map: InsertionProverMap, + deletion_prover_map: DeletionProverMap, ) -> anyhow::Result where Self: Sized, @@ -128,6 +130,7 @@ impl IdentityManager { let identity_manager = Self { ethereum, insertion_prover_map, + deletion_prover_map, abi, secondary_abis, initial_leaf_value, @@ -153,10 +156,7 @@ impl IdentityManager { /// Validates that merkle proofs are of the correct length against tree /// depth - pub fn validate_merkle_proofs( - &self, - identity_commitments: &[batch_insertion::Identity], - ) -> anyhow::Result<()> { + pub fn validate_merkle_proofs(&self, identity_commitments: &[Identity]) -> anyhow::Result<()> { for id in identity_commitments { if id.merkle_proof.len() != self.tree_depth { return Err(anyhow!(format!( @@ -173,7 +173,7 @@ impl IdentityManager { pub async fn get_suitable_prover( &self, num_identities: usize, - ) -> anyhow::Result> { + ) -> anyhow::Result> { let prover_map = self.insertion_prover_map.read().await; match RwLockReadGuard::try_map(prover_map, |map| map.get(num_identities)) { @@ -185,12 +185,12 @@ impl IdentityManager { } #[instrument(level = "debug", skip(prover, identity_commitments))] - pub async fn prepare_proof( + pub async fn prepare_insertion_proof( prover: ReadOnlyInsertionProver<'_>, start_index: usize, pre_root: U256, post_root: U256, - identity_commitments: &[batch_insertion::Identity], + identity_commitments: &[Identity], ) -> anyhow::Result { let batch_size = identity_commitments.len(); @@ -203,7 +203,7 @@ impl IdentityManager { ); let proof_data: Proof = prover - .generate_proof( + .generate_insertion_proof( actual_start_index, pre_root, post_root, @@ -220,7 +220,7 @@ impl IdentityManager { start_index: usize, pre_root: U256, post_root: U256, - identity_commitments: Vec, + identity_commitments: Vec, proof_data: Proof, ) -> anyhow::Result { let actual_start_index: u32 = start_index.try_into()?; @@ -319,16 +319,21 @@ impl IdentityManager { url: &impl ToString, batch_size: usize, timeout_seconds: u64, + prover_type: ProverType, ) -> Result<(), ServerError> { - let mut map = self.insertion_prover_map.write().await; + let mut map = match prover_type { + ProverType::Insertion => self.insertion_prover_map.write().await, + ProverType::Deletion => self.deletion_prover_map.write().await, + }; if map.batch_size_exists(batch_size) { return Err(ServerError::BatchSizeAlreadyExists); } - let prover = batch_insertion::Prover::new(&ProverConfiguration { + let prover = Prover::new(&ProverConfiguration { url: url.to_string(), batch_size, + prover_type, timeout_s: timeout_seconds, })?; @@ -341,8 +346,15 @@ impl IdentityManager { /// /// Will return `Err` if the batch size requested for removal doesn't exist /// in the prover map. - pub async fn remove_batch_size(&self, batch_size: usize) -> Result<(), ServerError> { - let mut map = self.insertion_prover_map.write().await; + pub async fn remove_batch_size( + &self, + batch_size: usize, + prover_type: ProverType, + ) -> Result<(), ServerError> { + let mut map = match prover_type { + ProverType::Insertion => self.insertion_prover_map.write().await, + ProverType::Deletion => self.deletion_prover_map.write().await, + }; if map.len() == 1 { warn!("Attempting to remove the last batch size."); @@ -363,9 +375,13 @@ impl IdentityManager { .as_configuration_vec()) } - pub async fn has_provers(&self) -> bool { + pub async fn has_insertion_provers(&self) -> bool { self.insertion_prover_map.read().await.len() > 0 } + + pub async fn has_deletion_provers(&self) -> bool { + self.deletion_prover_map.read().await.len() > 0 + } } /// A type for an identity manager object that can be sent across threads. diff --git a/src/database/mod.rs b/src/database/mod.rs index e3bf3ff1..67a2f0a8 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -15,12 +15,11 @@ use sqlx::{Executor, Pool, Postgres, Row}; use thiserror::Error; use tracing::{error, info, instrument, warn}; -use self::prover::ProverConfiguration; use self::types::{DeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; -pub mod prover; pub mod types; +use crate::prover::{self, ProverConfiguration, ProverType, Provers}; use crate::secret::SecretUrl; // Statically link in migration files @@ -327,7 +326,7 @@ impl Database { .into_iter() .map(|row| TreeUpdate { leaf_index: row.get::(0) as usize, - element: row.get::(1), + element: row.get::(1), }) .collect::>()) } @@ -391,10 +390,10 @@ impl Database { Ok(result.get::(0) as i32) } - pub async fn get_provers(&self) -> Result { + pub async fn get_provers(&self) -> Result { let query = sqlx::query( r#" - SELECT batch_size, url, timeout_s + SELECT batch_size, url, timeout_s, prover_type FROM provers "#, ); @@ -407,13 +406,15 @@ impl Database { let batch_size = row.get::(0) as usize; let url = row.get::(1); let timeout_s = row.get::(2) as u64; - prover::ProverConfiguration { + let prover_type = row.get::(3); + ProverConfiguration { url, batch_size, timeout_s, + prover_type, } }) - .collect::()) + .collect::()) } pub async fn insert_prover_configuration( @@ -421,20 +422,20 @@ impl Database { batch_size: usize, url: impl ToString, timeout_seconds: u64, + prover_type: ProverType, ) -> Result<(), Error> { let url = url.to_string(); let query = sqlx::query( r#" - INSERT INTO provers (batch_size, url, timeout_s) - VALUES ($1, $2, $3) - ON CONFLICT (batch_size) - DO UPDATE SET (url, timeout_s) = ($2, $3) + INSERT INTO provers (batch_size, url, timeout_s, prover_type) + VALUES ($1, $2, $3, $4) "#, ) .bind(batch_size as i64) .bind(url) - .bind(timeout_seconds as i64); + .bind(timeout_seconds as i64) + .bind(prover_type); self.pool.execute(query).await?; @@ -448,14 +449,15 @@ impl Database { let mut query_builder = sqlx::QueryBuilder::new( r#" - INSERT INTO provers (batch_size, url, timeout_s) + INSERT INTO provers (batch_size, url, timeout_s, prover_type) "#, ); query_builder.push_values(provers, |mut b, prover| { b.push_bind(prover.batch_size as i64) .push_bind(prover.url) - .push_bind(prover.timeout_s as i64); + .push_bind(prover.timeout_s as i64) + .push_bind(prover.prover_type); }); let query = query_builder.build(); @@ -464,36 +466,47 @@ impl Database { Ok(()) } - pub async fn remove_prover(&self, batch_size: usize) -> Result<(), Error> { + pub async fn remove_prover( + &self, + batch_size: usize, + prover_type: ProverType, + ) -> Result<(), Error> { let query = sqlx::query( r#" - DELETE FROM provers WHERE batch_size = $1 + DELETE FROM provers WHERE batch_size = $1 AND prover_type = $2 "#, ) - .bind(batch_size as i64); + .bind(batch_size as i64) + .bind(prover_type); self.pool.execute(query).await?; Ok(()) } - pub async fn insert_new_identity(&self, identity: Hash) -> Result { + pub async fn insert_new_identity( + &self, + identity: Hash, + eligibility_timestamp: sqlx::types::chrono::DateTime, + ) -> Result { let query = sqlx::query( r#" - INSERT INTO unprocessed_identities (commitment, status, created_at) - VALUES ($1, $2, CURRENT_TIMESTAMP) + INSERT INTO unprocessed_identities (commitment, status, created_at, eligibility) + VALUES ($1, $2, CURRENT_TIMESTAMP, $3) "#, ) .bind(identity) - .bind(<&str>::from(Status::New)); + .bind(<&str>::from(Status::New)) + .bind(eligibility_timestamp); + self.pool.execute(query).await?; Ok(identity) } pub async fn insert_new_recovery( &self, - existing_commitment: Hash, - new_commitment: Hash, + existing_commitment: &Hash, + new_commitment: &Hash, ) -> Result<(), Error> { let query = sqlx::query( r#" @@ -507,7 +520,8 @@ impl Database { Ok(()) } - //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + // TODO: consider using a larger value than i64 for leaf index, ruint should + // have postgres compatibility for u256 pub async fn get_recoveries(&self) -> Result, Error> { let query = sqlx::query( r#" @@ -522,26 +536,31 @@ impl Database { .into_iter() .map(|row| RecoveryEntry { existing_commitment: row.get::(0), - new_commitment: row.get::(1), + new_commitment: row.get::(1), }) .collect::>()) } - pub async fn insert_new_deletion(&self, leaf_index: i64, identity: &Hash) -> Result<(), Error> { + pub async fn insert_new_deletion( + &self, + leaf_index: usize, + identity: &Hash, + ) -> Result<(), Error> { let query = sqlx::query( r#" INSERT INTO deletions (leaf_index, commitment) VALUES ($1, $2) "#, ) - .bind(leaf_index) + .bind(leaf_index as i64) .bind(identity); self.pool.execute(query).await?; Ok(()) } - //TODO: consider using a larger value than i64 for leaf index, ruint should have postgres compatibility for u256 + // TODO: consider using a larger value than i64 for leaf index, ruint should + // have postgres compatibility for u256 pub async fn get_deletions(&self) -> Result, Error> { let query = sqlx::query( r#" @@ -561,7 +580,7 @@ impl Database { .collect::>()) } - pub async fn get_unprocessed_commitments( + pub async fn get_eligible_unprocessed_commitments( &self, status: Status, ) -> Result, Error> { @@ -577,6 +596,35 @@ impl Database { let result = self.pool.fetch_all(query).await?; + Ok(result + .into_iter() + .map(|row| types::UnprocessedCommitment { + commitment: row.get::(0), + status, + created_at: row.get::<_, _>(2), + processed_at: row.get::<_, _>(3), + error_message: row.get::<_, _>(4), + eligibility_timestamp: row.get::<_, _>(5), + }) + .collect::>()) + } + + pub async fn get_unprocessed_commitments( + &self, + status: Status, + ) -> Result, Error> { + let query = sqlx::query( + r#" + SELECT * FROM unprocessed_identities + WHERE status = $1 + LIMIT $2 + "#, + ) + .bind(<&str>::from(status)) + .bind(MAX_UNPROCESSED_FETCH_COUNT); + + let result = self.pool.fetch_all(query).await?; + Ok(result .into_iter() .map(|row| types::UnprocessedCommitment { @@ -646,6 +694,7 @@ impl Database { Ok(()) } + // TODO: add docs pub async fn update_eligibility_timestamp( &self, commitment: Hash, @@ -667,14 +716,14 @@ impl Database { pub async fn identity_exists(&self, commitment: Hash) -> Result { let query_unprocessed_identity = sqlx::query( - r#"SELECT exists(SELECT 1 from unprocessed_identities where commitment = $1)"#, + r#"SELECT exists(SELECT 1 FROM unprocessed_identities where commitment = $1)"#, ) .bind(commitment); let row_unprocessed = self.pool.fetch_one(query_unprocessed_identity).await?; let query_processed_identity = - sqlx::query(r#"SELECT exists(SELECT 1 from identities where commitment = $1)"#) + sqlx::query(r#"SELECT exists(SELECT 1 FROM identities where commitment = $1)"#) .bind(commitment); let row_processed = self.pool.fetch_one(query_processed_identity).await?; @@ -683,6 +732,15 @@ impl Database { Ok(exists) } + + // TODO: add docs + pub async fn identity_is_queued_for_deletion(&self, commitment: &Hash) -> Result { + let query_queued_deletion = + sqlx::query(r#"SELECT exists(SELECT 1 FROM deletions where commitment = $1)"#) + .bind(commitment); + let row_unprocessed = self.pool.fetch_one(query_queued_deletion).await?; + Ok(row_unprocessed.get::(0)) + } } #[derive(Debug, Error)] @@ -696,6 +754,7 @@ pub enum Error { #[cfg(test)] mod test { + use std::collections::HashSet; use std::str::FromStr; use std::time::Duration; @@ -703,12 +762,14 @@ mod test { use chrono::{Days, Utc}; use ethers::types::U256; use postgres_docker_utils::DockerContainerGuard; + use ruint::Uint; use semaphore::Field; use sqlx::types::chrono::DateTime; use sqlx::{PgPool, Row}; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; + use crate::prover::{ProverConfiguration, ProverType}; use crate::secret::SecretUrl; macro_rules! assert_same_time { @@ -731,14 +792,16 @@ mod test { chrono::Duration::milliseconds(x.num_milliseconds().abs()) } + // TODO: we should probably consolidate all tests that propagate errors to + // TODO: either use anyhow or eyre async fn setup_db() -> anyhow::Result<(Database, DockerContainerGuard)> { let db_container = postgres_docker_utils::setup().await?; let port = db_container.port(); let url = format!("postgres://postgres:postgres@localhost:{port}/database"); let db = Database::new(Options { - database: SecretUrl::from_str(&url)?, - database_migrate: true, + database: SecretUrl::from_str(&url)?, + database_migrate: true, database_max_connections: 1, }) .await?; @@ -778,7 +841,12 @@ mod test { let commit_hash: Hash = U256::from_dec_str(dec) .expect("cant convert to u256") .into(); - let hash = db.insert_new_identity(commit_hash).await?; + + let eligibility_timestamp = DateTime::from(Utc::now()); + + let hash = db + .insert_new_identity(commit_hash, eligibility_timestamp) + .await?; assert_eq!(commit_hash, hash); @@ -789,6 +857,7 @@ mod test { assert_eq!(commit.0, Status::New); let identity_count = db.get_unprocessed_commitments(Status::New).await?.len(); + assert_eq!(identity_count, 1); assert!(db.remove_unprocessed_identity(&commit_hash).await.is_ok()); @@ -796,6 +865,209 @@ mod test { Ok(()) } + fn mock_provers() -> HashSet { + let mut provers = HashSet::new(); + + provers.insert(ProverConfiguration { + batch_size: 100, + url: "http://localhost:8080".to_string(), + timeout_s: 100, + prover_type: ProverType::Insertion, + }); + + provers.insert(ProverConfiguration { + batch_size: 100, + url: "http://localhost:8080".to_string(), + timeout_s: 100, + prover_type: ProverType::Deletion, + }); + + provers + } + + #[tokio::test] + async fn test_insert_prover_configuration() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let mock_prover_configuration_0 = ProverConfiguration { + batch_size: 100, + url: "http://localhost:8080".to_string(), + timeout_s: 100, + prover_type: ProverType::Insertion, + }; + + let mock_prover_configuration_1 = ProverConfiguration { + batch_size: 100, + url: "http://localhost:8081".to_string(), + timeout_s: 100, + prover_type: ProverType::Deletion, + }; + + db.insert_prover_configuration( + mock_prover_configuration_0.batch_size, + mock_prover_configuration_0.url.clone(), + mock_prover_configuration_0.timeout_s, + mock_prover_configuration_0.prover_type, + ) + .await?; + + db.insert_prover_configuration( + mock_prover_configuration_1.batch_size, + mock_prover_configuration_1.url.clone(), + mock_prover_configuration_1.timeout_s, + mock_prover_configuration_1.prover_type, + ) + .await?; + + let provers = db.get_provers().await?; + + assert!(provers.contains(&mock_prover_configuration_0)); + assert!(provers.contains(&mock_prover_configuration_1)); + + Ok(()) + } + + #[tokio::test] + async fn test_insert_provers() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let mock_provers = mock_provers(); + + db.insert_provers(mock_provers.clone()).await?; + + let provers = db.get_provers().await?; + + assert_eq!(provers, mock_provers); + Ok(()) + } + + #[tokio::test] + async fn test_remove_prover() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let mock_provers = mock_provers(); + + db.insert_provers(mock_provers.clone()).await?; + db.remove_prover(100, ProverType::Insertion).await?; + let provers = db.get_provers().await?; + + assert_eq!(provers, HashSet::new()); + + Ok(()) + } + + #[tokio::test] + async fn test_insert_new_recovery() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let existing_commitment: Uint<256, 4> = Uint::from(1); + let new_commitment: Uint<256, 4> = Uint::from(2); + + db.insert_new_recovery(&existing_commitment, &new_commitment) + .await?; + + let recoveries = db.get_recoveries().await?; + + assert_eq!(recoveries.len(), 1); + assert_eq!(recoveries[0].existing_commitment, existing_commitment); + assert_eq!(recoveries[0].new_commitment, new_commitment); + + Ok(()) + } + + #[tokio::test] + async fn test_insert_new_deletion() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let existing_commitment: Uint<256, 4> = Uint::from(1); + + db.insert_new_deletion(0, &existing_commitment).await?; + + let deletions = db.get_deletions().await?; + assert_eq!(deletions.len(), 1); + assert_eq!(deletions[0].leaf_index, 0); + assert_eq!(deletions[0].commitment, existing_commitment); + + Ok(()) + } + + #[tokio::test] + async fn test_get_eligible_unprocessed_commitments() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let commitment_0: Uint<256, 4> = Uint::from(1); + let eligibility_timestamp_0 = DateTime::from(Utc::now()); + + db.insert_new_identity(commitment_0, eligibility_timestamp_0) + .await?; + + let commitment_1: Uint<256, 4> = Uint::from(2); + let eligibility_timestamp_1 = DateTime::from(Utc::now()) + .checked_add_days(Days::new(7)) + .expect("Could not create eligibility timestamp"); + + db.insert_new_identity(commitment_1, eligibility_timestamp_1) + .await?; + + let unprocessed_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; + + assert_eq!(unprocessed_commitments.len(), 1); + assert_eq!(unprocessed_commitments[0].commitment, commitment_0); + assert_eq!( + unprocessed_commitments[0].eligibility_timestamp, + eligibility_timestamp_0 + ); + + Ok(()) + } + + #[tokio::test] + async fn test_get_unprocessed_commitments() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let commitment_0: Uint<256, 4> = Uint::from(1); + let eligibility_timestamp_0 = DateTime::from(Utc::now()); + + db.insert_new_identity(commitment_0, eligibility_timestamp_0) + .await?; + + let commitment_1: Uint<256, 4> = Uint::from(2); + let eligibility_timestamp_1 = DateTime::from(Utc::now()) + .checked_add_days(Days::new(7)) + .expect("Could not create eligibility timestamp"); + + db.insert_new_identity(commitment_1, eligibility_timestamp_1) + .await?; + + let unprocessed_commitments = db.get_unprocessed_commitments(Status::New).await?; + + assert_eq!(unprocessed_commitments.len(), 2); + assert_eq!(unprocessed_commitments[0].commitment, commitment_0); + assert_eq!( + unprocessed_commitments[0].eligibility_timestamp, + eligibility_timestamp_0 + ); + + assert_eq!(unprocessed_commitments[1].commitment, commitment_1); + assert_eq!( + unprocessed_commitments[1].eligibility_timestamp, + eligibility_timestamp_1 + ); + + Ok(()) + } + + #[tokio::test] + async fn test_identity_is_queued_for_deletion() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let existing_commitment: Uint<256, 4> = Uint::from(1); + + db.insert_new_deletion(0, &existing_commitment).await?; + + assert!( + db.identity_is_queued_for_deletion(&existing_commitment) + .await? + ); + + Ok(()) + } + #[tokio::test] async fn test_update_eligibility_timestamp() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; @@ -804,8 +1076,18 @@ mod test { .expect("cant convert to u256") .into(); - db.insert_new_identity(commit_hash).await?; + // Set eligibility to Utc::now() day and check db entries + let eligibility_timestamp = DateTime::from(Utc::now()); + db.insert_new_identity(commit_hash, eligibility_timestamp) + .await?; + + let commitments = db.get_unprocessed_commitments(Status::New).await?; + assert_eq!(commitments.len(), 1); + + let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; + assert_eq!(eligible_commitments.len(), 1); + // Set eligibility to Utc::now() + 7 days and check db entries let eligibility_timestamp = DateTime::from(Utc::now()) .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); @@ -813,15 +1095,11 @@ mod test { db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_unprocessed_commitments(Status::Pending).await?; + let commitments = db.get_unprocessed_commitments(Status::New).await?; assert_eq!(commitments.len(), 1); - assert_eq!( - commitments[0] - .eligibility_timestamp - .expect("Could not get eligibility_timestamp from commitment"), - eligibility_timestamp - ); + let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; + assert_eq!(eligible_commitments.len(), 0); Ok(()) } @@ -850,7 +1128,7 @@ mod test { let new_identities = mock_identities(3); for (old, new) in old_identities.into_iter().zip(new_identities) { - db.insert_new_recovery(old, new).await?; + db.insert_new_recovery(&old, &new).await?; } let recoveries = db.get_recoveries().await?; @@ -1226,8 +1504,9 @@ mod test { assert!(!db.identity_exists(identities[0]).await?); // When there's only unprocessed identity + let eligibility_timestamp = DateTime::from(Utc::now()); - db.insert_new_identity(identities[0]) + db.insert_new_identity(identities[0], eligibility_timestamp) .await .context("Inserting new identity")?; assert!(db.identity_exists(identities[0]).await?); diff --git a/src/database/prover.rs b/src/database/prover.rs deleted file mode 100644 index 91125bc4..00000000 --- a/src/database/prover.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::collections::HashSet; -use std::hash::{Hash, Hasher}; - -pub type Provers = HashSet; - -#[derive(Debug, Clone)] -pub struct ProverConfiguration { - pub url: String, - pub batch_size: usize, - pub timeout_s: u64, -} - -impl Hash for ProverConfiguration { - fn hash(&self, state: &mut H) { - self.batch_size.hash(state); - } -} - -impl PartialEq for ProverConfiguration { - fn eq(&self, other: &Self) -> bool { - self.batch_size == other.batch_size - } -} - -impl Eq for ProverConfiguration {} diff --git a/src/database/types.rs b/src/database/types.rs index 6ba69505..a3891197 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -3,20 +3,20 @@ use chrono::{DateTime, Utc}; use crate::identity_tree::{Hash, Status}; pub struct UnprocessedCommitment { - pub commitment: Hash, - pub status: Status, - pub created_at: DateTime, - pub processed_at: Option>, - pub error_message: Option, - pub eligibility_timestamp: Option>, + pub commitment: Hash, + pub status: Status, + pub created_at: DateTime, + pub processed_at: Option>, + pub error_message: Option, + pub eligibility_timestamp: DateTime, } pub struct RecoveryEntry { pub existing_commitment: Hash, - pub new_commitment: Hash, + pub new_commitment: Hash, } pub struct DeletionEntry { - pub leaf_index: i64, //TODO: consider using a larger type for leaf indices + pub leaf_index: i64, // TODO: consider using a larger type for leaf indices pub commitment: Hash, } diff --git a/src/identity_tree.rs b/src/identity_tree.rs index d1b109c2..84235f30 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -183,6 +183,11 @@ where self.tree.root() } + /// Gets the leaf value at a given index. + fn get_leaf(&self, leaf: usize) -> Hash { + self.get_leaf(leaf) + } + /// Gets the proof of the given leaf index element fn get_proof(&self, leaf: usize) -> (Hash, Proof) { let proof = self.tree.proof(leaf); @@ -401,6 +406,8 @@ pub trait TreeVersionReadOps { fn next_leaf(&self) -> usize; /// Returns the merkle proof and element at the given leaf. fn get_proof(&self, leaf: usize) -> (Hash, Proof); + /// Gets the leaf value at a given index. + fn get_leaf(&self, leaf: usize) -> Hash; } impl TreeVersionReadOps for TreeVersion @@ -419,6 +426,11 @@ where let tree = self.get_data(); tree.get_proof(leaf) } + + fn get_leaf(&self, leaf: usize) -> Hash { + let tree = self.get_data(); + tree.get_leaf(leaf) + } } impl TreeVersion { diff --git a/src/prover/batch_insertion/identity.rs b/src/prover/identity.rs similarity index 100% rename from src/prover/batch_insertion/identity.rs rename to src/prover/identity.rs diff --git a/src/prover/map.rs b/src/prover/map.rs index 51b6fc7d..8712b90c 100644 --- a/src/prover/map.rs +++ b/src/prover/map.rs @@ -1,10 +1,9 @@ use std::collections::BTreeMap; +use std::hash::{Hash, Hasher}; use tokio::sync::{RwLock, RwLockReadGuard}; -use crate::database::prover; -use crate::prover::batch_insertion; -use crate::prover::batch_insertion::ProverConfiguration; +use crate::prover::{Prover, ProverConfiguration, ProverType, Provers}; /// The type of a map containing a mapping from a usize to a locked item. type SharedProverMap

= RwLock>; @@ -23,6 +22,10 @@ pub struct ProverMap

{ } impl

ProverMap

{ + pub fn new(map: BTreeMap) -> Self { + Self { map } + } + /// Get the smallest prover that can handle the given batch size. pub fn get(&self, batch_size: usize) -> Option<&P> { for (size, prover) in &self.map { @@ -57,14 +60,15 @@ impl

ProverMap

{ } } -impl ProverMap { +impl ProverMap { pub fn as_configuration_vec(&self) -> Vec { self.map .iter() .map(|(k, v)| ProverConfiguration { - url: v.url(), - timeout_s: v.timeout_s(), - batch_size: *k, + url: v.url(), + timeout_s: v.timeout_s(), + batch_size: *k, + prover_type: v.prover_type(), }) .collect() } @@ -77,24 +81,36 @@ impl

From> for ProverMap

{ } /// A map of provers for batch insertion operations. -pub type InsertionProverMap = SharedProverMap; +pub type InsertionProverMap = SharedProverMap; +/// A map of provers for batch deletion operations. +pub type DeletionProverMap = SharedProverMap; /// The type of provers that can only be read from for insertion operations. -pub type ReadOnlyInsertionProver<'a> = ReadOnlyProver<'a, batch_insertion::Prover>; +pub type ReadOnlyInsertionProver<'a> = ReadOnlyProver<'a, Prover>; /// Builds an insertion prover map from the provided configuration. -pub fn make_insertion_map(db_provers: prover::Provers) -> anyhow::Result { - let mut map = BTreeMap::new(); +pub fn initialize_prover_maps( + db_provers: Provers, +) -> anyhow::Result<(InsertionProverMap, DeletionProverMap)> { + let mut insertion_map = BTreeMap::new(); + let mut deletion_map = BTreeMap::new(); for prover in db_provers { - map.insert( - prover.batch_size, - batch_insertion::Prover::from_prover_conf(&prover)?, - ); + match prover.prover_type { + ProverType::Insertion => { + insertion_map.insert(prover.batch_size, Prover::from_prover_conf(&prover)?); + } + + ProverType::Deletion => { + deletion_map.insert(prover.batch_size, Prover::from_prover_conf(&prover)?); + } + } } - let insertion_map = ProverMap::from(map); - Ok(RwLock::new(insertion_map)) + Ok(( + RwLock::new(ProverMap::new(insertion_map)), + RwLock::new(ProverMap::new(deletion_map)), + )) } #[cfg(test)] diff --git a/src/prover/mod.rs b/src/prover/mod.rs index 5672a806..62f08bbc 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -7,9 +7,641 @@ //! APIs are designed to be imported for use qualified (e.g. //! `batch_insertion::Prover`, `batch_insertion::Identity` and so on). -pub mod batch_insertion; +pub mod identity; pub mod map; pub mod proof; +use std::collections::HashSet; +use std::default; +use std::fmt::{Display, Formatter}; +use std::hash::{Hash, Hasher}; +use std::mem::size_of; +use std::time::Duration; + +use clap::Parser; +use ethers::types::U256; +use ethers::utils::keccak256; pub use map::{InsertionProverMap, ProverMap, ReadOnlyProver}; +use once_cell::sync::Lazy; +use prometheus::{exponential_buckets, register_histogram, Histogram}; pub use proof::Proof; +use serde::{Deserialize, Serialize}; +use url::Url; + +use crate::prover::identity::Identity; +use crate::serde_utils::JsonStrWrapper; + +/// The endpoint used for proving operations. +const MTB_PROVE_ENDPOINT: &str = "prove"; + +static TOTAL_PROVING_TIME: Lazy = Lazy::new(|| { + register_histogram!( + "total_proving_time", + "The time to generate a proof in seconds. Includes preparing the data for the prover", + exponential_buckets(0.1, 1.5, 25).unwrap() + ) + .unwrap() +}); + +static PROVER_PROVING_TIME: Lazy = Lazy::new(|| { + register_histogram!( + "prover_proving_time", + "Only the time between sending a request and receiving the proof", + exponential_buckets(0.1, 1.5, 25).unwrap() + ) + .unwrap() +}); + +#[derive(Clone, Debug, PartialEq, Eq, Parser)] +#[group(skip)] +pub struct Options { + /// The options for configuring the batch insertion prover service. + /// + /// This should be a JSON array containing objects of the following format `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30,"prover_type", "insertion"}` + #[clap( + long, + env, + default_value = r#"[{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30,"prover_type": "insertion"}]"# //TODO: update this and test + )] + pub prover_urls: JsonStrWrapper>, +} + +/// Configuration options for the component responsible for interacting with the +/// prover service. +#[derive(Clone, Debug, Eq, Serialize, Deserialize)] +pub struct ProverConfiguration { + /// The URL at which to contact the semaphore prover service for proof + /// generation. + pub url: String, + + /// The number of seconds to wait before timing out the transaction. + pub timeout_s: u64, + + // TODO Add and query a prover `info` endpoint instead. + /// The batch size that the prover is set up to work with. This must match + /// the deployed prover. + pub batch_size: usize, + + // TODO: add docs + pub prover_type: ProverType, +} + +#[derive(Debug, Copy, Clone, sqlx::Type, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +#[sqlx(type_name = "prover_enum", rename_all = "PascalCase")] +pub enum ProverType { + #[default] + Insertion, + Deletion, +} + +impl Hash for ProverConfiguration { + fn hash(&self, state: &mut H) { + self.batch_size.hash(state); + } +} + +impl PartialEq for ProverConfiguration { + fn eq(&self, other: &Self) -> bool { + self.batch_size == other.batch_size + } +} + +pub type Provers = HashSet; + +/// A representation of the connection to the MTB prover service. +#[derive(Clone, Debug)] +pub struct Prover { + target_url: Url, + client: reqwest::Client, + batch_size: usize, + timeout_s: u64, + prover_type: ProverType, +} + +impl Prover { + /// Constructs a new instance of the Merkle Tree Batcher (or Mtb). + /// + /// # Arguments + /// - `options`: The prover configuration options. + pub fn new(options: &ProverConfiguration) -> anyhow::Result { + let target_url = Url::parse(&options.url)?; + let timeout_duration = Duration::from_secs(options.timeout_s); + let client = reqwest::Client::builder() + .connect_timeout(timeout_duration) + .https_only(false) + .build()?; + + let mtb = Self { + target_url, + client, + batch_size: options.batch_size, + timeout_s: options.timeout_s, + prover_type: options.prover_type, + }; + + Ok(mtb) + } + + /// Creates a new batch insertion prover from the prover taken from the + /// database + pub fn from_prover_conf(prover_conf: &ProverConfiguration) -> anyhow::Result { + let target_url = Url::parse(&prover_conf.url)?; + let timeout_duration = Duration::from_secs(prover_conf.timeout_s); + let client = reqwest::Client::builder() + .connect_timeout(timeout_duration) + .https_only(false) + .build()?; + + Ok(Self { + target_url, + client, + batch_size: prover_conf.batch_size, + timeout_s: prover_conf.timeout_s, + prover_type: prover_conf.prover_type, + }) + } + + pub fn batch_size(&self) -> usize { + self.batch_size + } + + pub fn prover_type(&self) -> ProverType { + self.prover_type + } + + pub fn timeout_s(&self) -> u64 { + self.timeout_s + } + + /// Generates a proof term for the provided identity insertions into the + /// merkle tree. + /// + /// # Arguments + /// - `start_index`: The index in the merkle tree at which the insertions + /// were started. + /// - `pre_root`: The value of the merkle tree's root before identities were + /// inserted. + /// - `post_root`: The value of the merkle tree's root after the identities + /// were inserted. + /// - `identities`: A list of identity insertions, ordered in the order the + /// identities were inserted into the merkle tree. + pub async fn generate_insertion_proof( + &self, + start_index: u32, + pre_root: U256, + post_root: U256, + identities: &[Identity], + ) -> anyhow::Result { + if identities.len() != self.batch_size { + return Err(anyhow::Error::msg( + "Provided batch does not match prover batch size.", + )); + } + + let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); + + let identity_commitments: Vec = identities.iter().map(|id| id.commitment).collect(); + let input_hash = + compute_input_hash(start_index, pre_root, post_root, &identity_commitments); + let merkle_proofs = identities + .iter() + .map(|id| id.merkle_proof.clone()) + .collect(); + + let proof_input = ProofInput { + input_hash, + start_index, + pre_root, + post_root, + identity_commitments, + merkle_proofs, + }; + + let request = self + .client + .post(self.target_url.join(MTB_PROVE_ENDPOINT)?) + .body("OH MY GOD") + .json(&proof_input) + .build()?; + + let prover_proving_time_timer = PROVER_PROVING_TIME.start_timer(); + let proof_term = self.client.execute(request).await?; + let proof_term = proof_term.error_for_status()?; + prover_proving_time_timer.observe_duration(); + + let json = proof_term.text().await?; + + let Ok(proof) = serde_json::from_str::(&json) else { + let error: ProverError = serde_json::from_str(&json)?; + return Err(anyhow::Error::msg(format!("{error}"))) + }; + + total_proving_time_timer.observe_duration(); + + Ok(proof) + } + + pub async fn generate_deletion_proof( + &self, + start_index: u32, + pre_root: U256, + post_root: U256, + identities: &[Identity], + ) -> anyhow::Result { + todo!("TODO:"); + } + + pub fn url(&self) -> String { + self.target_url.to_string() + } +} + +/// Computes the input hash to the prover. +/// +/// The input hash is specified as the `keccak256` hash of the inputs arranged +/// as follows: +/// +/// ```md +/// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] +/// 32 || 256 || 256 || 256 || 256 || ... || 256 bits +/// ``` +/// +/// where: +/// - `StartIndex` is `start_index`, the leaf index in the tree from which the +/// insertions started. +/// - `PreRoot` is `pre_root`, the root value of the merkle tree before the +/// insertions were made. +/// - `PostRoot` is `post_root`, the root value of the merkle tree after the +/// insertions were made. +/// - `IdComms` is `identity_commitments`, the list of identity commitments +/// provided in the order that they were inserted into the tree. +/// +/// The result is computed using the inputs in _big-endian_ byte ordering. +pub fn compute_input_hash( + start_index: u32, + pre_root: U256, + post_root: U256, + identity_commitments: &[U256], +) -> U256 { + let mut pre_root_bytes: [u8; size_of::()] = Default::default(); + pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); + let mut post_root_bytes: [u8; size_of::()] = Default::default(); + post_root.to_big_endian(post_root_bytes.as_mut_slice()); + + let mut bytes: Vec = vec![]; + bytes.extend_from_slice(&start_index.to_be_bytes()); + bytes.extend(pre_root_bytes.iter()); + bytes.extend(post_root_bytes.iter()); + + for commitment in identity_commitments.iter() { + let mut commitment_bytes: [u8; size_of::()] = Default::default(); + commitment.to_big_endian(commitment_bytes.as_mut_slice()); + bytes.extend(commitment_bytes.iter()); + } + + keccak256(bytes).into() +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ProverError { + pub code: String, + pub message: String, +} + +impl Display for ProverError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "PROVER FAILURE: Code = {}, Message = {}", + self.code, self.message + ) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ProofInput { + input_hash: U256, + start_index: u32, + pre_root: U256, + post_root: U256, + identity_commitments: Vec, + merkle_proofs: Vec>, +} + +#[cfg(test)] +mod test { + use super::*; + + #[tokio::test] + async fn mtb_should_generate_proof_with_correct_inputs() -> anyhow::Result<()> { + let mock_url: String = "0.0.0.0:3001".into(); + let mock_service = mock::Service::new(mock_url.clone()).await?; + + let options = ProverConfiguration { + url: "http://localhost:3001".into(), + timeout_s: 30, + batch_size: 3, + prover_type: ProverType::Insertion, + }; + let mtb = Prover::new(&options).unwrap(); + let input_data = get_default_proof_input(); + let identities: Vec = extract_identities_from(&input_data); + + let expected_proof = get_default_proof_output(); + let proof = mtb + .generate_insertion_proof( + input_data.start_index, + input_data.pre_root, + input_data.post_root, + &identities, + ) + .await?; + + mock_service.stop(); + + assert_eq!(proof, expected_proof); + + Ok(()) + } + + #[tokio::test] + async fn mtb_should_respond_with_error_if_inputs_incorrect() -> anyhow::Result<()> { + let mock_url: String = "0.0.0.0:3002".into(); + let mock_service = mock::Service::new(mock_url.clone()).await?; + + let options = ProverConfiguration { + url: "http://localhost:3002".into(), + timeout_s: 30, + batch_size: 3, + prover_type: ProverType::Insertion, + }; + let mtb = Prover::new(&options).unwrap(); + let mut input_data = get_default_proof_input(); + let identities = extract_identities_from(&input_data); + input_data.post_root = U256::from(2); + + let prover_result = mtb + .generate_insertion_proof( + input_data.start_index, + input_data.pre_root, + input_data.post_root, + &identities, + ) + .await; + + mock_service.stop(); + assert!(prover_result.is_err()); + + Ok(()) + } + + #[tokio::test] + async fn prover_should_error_if_batch_size_wrong() -> anyhow::Result<()> { + let options = ProverConfiguration { + url: "http://localhost:3002".into(), + timeout_s: 30, + batch_size: 10, + prover_type: ProverType::Insertion, + }; + let mtb = Prover::new(&options).unwrap(); + let input_data = get_default_proof_input(); + let identities = extract_identities_from(&input_data); + + let prover_result = mtb + .generate_insertion_proof( + input_data.start_index, + input_data.pre_root, + input_data.post_root, + &identities, + ) + .await; + + assert!(prover_result.is_err()); + assert_eq!( + prover_result.unwrap_err().to_string(), + anyhow::Error::msg("Provided batch does not match prover batch size.").to_string() + ); + + Ok(()) + } + + #[test] + fn compute_input_hash_should_succeed() { + let input = get_default_proof_input(); + + assert_eq!( + compute_input_hash( + input.start_index, + input.pre_root, + input.post_root, + &input.identity_commitments + ), + input.input_hash + ); + } + + #[test] + fn proof_input_should_serde() { + let expected_data: ProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); + let proof_input = get_default_proof_input(); + + assert_eq!(proof_input, expected_data); + } + + fn extract_identities_from(proof_input: &ProofInput) -> Vec { + proof_input + .identity_commitments + .iter() + .zip(&proof_input.merkle_proofs) + .map(|(comm, prf)| Identity::new(*comm, prf.clone())) + .collect() + } + + pub fn get_default_proof_output() -> Proof { + Proof::from([ + "0x12bba8b5a46139c819d83544f024828ece34f4f46be933a377a07c1904e96ec4".into(), + "0x112c8d7c63b6c431cef23e9c0d9ffff39d1d660f514030d4f2787960b437a1d5".into(), + "0x2413396a2af3add6fbe8137cfe7657917e31a5cdab0b7d1d645bd5eeb47ba601".into(), + "0x1ad029539528b32ba70964ce43dbf9bba2501cdb3aaa04e4d58982e2f6c34752".into(), + "0x5bb975296032b135458bd49f92d5e9d363367804440d4692708de92e887cf17".into(), + "0x14932600f53a1ceb11d79a7bdd9688a2f8d1919176f257f132587b2b3274c41e".into(), + "0x13d7b19c7b67bf5d3adf2ac2d3885fd5d49435b6069c0656939cd1fb7bef9dc9".into(), + "0x142e14f90c49c79b4edf5f6b7acbcdb0b0f376a4311fc036f1006679bd53ca9e".into(), + ]) + } + + fn get_default_proof_input() -> ProofInput { + let start_index: u32 = 0; + let pre_root: U256 = + "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2".into(); + let post_root: U256 = + "0x7b248024e18c30f6c8a6c63dad3748d72cd13d1197bfd79a1323216d6ac6e99".into(); + let identities: Vec = vec!["0x1".into(), "0x2".into(), "0x3".into()]; + let merkle_proofs: Vec> = vec![ + vec![ + "0x0".into(), + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864".into(), + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), + ], + vec![ + "0x1".into(), + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864".into(), + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), + ], + vec![ + "0x0".into(), + "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a".into(), + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1".into(), + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238".into(), + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a".into(), + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55".into(), + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78".into(), + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d".into(), + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61".into(), + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747".into(), + ], + ]; + let input_hash: U256 = + "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8".into(); + + ProofInput { + input_hash, + start_index, + pre_root, + post_root, + identity_commitments: identities, + merkle_proofs, + } + } + + const EXPECTED_JSON: &str = r#"{ + "inputHash": "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8", + "startIndex": 0, + "preRoot": "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2", + "postRoot": "0x7b248024e18c30f6c8a6c63dad3748d72cd13d1197bfd79a1323216d6ac6e99", + "identityCommitments": [ + "0x1", + "0x2", + "0x3" + ], + "merkleProofs": [ + [ + "0x0", + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" + ], + [ + "0x1", + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" + ], + [ + "0x0", + "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a", + "0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747" + ] + ] +} +"#; +} + +#[cfg(test)] +pub mod mock { + use std::net::SocketAddr; + + use axum::routing::post; + use axum::{Json, Router}; + use axum_server::Handle; + + use super::*; + + pub struct Service { + server: Handle, + } + + #[derive(Serialize, Deserialize)] + #[serde(untagged)] + #[allow(clippy::large_enum_variant)] + enum ProveResponse { + ProofSuccess(Proof), + ProofFailure(ProverError), + } + + impl Service { + pub async fn new(url: String) -> anyhow::Result { + let prove = |Json(payload): Json| async move { + match payload.post_root.div_mod(U256::from(2)) { + (_, y) if y != U256::zero() => { + Json(ProveResponse::ProofSuccess(test::get_default_proof_output())) + } + _ => { + let error = ProverError { + code: "Oh no!".into(), + message: "Things went wrong.".into(), + }; + Json(ProveResponse::ProofFailure(error)) + } + } + }; + let app = Router::new().route("/prove", post(prove)); + + let addr: SocketAddr = url.parse()?; + let server = Handle::new(); + let serverside_handle = server.clone(); + let service = app.into_make_service(); + + tokio::spawn(async move { + axum_server::bind(addr) + .handle(serverside_handle) + .serve(service) + .await + .unwrap(); + }); + + let service = Self { server }; + Ok(service) + } + + pub fn stop(self) { + self.server.shutdown(); + } + } +} diff --git a/src/server/custom_middleware.rs b/src/server/custom_middleware/mod.rs similarity index 100% rename from src/server/custom_middleware.rs rename to src/server/custom_middleware/mod.rs diff --git a/src/server/error.rs b/src/server/error.rs index dacb8ab7..fc5be160 100644 --- a/src/server/error.rs +++ b/src/server/error.rs @@ -33,6 +33,10 @@ pub enum Error { RootMismatch, #[error("Root provided in semaphore proof is too old.")] RootTooOld, + #[error("Identity is already queued for deletion.")] + IdentityQueuedForDeletion, + #[error("Identity has already been deleted.")] + IdentityAlreadyDeleted, #[error("invalid JSON request: {0}")] InvalidSerialization(#[from] serde_json::Error), #[error(transparent)] @@ -57,6 +61,8 @@ pub enum Error { CannotRemoveLastBatchSize, #[error("Identity Manager had no provers on point of identity insertion.")] NoProversOnIdInsert, + #[error("Identity Manager had no provers on point of identity deletion.")] + NoProversOnIdDeletion, #[error(transparent)] Other(#[from] EyreError), } diff --git a/src/server/mod.rs b/src/server/mod.rs index 06595f24..dc5aed14 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -22,6 +22,7 @@ use crate::app::{ App, InclusionProofResponse, ListBatchSizesResponse, VerifySemaphoreProofResponse, }; use crate::identity_tree::Hash; +use crate::prover::ProverType; mod custom_middleware; @@ -55,6 +56,8 @@ pub struct AddBatchSizeRequest { batch_size: usize, /// The timeout for communications with the prover service. timeout_seconds: u64, + // TODO: add docs + prover_type: ProverType, } #[derive(Clone, Serialize, Deserialize)] @@ -62,7 +65,9 @@ pub struct AddBatchSizeRequest { #[serde(deny_unknown_fields)] pub struct RemoveBatchSizeRequest { /// The batch size to remove from the prover map. - batch_size: usize, + batch_size: usize, + // TODO: add docs + prover_type: ProverType, } #[derive(Serialize, Deserialize)] @@ -91,6 +96,24 @@ pub struct VerifySemaphoreProofQuery { pub max_root_age_seconds: Option, } +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct DeletionRequest { + /// The identity commitment to delete. + identity_commitment: Hash, +} + +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct RecoveryRequest { + /// The leaf index of the identity commitment to delete. + prev_identity_commitment: Hash, + /// The new identity commitment to insert. + new_identity_commitment: Hash, +} + pub trait ToResponseCode { fn to_response_code(&self) -> StatusCode; } @@ -145,16 +168,40 @@ async fn add_batch_size( State(app): State>, Json(req): Json, ) -> Result<(), Error> { - app.add_batch_size(req.url, req.batch_size, req.timeout_seconds) - .await?; + app.add_batch_size( + req.url, + req.batch_size, + req.timeout_seconds, + req.prover_type, + ) + .await?; Ok(()) } + +async fn delete_identity( + State(app): State>, + Json(req): Json, +) -> Result<(), Error> { + app.delete_identity(&req.identity_commitment).await?; + Ok(()) +} + +async fn recover_identity( + State(app): State>, + Json(req): Json, +) -> Result<(), Error> { + app.recover_identity(&req.prev_identity_commitment, &req.new_identity_commitment) + .await?; + Ok(()) +} + async fn remove_batch_size( State(app): State>, Json(req): Json, ) -> Result<(), Error> { - app.remove_batch_size(req.batch_size).await?; + app.remove_batch_size(req.batch_size, req.prover_type) + .await?; Ok(()) } @@ -214,6 +261,8 @@ pub async fn bind_from_listener( .route("/inclusionProof", post(inclusion_proof)) .route("/insertIdentity", post(insert_identity)) .route("/addBatchSize", post(add_batch_size)) + .route("/deleteIdentity", post(delete_identity)) + .route("/recoverIdentity", post(recover_identity)) .route("/removeBatchSize", post(remove_batch_size)) .route("/listBatchSizes", get(list_batch_sizes)) .layer(middleware::from_fn( diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 244f2e61..2ec0ca96 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -15,7 +15,7 @@ use crate::database::Database; use crate::identity_tree::{ AppliedTreeUpdate, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, }; -use crate::prover::batch_insertion::Identity; +use crate::prover::identity::Identity; use crate::prover::map::ReadOnlyInsertionProver; use crate::task_monitor::{PendingBatchSubmission, TaskMonitor}; use crate::utils::async_queue::AsyncQueue; @@ -328,7 +328,7 @@ async fn commit_identities( identity_manager.validate_merkle_proofs(&identity_commitments)?; // We prepare the proof before reserving a slot in the pending identities - let proof = IdentityManager::prepare_proof( + let proof = IdentityManager::prepare_insertion_proof( insertion_prover, start_index, pre_root, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 182a3e35..7752d835 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -63,6 +63,7 @@ use hyper::StatusCode; use self::chain_mock::{spawn_mock_chain, MockChain, SpecialisedContract}; use self::prelude::*; +use self::prover_mock::ProverType; #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] @@ -275,14 +276,17 @@ pub async fn test_add_batch_size( uri: impl Into, prover_url: impl Into, batch_size: u64, + prover_type: ProverType, client: &Client, ) -> anyhow::Result<()> { let prover_url_string: String = prover_url.into(); + let body = Body::from( json!({ "url": prover_url_string, "batchSize": batch_size, - "timeoutSeconds": 3 + "timeoutSeconds": 3, + "proverType": prover_type }) .to_string(), ); @@ -306,9 +310,11 @@ pub async fn test_remove_batch_size( uri: impl Into, batch_size: u64, client: &Client, + prover_type: ProverType, expect_failure: bool, ) -> anyhow::Result<()> { - let body = Body::from(json!({ "batchSize": batch_size }).to_string()); + let body = + Body::from(json!({ "batchSize": batch_size, "proverType": prover_type }).to_string()); let request = Request::builder() .method("POST") .uri(uri.into() + "/removeBatchSize") @@ -481,7 +487,8 @@ async fn spawn_db() -> anyhow::Result { } pub async fn spawn_mock_prover(batch_size: usize) -> anyhow::Result { - let mock_prover_service = prover_mock::ProverService::new(batch_size).await?; + let mock_prover_service = + prover_mock::ProverService::new(batch_size, prover_mock::ProverType::Insertion).await?; Ok(mock_prover_service) } diff --git a/tests/common/prover_mock.rs b/tests/common/prover_mock.rs index d0bf5c33..f7ab189e 100644 --- a/tests/common/prover_mock.rs +++ b/tests/common/prover_mock.rs @@ -91,10 +91,30 @@ impl ProveResponse { /// The mock prover service. pub struct ProverService { - server: Handle, - inner: Arc>, - address: SocketAddr, - batch_size: usize, + server: Handle, + inner: Arc>, + address: SocketAddr, + batch_size: usize, + prover_type: ProverType, +} + +// TODO: we could just import this from the sequencer +#[derive(Debug, Copy, Clone, sqlx::Type, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +#[sqlx(type_name = "prover_enum", rename_all = "PascalCase")] +pub enum ProverType { + #[default] + Insertion, + Deletion, +} + +impl std::fmt::Display for ProverType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + ProverType::Insertion => write!(f, "insertion"), + ProverType::Deletion => write!(f, "deletion"), + } + } } struct Prover { @@ -108,7 +128,7 @@ impl ProverService { /// It provides only a single endpoint for now, `/prove` in order to match /// the full service (`semaphore-mtb`). This can be extended in the future /// if needed. - pub async fn new(batch_size: usize) -> anyhow::Result { + pub async fn new(batch_size: usize, prover_type: ProverType) -> anyhow::Result { async fn prove( State(state): State>>, Json(input): Json, @@ -146,6 +166,7 @@ impl ProverService { inner, address, batch_size, + prover_type, }; Ok(service) @@ -169,6 +190,10 @@ impl ProverService { self.batch_size } + pub fn prover_type(&self) -> ProverType { + self.prover_type + } + /// Produces an arg string that's compatible with this prover - can be used /// as is in the CLI args /// @@ -180,12 +205,13 @@ impl ProverService { /// Produces an arg string that's compatible with this prover - needs to be /// wrapped in an array /// - /// e.g. `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30}` + /// e.g. `{"url": "http://localhost:3001","batch_size": 3,"timeout_s": 30,"prover_type": "insertion"}` pub fn arg_string_single(&self) -> String { format!( - r#"{{"url": "{}","batch_size": {},"timeout_s": 30}}"#, + r#"{{"url": "{}","batch_size": {},"timeout_s": 30, "prover_type": "{}"}}"#, self.url(), - self.batch_size + self.batch_size, + self.prover_type ) } } diff --git a/tests/dynamic_batch_sizes.rs b/tests/dynamic_batch_sizes.rs index 5905a1a3..c20c6068 100644 --- a/tests/dynamic_batch_sizes.rs +++ b/tests/dynamic_batch_sizes.rs @@ -128,9 +128,16 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { // Add a new prover for batch sizes of two. let second_prover = spawn_mock_prover(second_batch_size).await?; - test_add_batch_size(&uri, second_prover.url(), second_batch_size as u64, &client) - .await - .expect("Failed to add batch size."); + + test_add_batch_size( + &uri, + second_prover.url(), + second_batch_size as u64, + second_prover.prover_type(), + &client, + ) + .await + .expect("Failed to add batch size."); // Query for the available provers. let batch_sizes_uri: Uri = @@ -153,11 +160,14 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { "url": second_prover.url() + "/", "timeout_s": 3, "batch_size": second_batch_size, + "prover_type": "insertion", }, { "url": prover_mock.url() + "/", "timeout_s": 30, "batch_size": batch_size, + "prover_type": "insertion", + } ]) ); @@ -195,7 +205,14 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { .await; // Now if we remove the original prover, things should still work. - test_remove_batch_size(&uri, batch_size as u64, &client, false).await?; + test_remove_batch_size( + &uri, + batch_size as u64, + &client, + prover_mock.prover_type(), + false, + ) + .await?; // We should be able to insert less than a full batch successfully. test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, 5).await; @@ -216,7 +233,14 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { .await; // We should be unable to remove _all_ of the provers, however. - test_remove_batch_size(&uri, second_batch_size as u64, &client, true).await?; + test_remove_batch_size( + &uri, + second_batch_size as u64, + &client, + second_prover.prover_type(), + true, + ) + .await?; // So we should still be able to run a batch. test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, 6).await; From 1acfbea7df2a65579707899ca5df9042ae739ee8 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Thu, 31 Aug 2023 15:08:29 -0400 Subject: [PATCH 27/45] chore: removing unused whitespace --- schemas/database/008_prover_type.sql | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/schemas/database/008_prover_type.sql b/schemas/database/008_prover_type.sql index 651c9ce0..eacc11df 100644 --- a/schemas/database/008_prover_type.sql +++ b/schemas/database/008_prover_type.sql @@ -14,15 +14,4 @@ ALTER TABLE provers ALTER COLUMN prover_type SET NOT NULL; ALTER TABLE provers DROP CONSTRAINT provers_pkey; -- Drop the url uniqueness constraint -ALTER TABLE provers DROP CONSTRAINT IF EXISTS provers_url_key; - - - - - - - - - - - +ALTER TABLE provers DROP CONSTRAINT IF EXISTS provers_url_key; \ No newline at end of file From a45edef0a47ff5c47d473cbfab4bc6978286b405 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Thu, 31 Aug 2023 15:34:04 -0400 Subject: [PATCH 28/45] removed redundant deletion prover check --- src/app.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/app.rs b/src/app.rs index 35f5ece3..11a2d57a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -401,17 +401,9 @@ impl App { return Err(ServerError::NoProversOnIdInsert); } - // Ensure that deletion provers exist - if !self.identity_manager.has_deletion_provers().await { - warn!( - ?new_commitment, - "Identity Manager has no deletion provers. Add provers with /addBatchSize request." - ); - return Err(ServerError::NoProversOnIdDeletion); - } - // Delete the existing id and insert the commitments into the recovery table self.delete_identity(&existing_commitment).await?; + self.database .insert_new_recovery(&existing_commitment, &new_commitment) .await?; From 04134f8db0d1dfb4bf3ff3e492a9c5d2616a1d82 Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:42:05 -0400 Subject: [PATCH 29/45] Deletion/recovery task monitor updates (#589) * added deletion and recovery endpoints, added app functions for deletion * added deletion prover map * added prover_type to separate deletion and insertion provers * added prover_type during batch size removal * moved custom middleware * updated prover table migration * patching tests, added get_eligible_unprocessed_commitments * patched test_update_eligibility_timestamp * patched dynamic_batch_sizes * chore: cargo fmt * updated delete_identity to check if id has already been deleted or queued for deletion * updated recover_identity to delete existing commitment, and insert data in to recoveries table * removed unused function * added new tests for new database/identity manager logic * added new tests * fix: imported IdentityManager into test mod * updated IdentityManager tests * updated database tests * patched test_remove_prover * added delete_identities task * updated DeleteIdentities methods * updated delete identities task * updated logic to remove deletions from table after inserting into identities table * updated delete task * Updated identity tree peek_next_updates to get contiguous insertion or deletion updates until max_update_count * updated processes identities * added deletion task to the task monitor startup * updated commit_identities * added helper functions for delete/insert identities, refactored commit_identities * added logic to separate insertion/deletion inputs * fix test * added logic to insert recovery commitments after deletion * added deletion indices to deletion proof input * removed identity manager from delete_identities task * removed unused imports, arguments and outdated comment * removed get_unprocessed_commitments * added peek next updates test * updated remove_deletions, added test * moved logic to process recoveries into mine identities task * added logic to get dynamic eligibility timestamp * adding logic to get time until next deletion * added logic to update latest deletion root * updated to track the latest deletion timestamp * chore: typo * removed todos, added fixme --- schemas/database/009_latest_deletion_root.sql | 6 + src/app.rs | 8 +- src/contracts/abi.rs | 2 + src/contracts/mod.rs | 68 ++++- src/database/mod.rs | 161 +++++++--- src/database/types.rs | 7 +- src/identity_tree.rs | 89 +++++- src/prover/mod.rs | 113 ++++++- src/task_monitor.rs | 100 +++++- src/task_monitor/tasks/delete_identities.rs | 110 +++++++ src/task_monitor/tasks/insert_identities.rs | 4 +- src/task_monitor/tasks/mine_identities.rs | 125 +++++++- src/task_monitor/tasks/mod.rs | 1 + src/task_monitor/tasks/process_identities.rs | 284 ++++++++++++++++-- 14 files changed, 976 insertions(+), 102 deletions(-) create mode 100644 schemas/database/009_latest_deletion_root.sql create mode 100644 src/task_monitor/tasks/delete_identities.rs diff --git a/schemas/database/009_latest_deletion_root.sql b/schemas/database/009_latest_deletion_root.sql new file mode 100644 index 00000000..a3a1c146 --- /dev/null +++ b/schemas/database/009_latest_deletion_root.sql @@ -0,0 +1,6 @@ +CREATE TABLE latest_deletion_root ( + Lock char(1) NOT NULL DEFAULT 'X', + deletion_timestamp TIMESTAMPTZ, + constraint PK_T1 PRIMARY KEY (Lock), + constraint CK_T1_Locked CHECK (Lock='X') +) \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index 11a2d57a..f276a277 100644 --- a/src/app.rs +++ b/src/app.rs @@ -155,7 +155,6 @@ impl App { let database = Arc::new(db); let mut provers: HashSet = database.get_provers().await?; - // TODO: need to update this let non_inserted_provers = Self::merge_env_provers(options.batch_provers, &mut provers); database.insert_provers(non_inserted_provers).await?; @@ -372,6 +371,13 @@ impl App { return Err(ServerError::IdentityQueuedForDeletion); } + // Check if there are any deletions, if not, set the latest deletion timestamp + // to now to ensure that the new deletion is processed by the next deletion + // interval + if self.database.get_deletions().await?.is_empty() { + self.database.update_latest_deletion(Utc::now()).await?; + } + // If the id has not been deleted, insert into the deletions table self.database .insert_new_deletion(leaf_index, &commitment) diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index ee3467bb..2bcdeaee 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -8,9 +8,11 @@ abigen!( struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } event TreeChanged(uint256 indexed preRoot, uint8 indexed kind, uint256 indexed postRoot) function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, uint32[] calldata deletionIndices, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) + function getRootHistoryExpiry() external view returns (uint256) ]"#, ); diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 6a5aae08..c4b4bdd3 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -170,7 +170,7 @@ impl IdentityManager { Ok(()) } - pub async fn get_suitable_prover( + pub async fn get_suitable_insertion_prover( &self, num_identities: usize, ) -> anyhow::Result> { @@ -184,13 +184,31 @@ impl IdentityManager { } } + pub async fn get_suitable_deletion_prover( + &self, + num_identities: usize, + ) -> anyhow::Result> { + let prover_map = self.deletion_prover_map.read().await; + + match RwLockReadGuard::try_map(prover_map, |map| map.get(num_identities)) { + Ok(p) => anyhow::Ok(p), + Err(_) => Err(anyhow!( + "No available prover for batch size: {num_identities}" + )), + } + } + + pub async fn root_history_expiry(&self) -> anyhow::Result { + Ok(self.abi.get_root_history_expiry().call().await?) + } + #[instrument(level = "debug", skip(prover, identity_commitments))] pub async fn prepare_insertion_proof( prover: ReadOnlyInsertionProver<'_>, start_index: usize, pre_root: U256, - post_root: U256, identity_commitments: &[Identity], + post_root: U256, ) -> anyhow::Result { let batch_size = identity_commitments.len(); @@ -214,6 +232,27 @@ impl IdentityManager { Ok(proof_data) } + #[instrument(level = "debug", skip(prover, identity_commitments))] + pub async fn prepare_deletion_proof( + prover: ReadOnlyProver<'_, Prover>, + pre_root: U256, + deletion_indices: &[u32], + identity_commitments: Vec, + post_root: U256, + ) -> anyhow::Result { + info!( + "Sending {} identities to prover of batch size {}", + identity_commitments.len(), + prover.batch_size() + ); + + let proof_data: Proof = prover + .generate_deletion_proof(pre_root, post_root, deletion_indices, identity_commitments) + .await?; + + Ok(proof_data) + } + #[instrument(level = "debug", skip(self, identity_commitments, proof_data))] pub async fn register_identities( &self, @@ -251,6 +290,31 @@ impl IdentityManager { .map_err(|tx_err| anyhow!("{}", tx_err.to_string())) } + // TODO: docs + #[instrument(level = "debug")] + pub async fn delete_identities( + &self, + deletion_proof: Proof, + pre_root: U256, + deletion_indices: Vec, + post_root: U256, + ) -> anyhow::Result { + let proof_points_array: [U256; 8] = deletion_proof.into(); + + // We want to send the transaction through our ethereum provider rather than + // directly now. To that end, we create it, and then send it later, waiting for + // it to complete. + let register_identities_transaction = self + .abi + .delete_identities(proof_points_array, pre_root, deletion_indices, post_root) + .tx; + + self.ethereum + .send_transaction(register_identities_transaction, true) + .await + .map_err(|tx_err| anyhow!("{}", tx_err.to_string())) + } + #[instrument(level = "debug", skip(self))] pub async fn mine_identities(&self, transaction_id: TransactionId) -> anyhow::Result { let result = self.ethereum.mine_transaction(transaction_id).await?; diff --git a/src/database/mod.rs b/src/database/mod.rs index 67a2f0a8..e194bca7 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,7 +7,7 @@ use std::collections::HashSet; use anyhow::{anyhow, Context, Error as ErrReport}; -use chrono::Utc; +use chrono::{DateTime, Utc}; use clap::Parser; use sqlx::migrate::{Migrate, MigrateDatabase, Migrator}; use sqlx::pool::PoolOptions; @@ -15,7 +15,7 @@ use sqlx::{Executor, Pool, Postgres, Row}; use thiserror::Error; use tracing::{error, info, instrument, warn}; -use self::types::{DeletionEntry, RecoveryEntry}; +use self::types::{DeletionEntry, LatestDeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod types; @@ -520,6 +520,41 @@ impl Database { Ok(()) } + pub async fn get_latest_deletion(&self) -> Result { + let query = + sqlx::query("SELECT deletion_timestamp FROM latest_deletion_root WHERE Lock = 'X';"); + + let row = self.pool.fetch_optional(query).await?; + + if let Some(row) = row { + Ok(LatestDeletionEntry { + timestamp: row.get(0), + }) + } else { + Ok(LatestDeletionEntry { + timestamp: DateTime::from(Utc::now()), + }) + } + } + + pub async fn update_latest_deletion( + &self, + deletion_timestamp: DateTime, + ) -> Result<(), Error> { + let query = sqlx::query( + r#" + INSERT INTO latest_deletion_root (Lock, deletion_timestamp) + VALUES ('X', $1) + ON CONFLICT (Lock) + DO UPDATE SET deletion_timestamp = EXCLUDED.deletion_timestamp; + "#, + ) + .bind(&deletion_timestamp); + + self.pool.execute(query).await?; + Ok(()) + } + // TODO: consider using a larger value than i64 for leaf index, ruint should // have postgres compatibility for u256 pub async fn get_recoveries(&self) -> Result, Error> { @@ -574,49 +609,45 @@ impl Database { Ok(result .into_iter() .map(|row| DeletionEntry { - leaf_index: row.get::(0), + leaf_index: row.get::(0) as usize, commitment: row.get::(1), }) .collect::>()) } - pub async fn get_eligible_unprocessed_commitments( - &self, - status: Status, - ) -> Result, Error> { - let query = sqlx::query( - r#" - SELECT * FROM unprocessed_identities - WHERE status = $1 AND CURRENT_TIMESTAMP > eligibility - LIMIT $2 - "#, - ) - .bind(<&str>::from(status)) - .bind(MAX_UNPROCESSED_FETCH_COUNT); + /// Remove a list of entries from the deletions table + pub async fn remove_deletions(&self, commitments: Vec) -> Result<(), Error> { + let placeholders: String = commitments + .iter() + .enumerate() + .map(|(i, _)| format!("${}", i + 1)) + .collect::>() + .join(", "); + + let query = format!( + "DELETE FROM deletions WHERE commitment IN ({})", + placeholders + ); - let result = self.pool.fetch_all(query).await?; + let mut query = sqlx::query(&query); - Ok(result - .into_iter() - .map(|row| types::UnprocessedCommitment { - commitment: row.get::(0), - status, - created_at: row.get::<_, _>(2), - processed_at: row.get::<_, _>(3), - error_message: row.get::<_, _>(4), - eligibility_timestamp: row.get::<_, _>(5), - }) - .collect::>()) + for commitment in commitments.iter() { + query = query.bind(commitment); + } + + query.execute(&self.pool).await?; + + Ok(()) } - pub async fn get_unprocessed_commitments( + pub async fn get_eligible_unprocessed_commitments( &self, status: Status, ) -> Result, Error> { let query = sqlx::query( r#" SELECT * FROM unprocessed_identities - WHERE status = $1 + WHERE status = $1 AND CURRENT_TIMESTAMP > eligibility LIMIT $2 "#, ) @@ -633,7 +664,6 @@ impl Database { created_at: row.get::<_, _>(2), processed_at: row.get::<_, _>(3), error_message: row.get::<_, _>(4), - eligibility_timestamp: row.get::<_, _>(5), }) .collect::>()) @@ -856,7 +886,10 @@ mod test { .expect("expected commitment status"); assert_eq!(commit.0, Status::New); - let identity_count = db.get_unprocessed_commitments(Status::New).await?.len(); + let identity_count = db + .get_eligible_unprocessed_commitments(Status::New) + .await? + .len(); assert_eq!(identity_count, 1); @@ -1035,7 +1068,7 @@ mod test { db.insert_new_identity(commitment_1, eligibility_timestamp_1) .await?; - let unprocessed_commitments = db.get_unprocessed_commitments(Status::New).await?; + let unprocessed_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; assert_eq!(unprocessed_commitments.len(), 2); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); @@ -1081,7 +1114,7 @@ mod test { db.insert_new_identity(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_unprocessed_commitments(Status::New).await?; + let commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; assert_eq!(commitments.len(), 1); let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; @@ -1095,7 +1128,7 @@ mod test { db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_unprocessed_commitments(Status::New).await?; + let commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; assert_eq!(commitments.len(), 1); let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; @@ -1520,4 +1553,62 @@ mod test { Ok(()) } + + #[tokio::test] + async fn test_remove_deletions() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let identities = mock_identities(4); + + // Insert new identities + db.insert_new_deletion(0, &identities[0]) + .await + .context("Inserting new identity")?; + + db.insert_new_deletion(1, &identities[1]) + .await + .context("Inserting new identity")?; + + db.insert_new_deletion(2, &identities[2]) + .await + .context("Inserting new identity")?; + db.insert_new_deletion(3, &identities[3]) + .await + .context("Inserting new identity")?; + + // Remove identities 0 to 2 + db.remove_deletions(identities[0..=2].to_vec()).await?; + let deletions = db.get_deletions().await?; + + assert_eq!(deletions.len(), 1); + + Ok(()) + } + + #[tokio::test] + async fn test_latest_deletion_root() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + // Update with initial timestamp + let initial_timestamp = chrono::Utc::now(); + db.update_latest_deletion(initial_timestamp) + .await + .context("Inserting initial root")?; + + // Assert values + let initial_entry = db.get_latest_deletion().await?; + assert_eq!(initial_entry.timestamp, initial_timestamp); + + // Update with a new timestamp + let new_timestamp = chrono::Utc::now(); + db.update_latest_deletion(new_timestamp) + .await + .context("Updating with new root")?; + + // Assert values + let new_entry = db.get_latest_deletion().await?; + assert_eq!(new_entry.timestamp, new_timestamp); + + Ok(()) + } } diff --git a/src/database/types.rs b/src/database/types.rs index a3891197..e3179d3d 100644 --- a/src/database/types.rs +++ b/src/database/types.rs @@ -16,7 +16,12 @@ pub struct RecoveryEntry { pub new_commitment: Hash, } +pub struct LatestDeletionEntry { + pub timestamp: DateTime, +} + +#[derive(Hash, PartialEq, Eq)] pub struct DeletionEntry { - pub leaf_index: i64, // TODO: consider using a larger type for leaf indices + pub leaf_index: usize, pub commitment: Hash, } diff --git a/src/identity_tree.rs b/src/identity_tree.rs index 84235f30..b6c7629a 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -194,17 +194,35 @@ where (self.tree.root(), proof) } - /// Returns _up to_ `maximum_update_count` updates that are to be applied to - /// the tree. + /// Returns _up to_ `maximum_update_count` contiguous deletion or insertion + /// updates that are to be applied to the tree. fn peek_next_updates(&self, maximum_update_count: usize) -> Vec { let Some(next) = self.next.as_ref() else { return Vec::new(); }; let next = next.get_data(); + + let first_is_zero = match next.metadata.diff.first() { + Some(first) => first.update.element == Hash::ZERO, + None => return vec![], + }; + + // Gets the next contiguous of insertion or deletion updates from the diff + let should_take = |elem: &&AppliedTreeUpdate| { + if first_is_zero { + // If first is zero, we should take only consecutive zeros + elem.update.element == Hash::ZERO + } else { + // If first is not zero, we should take only non-zeros + elem.update.element != Hash::ZERO + } + }; + next.metadata .diff .iter() + .take_while(should_take) .take(maximum_update_count) .cloned() .collect() @@ -460,6 +478,23 @@ impl TreeVersion { output } + + /// Deletes many identities from the tree, returns a list with the root + /// and proof of inclusion + pub fn delete_many(&self, leaf_indices: &[usize]) -> Vec<(Hash, Proof)> { + let mut data = self.get_data(); + + let mut output = Vec::with_capacity(leaf_indices.len()); + + for leaf_index in leaf_indices { + data.update(*leaf_index, Hash::ZERO); + let (root, proof) = data.get_proof(*leaf_index); + + output.push((root, proof)); + } + + output + } } /// Public API for working with versions that have a successor. Such versions @@ -668,3 +703,53 @@ impl DerivedTreeBuilder

{ sealed } } + +#[cfg(test)] +mod tests { + use semaphore::lazy_merkle_tree::{Canonical, LazyMerkleTree}; + use semaphore::poseidon_tree::PoseidonHash; + + use super::{ + AppliedTreeUpdate, CanonicalTreeBuilder, DerivedTreeBuilder, Hash, PoseidonTree, + TreeVersion, TreeWithNextVersion, + }; + + #[test] + fn test_peek_next_updates() { + let (canonical_tree, processed_builder) = + CanonicalTreeBuilder::new(10, 10, 0, Hash::ZERO, &vec![]).seal(); + let processed_tree = processed_builder.seal(); + let insertion_updates = processed_tree.append_many(&vec![ + Hash::from(1), + Hash::from(2), + Hash::from(3), + Hash::from(4), + Hash::from(5), + Hash::from(6), + Hash::from(7), + ]); + + let _deletion_updates = processed_tree.delete_many(&vec![0, 1, 2]); + + let next_updates = canonical_tree.peek_next_updates(10); + assert_eq!(next_updates.len(), 7); + + canonical_tree.apply_updates_up_to( + insertion_updates + .last() + .expect("Could not get insertion updates") + .0, + ); + + let _ = processed_tree.append_many(&vec![ + Hash::from(5), + Hash::from(6), + Hash::from(7), + Hash::from(8), + ]); + + let next_updates = canonical_tree.peek_next_updates(10); + + assert_eq!(next_updates.len(), 3); + } +} diff --git a/src/prover/mod.rs b/src/prover/mod.rs index 62f08bbc..f1ab1b9c 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -202,14 +202,18 @@ impl Prover { let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); let identity_commitments: Vec = identities.iter().map(|id| id.commitment).collect(); - let input_hash = - compute_input_hash(start_index, pre_root, post_root, &identity_commitments); + let input_hash = compute_insertion_proof_input_hash( + start_index, + pre_root, + post_root, + &identity_commitments, + ); let merkle_proofs = identities .iter() .map(|id| id.merkle_proof.clone()) .collect(); - let proof_input = ProofInput { + let proof_input = InsertionProofInput { input_hash, start_index, pre_root, @@ -244,12 +248,58 @@ impl Prover { pub async fn generate_deletion_proof( &self, - start_index: u32, pre_root: U256, post_root: U256, - identities: &[Identity], + deletion_indices: &[u32], + identities: Vec, ) -> anyhow::Result { - todo!("TODO:"); + if identities.len() != self.batch_size { + return Err(anyhow::Error::msg( + "Provided batch does not match prover batch size.", + )); + } + + let total_proving_time_timer = TOTAL_PROVING_TIME.start_timer(); + + let (identity_commitments, merkle_proofs): (Vec, Vec>) = identities + .into_iter() + .map(|id| (id.commitment, id.merkle_proof)) + .unzip(); + + let input_hash = + compute_deletion_proof_input_hash(pre_root, post_root, &identity_commitments); + + let proof_input = DeletionProofInput { + input_hash, + pre_root, + post_root, + deletion_indices: deletion_indices.to_vec(), + identity_commitments, + merkle_proofs, + }; + + let request = self + .client + .post(self.target_url.join(MTB_PROVE_ENDPOINT)?) + .body("OH MY GOD") + .json(&proof_input) + .build()?; + + let prover_proving_time_timer = PROVER_PROVING_TIME.start_timer(); + let proof_term = self.client.execute(request).await?; + let proof_term = proof_term.error_for_status()?; + prover_proving_time_timer.observe_duration(); + + let json = proof_term.text().await?; + + let Ok(proof) = serde_json::from_str::(&json) else { + let error: ProverError = serde_json::from_str(&json)?; + return Err(anyhow::Error::msg(format!("{error}"))) + }; + + total_proving_time_timer.observe_duration(); + + Ok(proof) } pub fn url(&self) -> String { @@ -278,7 +328,7 @@ impl Prover { /// provided in the order that they were inserted into the tree. /// /// The result is computed using the inputs in _big-endian_ byte ordering. -pub fn compute_input_hash( +pub fn compute_insertion_proof_input_hash( start_index: u32, pre_root: U256, post_root: U256, @@ -303,6 +353,30 @@ pub fn compute_input_hash( keccak256(bytes).into() } +// TODO: check this and update docs +pub fn compute_deletion_proof_input_hash( + pre_root: U256, + post_root: U256, + identity_commitments: &[U256], +) -> U256 { + let mut pre_root_bytes: [u8; size_of::()] = Default::default(); + pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); + let mut post_root_bytes: [u8; size_of::()] = Default::default(); + post_root.to_big_endian(post_root_bytes.as_mut_slice()); + + let mut bytes: Vec = vec![]; + bytes.extend(pre_root_bytes.iter()); + bytes.extend(post_root_bytes.iter()); + + for commitment in identity_commitments.iter() { + let mut commitment_bytes: [u8; size_of::()] = Default::default(); + commitment.to_big_endian(commitment_bytes.as_mut_slice()); + bytes.extend(commitment_bytes.iter()); + } + + keccak256(bytes).into() +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct ProverError { @@ -322,7 +396,7 @@ impl Display for ProverError { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -struct ProofInput { +struct InsertionProofInput { input_hash: U256, start_index: u32, pre_root: U256, @@ -331,6 +405,17 @@ struct ProofInput { merkle_proofs: Vec>, } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct DeletionProofInput { + input_hash: U256, + pre_root: U256, + post_root: U256, + deletion_indices: Vec, + identity_commitments: Vec, + merkle_proofs: Vec>, +} + #[cfg(test)] mod test { use super::*; @@ -433,7 +518,7 @@ mod test { let input = get_default_proof_input(); assert_eq!( - compute_input_hash( + compute_insertion_proof_input_hash( input.start_index, input.pre_root, input.post_root, @@ -445,13 +530,13 @@ mod test { #[test] fn proof_input_should_serde() { - let expected_data: ProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); + let expected_data: InsertionProofInput = serde_json::from_str(EXPECTED_JSON).unwrap(); let proof_input = get_default_proof_input(); assert_eq!(proof_input, expected_data); } - fn extract_identities_from(proof_input: &ProofInput) -> Vec { + fn extract_identities_from(proof_input: &InsertionProofInput) -> Vec { proof_input .identity_commitments .iter() @@ -473,7 +558,7 @@ mod test { ]) } - fn get_default_proof_input() -> ProofInput { + fn get_default_proof_input() -> InsertionProofInput { let start_index: u32 = 0; let pre_root: U256 = "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2".into(); @@ -521,7 +606,7 @@ mod test { let input_hash: U256 = "0xa2d9c54a0aecf0f2aeb502c4a14ac45209d636986294c5e3168a54a7f143b1d8".into(); - ProofInput { + InsertionProofInput { input_hash, start_index, pre_root, @@ -607,7 +692,7 @@ pub mod mock { impl Service { pub async fn new(url: String) -> anyhow::Result { - let prove = |Json(payload): Json| async move { + let prove = |Json(payload): Json| async move { match payload.post_root.div_mod(U256::from(2)) { (_, y) if y != U256::zero() => { Json(ProveResponse::ProofSuccess(test::get_default_proof_output())) diff --git a/src/task_monitor.rs b/src/task_monitor.rs index 90e768f6..d532eaa6 100644 --- a/src/task_monitor.rs +++ b/src/task_monitor.rs @@ -10,6 +10,7 @@ use tokio::sync::{broadcast, Notify, RwLock}; use tokio::task::JoinHandle; use tracing::{info, instrument, warn}; +use self::tasks::delete_identities::DeleteIdentities; use self::tasks::finalize_identities::FinalizeRoots; use self::tasks::insert_identities::InsertIdentities; use self::tasks::mine_identities::MineIdentities; @@ -17,7 +18,7 @@ use self::tasks::process_identities::ProcessIdentities; use crate::contracts::SharedIdentityManager; use crate::database::Database; use crate::ethereum::write::TransactionId; -use crate::identity_tree::TreeState; +use crate::identity_tree::{Hash, TreeState}; use crate::utils::async_queue::AsyncQueue; pub mod tasks; @@ -26,6 +27,7 @@ const PROCESS_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const FINALIZE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const MINE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const INSERT_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); +const DELETE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); struct RunningInstance { handles: Vec>, @@ -33,13 +35,59 @@ struct RunningInstance { } #[derive(Debug, Clone)] -pub struct PendingBatchSubmission { +pub struct PendingBatchInsertion { transaction_id: TransactionId, pre_root: U256, post_root: U256, start_index: usize, } +impl PendingBatchInsertion { + pub fn new( + transaction_id: TransactionId, + pre_root: U256, + post_root: U256, + start_index: usize, + ) -> Self { + Self { + transaction_id, + pre_root, + post_root, + start_index, + } + } +} + +#[derive(Debug, Clone)] +pub struct PendingBatchDeletion { + transaction_id: TransactionId, + pre_root: U256, + commitments: Vec, + post_root: U256, +} + +impl PendingBatchDeletion { + pub fn new( + transaction_id: TransactionId, + pre_root: U256, + commitments: Vec, + post_root: U256, + ) -> Self { + Self { + transaction_id, + pre_root, + commitments, + post_root, + } + } +} + +#[derive(Debug, Clone)] +pub enum PendingBatchSubmission { + Insertion(PendingBatchInsertion), + Deletion(PendingBatchDeletion), +} + static PENDING_IDENTITIES: Lazy = Lazy::new(|| { register_gauge!("pending_identities", "Identities not submitted on-chain").unwrap() }); @@ -89,6 +137,20 @@ pub struct Options { #[clap(long, env, default_value = "180")] pub batch_timeout_seconds: u64, + /// TODO: + #[clap(long, env, default_value = "3600")] + pub deletion_time_interval: i64, + + /// TODO: + #[clap(long, env, default_value = "100")] + pub min_batch_deletion_size: usize, + + /// How many identities can be held in the API insertion queue at any given + /// time Past this limit the API request will block until the queue has + /// space for the insertion. + #[clap(long, env, default_value = "100")] + pub insert_identities_capacity: usize, + /// How many transactions can be sent "at once" to the blockchain via the /// write provider. #[clap(long, env, default_value = "1")] @@ -122,8 +184,12 @@ pub struct TaskMonitor { pending_identities_capacity: usize, // Finalization params - scanning_window_size: u64, - time_between_scans: Duration, + scanning_window_size: u64, + time_between_scans: Duration, + // TODO: docs + deletion_time_interval: i64, + // TODO: docs + min_batch_deletion_size: usize, } impl TaskMonitor { @@ -138,6 +204,9 @@ impl TaskMonitor { pending_identities_capacity, scanning_window_size, time_between_scans_seconds, + deletion_time_interval, + min_batch_deletion_size, + insert_identities_capacity, } = *options; Self { @@ -149,6 +218,8 @@ impl TaskMonitor { pending_identities_capacity, scanning_window_size, time_between_scans: Duration::from_secs(time_between_scans_seconds), + deletion_time_interval: options.deletion_time_interval, + min_batch_deletion_size: options.min_batch_deletion_size, } } @@ -206,7 +277,7 @@ impl TaskMonitor { handles.push(mine_identities_handle); - // Prcess identities task + // Process identities task let process_identities = ProcessIdentities::new( self.database.clone(), self.identity_manager.clone(), @@ -228,7 +299,7 @@ impl TaskMonitor { let insert_identities = InsertIdentities::new( self.database.clone(), self.tree_state.get_latest_tree(), - wake_up_notify, + wake_up_notify.clone(), ); let insert_identities_handle = crate::utils::spawn_monitored_with_backoff( @@ -239,6 +310,23 @@ impl TaskMonitor { handles.push(insert_identities_handle); + // Delete identities task + let delete_identities = DeleteIdentities::new( + self.database.clone(), + self.tree_state.get_latest_tree(), + self.deletion_time_interval, + self.min_batch_deletion_size, + wake_up_notify, + ); + + let delete_identities_handle = crate::utils::spawn_monitored_with_backoff( + move || delete_identities.clone().run(), + shutdown_sender.clone(), + DELETE_IDENTITIES_BACKOFF, + ); + + handles.push(delete_identities_handle); + *instance = Some(RunningInstance { handles, shutdown_sender, diff --git a/src/task_monitor/tasks/delete_identities.rs b/src/task_monitor/tasks/delete_identities.rs new file mode 100644 index 00000000..79487cf9 --- /dev/null +++ b/src/task_monitor/tasks/delete_identities.rs @@ -0,0 +1,110 @@ +use std::collections::HashSet; +use std::sync::Arc; + +use anyhow::Result as AnyhowResult; +use chrono::{DateTime, Utc}; +use tokio::sync::Notify; +use tracing::info; + +use crate::contracts::SharedIdentityManager; +use crate::database::types::DeletionEntry; +use crate::database::Database; +use crate::identity_tree::{Hash, Latest, TreeVersion}; + +pub struct DeleteIdentities { + database: Arc, + latest_tree: TreeVersion, + deletion_time_interval: i64, + min_deletion_batch_size: usize, + wake_up_notify: Arc, +} + +impl DeleteIdentities { + pub fn new( + database: Arc, + latest_tree: TreeVersion, + deletion_time_interval: i64, + min_deletion_batch_size: usize, + wake_up_notify: Arc, + ) -> Arc { + Arc::new(Self { + database, + latest_tree, + deletion_time_interval, + min_deletion_batch_size, + wake_up_notify, + }) + } + + pub async fn run(self: Arc) -> anyhow::Result<()> { + delete_identities( + &self.database, + &self.latest_tree, + self.deletion_time_interval, + self.min_deletion_batch_size, + self.wake_up_notify.clone(), + ) + .await + } +} + +async fn delete_identities( + database: &Database, + latest_tree: &TreeVersion, + deletion_time_interval: i64, + min_deletion_batch_size: usize, + wake_up_notify: Arc, +) -> AnyhowResult<()> { + info!("Starting deletion processor."); + + let deletion_time_interval = chrono::Duration::seconds(deletion_time_interval); + + loop { + let deletions = database.get_deletions().await?; + if deletions.is_empty() { + // Sleep for one hour + tokio::time::sleep(tokio::time::Duration::from_secs(3600)).await; + continue; + } + + let last_deletion_timestamp = database.get_latest_deletion().await?.timestamp; + // If the minimum deletions batch size is reached or the deletion time interval + // has elapsed, run a batch of deletions + if deletions.len() >= min_deletion_batch_size + || Utc::now() - last_deletion_timestamp > deletion_time_interval + { + // Dedup deletion entries + let deletions = deletions + .into_iter() + .map(|f| f) + .collect::>(); + + let (leaf_indices, previous_commitments): (Vec, Vec) = deletions + .iter() + .map(|d| (d.leaf_index, d.commitment)) + .unzip(); + + // Delete the commitments at the target leaf indices in the latest tree, + // generating the proof for each update + let data = latest_tree.delete_many(&leaf_indices); + + assert_eq!( + data.len(), + leaf_indices.len(), + "Length mismatch when appending identities to tree" + ); + + // Insert the new items into pending identities + let items = data.into_iter().zip(leaf_indices.into_iter()); + for ((root, _proof), leaf_index) in items { + database + .insert_pending_identity(leaf_index, &Hash::ZERO, &root) + .await?; + } + + // Remove the previous commitments from the deletions table + database.remove_deletions(previous_commitments).await?; + wake_up_notify.notify_one(); + } + } +} diff --git a/src/task_monitor/tasks/insert_identities.rs b/src/task_monitor/tasks/insert_identities.rs index 0d990568..cd052d79 100644 --- a/src/task_monitor/tasks/insert_identities.rs +++ b/src/task_monitor/tasks/insert_identities.rs @@ -42,7 +42,9 @@ async fn insert_identities_loop( ) -> AnyhowResult<()> { loop { // get commits from database - let unprocessed = database.get_unprocessed_commitments(Status::New).await?; + let unprocessed = database + .get_eligible_unprocessed_commitments(Status::New) + .await?; if unprocessed.is_empty() { sleep(Duration::from_secs(5)).await; continue; diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs index b64e9982..264f305d 100644 --- a/src/task_monitor/tasks/mine_identities.rs +++ b/src/task_monitor/tasks/mine_identities.rs @@ -1,12 +1,18 @@ +use std::collections::HashMap; use std::sync::Arc; -use anyhow::Result as AnyhowResult; +use anyhow::{Context, Result as AnyhowResult}; +use chrono::{DateTime, Days, Utc}; +use ethers::types::U256; use tracing::{info, instrument}; +use crate::contracts::abi::WorldId; use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; -use crate::identity_tree::{Intermediate, TreeVersion, TreeWithNextVersion}; -use crate::task_monitor::{PendingBatchSubmission, TaskMonitor}; +use crate::identity_tree::{Hash, Intermediate, TreeVersion, TreeWithNextVersion}; +use crate::task_monitor::{ + PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, +}; use crate::utils::async_queue::{AsyncPopGuard, AsyncQueue}; pub struct MineIdentities { @@ -51,25 +57,44 @@ async fn mine_identities_loop( loop { let pending_identity = pending_batch_submissions_queue.pop().await; - mine_identities(&pending_identity, database, identity_manager, mined_tree).await?; + match pending_identity.read().await { + PendingBatchSubmission::Insertion(pending_identity_insertion) => { + mine_insertions( + pending_identity_insertion, + database, + identity_manager, + mined_tree, + ) + .await?; + } + PendingBatchSubmission::Deletion(pending_identity_deletion) => { + mine_deletions( + pending_identity_deletion, + database, + identity_manager, + mined_tree, + ) + .await?; + } + } pending_identity.commit().await; } } #[instrument(level = "info", skip_all)] -async fn mine_identities( - pending_identity: &AsyncPopGuard<'_, PendingBatchSubmission>, +async fn mine_insertions( + pending_identity: PendingBatchInsertion, database: &Database, identity_manager: &IdentityManager, mined_tree: &TreeVersion, ) -> AnyhowResult<()> { - let PendingBatchSubmission { + let PendingBatchInsertion { transaction_id, pre_root, post_root, start_index, - } = pending_identity.read().await; + } = pending_identity; info!( start_index, @@ -110,3 +135,87 @@ async fn mine_identities( Ok(()) } + +#[instrument(level = "info", skip_all)] +async fn mine_deletions( + pending_identity_deletion: PendingBatchDeletion, + database: &Database, + identity_manager: &IdentityManager, + mined_tree: &TreeVersion, +) -> AnyhowResult<()> { + let PendingBatchDeletion { + transaction_id, + pre_root, + post_root, + commitments, + } = pending_identity_deletion; + + info!( + ?pre_root, + ?post_root, + ?transaction_id, + "Mining deletion batch" + ); + + if !identity_manager + .mine_identities(transaction_id.clone()) + .await? + { + panic!( + "Transaction {} failed on chain - sequencer will crash and restart", + transaction_id + ); + } + + // With this done, all that remains is to mark them as submitted to the + // blockchain in the source-of-truth database, and also update the mined tree to + // agree with the database and chain. + database.mark_root_as_processed(&post_root.into()).await?; + + // Update the latest deletion + database.update_latest_deletion(Utc::now()).await?; + + info!(?pre_root, ?post_root, "Deletion batch mined"); + + let updates_count = mined_tree.apply_updates_up_to(post_root.into()); + + info!(updates_count, ?pre_root, ?post_root, "Mined tree updated"); + + // Check if any deleted commitments correspond with entries in the + // recoveries table and insert the new commitment into the unprocessed + // identities table with the proper eligibility timestamp + let recoveries = database + .get_recoveries() + .await? + .iter() + .map(|f| (f.existing_commitment, f.new_commitment)) + .collect::>(); + + // Fetch the root history expiry time on chain + let root_history_expiry = identity_manager.root_history_expiry().await?; + + // Use the root history expiry to calcuate the eligibility timestamp for the new + // insertion + let eligibility_timestamp = DateTime::from_utc( + chrono::NaiveDateTime::from_timestamp_opt( + Utc::now().timestamp() + root_history_expiry.as_u64() as i64, + 0, + ) + .context("Could not convert eligibility timestamp to NaiveDateTime")?, + Utc, + ); + + // For each deletion, if there is a corresponding recovery, insert a new + // identity with the specified eligibility timestamp + for prev_commitment in commitments { + if let Some(new_commitment) = recoveries.get(&prev_commitment.into()) { + database + .insert_new_identity(*new_commitment, eligibility_timestamp) + .await?; + } + } + + TaskMonitor::log_identities_queues(database).await?; + + Ok(()) +} diff --git a/src/task_monitor/tasks/mod.rs b/src/task_monitor/tasks/mod.rs index 8ad56242..8db72a66 100644 --- a/src/task_monitor/tasks/mod.rs +++ b/src/task_monitor/tasks/mod.rs @@ -1,3 +1,4 @@ +pub mod delete_identities; pub mod finalize_identities; pub mod insert_identities; pub mod mine_identities; diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 2ec0ca96..139b704d 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -1,7 +1,9 @@ +use std::collections::HashMap; use std::sync::Arc; use std::time::{Duration, SystemTime}; -use anyhow::Result as AnyhowResult; +use anyhow::{Context, Result as AnyhowResult}; +use chrono::{Days, Utc}; use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{register_histogram, Histogram}; @@ -13,11 +15,14 @@ use tracing::{debug, error, info, instrument, warn}; use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; use crate::identity_tree::{ - AppliedTreeUpdate, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, + AppliedTreeUpdate, Hash, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, }; use crate::prover::identity::Identity; use crate::prover::map::ReadOnlyInsertionProver; -use crate::task_monitor::{PendingBatchSubmission, TaskMonitor}; +use crate::prover::{Proof, Prover, ReadOnlyProver}; +use crate::task_monitor::{ + PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, +}; use crate::utils::async_queue::AsyncQueue; /// The number of seconds either side of the timer tick to treat as enough to @@ -119,21 +124,12 @@ async fn process_identities( continue; } - let prover = identity_manager.get_suitable_prover(updates.len()).await?; - - info!( - "Sending timed-out batch with {}/{} updates.", - updates.len(), - prover.batch_size() - ); - commit_identities( database, identity_manager, batching_tree, pending_batch_submissions_queue, &updates, - prover ).await?; last_batch_time = SystemTime::now(); @@ -179,15 +175,12 @@ async fn process_identities( continue; } - let prover = identity_manager.get_suitable_prover(updates.len()).await?; - commit_identities( database, identity_manager, batching_tree, pending_batch_submissions_queue, &updates, - prover ).await?; // We've inserted the identities, so we want to ensure that @@ -203,14 +196,73 @@ async fn process_identities( } } -#[instrument(level = "info", skip_all)] async fn commit_identities( database: &Database, identity_manager: &IdentityManager, batching_tree: &TreeVersion, pending_batch_submissions_queue: &AsyncQueue, updates: &[AppliedTreeUpdate], - insertion_prover: ReadOnlyInsertionProver<'_>, +) -> AnyhowResult<()> { + // If the update is an insertion + if updates + .first() + .context("Updates should be > 1")? + .update + .element + != Hash::ZERO + { + let prover = identity_manager + .get_suitable_insertion_prover(updates.len()) + .await?; + + info!( + "Sending timed-out insertion batch with {}/{} updates.", + updates.len(), + prover.batch_size() + ); + + insert_identities( + database, + identity_manager, + batching_tree, + pending_batch_submissions_queue, + &updates, + prover, + ) + .await?; + } else { + let prover = identity_manager + .get_suitable_deletion_prover(updates.len()) + .await?; + + info!( + "Sending timed-out deletion batch with {}/{} updates.", + updates.len(), + prover.batch_size() + ); + + delete_identities( + database, + identity_manager, + batching_tree, + pending_batch_submissions_queue, + &updates, + prover, + ) + .await?; + } + + Ok(()) +} + +#[instrument(level = "info", skip_all)] +pub async fn insert_identities( + database: &Database, + identity_manager: &IdentityManager, + batching_tree: &TreeVersion, + pending_batch_submissions_queue: &AsyncQueue, + updates: &[AppliedTreeUpdate], + prover: ReadOnlyProver<'_, Prover>, ) -> AnyhowResult<()> { TaskMonitor::log_identities_queues(database).await?; @@ -221,7 +273,6 @@ async fn commit_identities( debug!("Starting identity commit for {} identities.", updates.len()); - // Sanity check that the insertions are to consecutive leaves in the tree. let mut last_index = updates .first() .expect("Updates is non empty.") @@ -238,6 +289,7 @@ async fn commit_identities( } // Grab the initial conditions before the updates are applied to the tree. + let start_index = updates[0].update.leaf_index; let pre_root: U256 = batching_tree.get_root().into(); let mut commitments: Vec = updates @@ -273,7 +325,7 @@ async fn commit_identities( "Number of identities does not match the number of merkle proofs." ); - let batch_size = insertion_prover.batch_size(); + let batch_size = prover.batch_size(); // The verifier and prover can only work with a given batch size, so we need to // ensure that our batches match that size. We do this by padding with @@ -329,17 +381,13 @@ async fn commit_identities( // We prepare the proof before reserving a slot in the pending identities let proof = IdentityManager::prepare_insertion_proof( - insertion_prover, + prover, start_index, pre_root, - post_root, &identity_commitments, + post_root, ) - .await - .map_err(|e| { - error!(?e, "Failed to prepare proof."); - e - })?; + .await?; #[allow(clippy::cast_precision_loss)] PENDING_IDENTITIES_CHANNEL_CAPACITY.observe(pending_batch_submissions_queue.len().await as f64); @@ -349,7 +397,12 @@ async fn commit_identities( // identities to mine. let permit = pending_batch_submissions_queue.reserve().await; - info!(start_index, ?pre_root, ?post_root, "Submitting batch"); + info!( + start_index, + ?pre_root, + ?post_root, + "Submitting insertion batch" + ); // With all the data prepared we can submit the identities to the on-chain // identity manager and wait for that transaction to be mined. @@ -372,23 +425,190 @@ async fn commit_identities( ?pre_root, ?post_root, ?transaction_id, - "Batch submitted" + "Insertion batch submitted" ); // The transaction will be awaited on asynchronously permit - .send(PendingBatchSubmission { + .send(PendingBatchSubmission::Insertion( + PendingBatchInsertion::new(transaction_id, pre_root, post_root, start_index), + )) + .await; + + // Update the batching tree only after submitting the identities to the chain + batching_tree.apply_updates_up_to(post_root.into()); + + info!(start_index, ?pre_root, ?post_root, "Tree updated"); + + TaskMonitor::log_batch_size(updates.len()); + + Ok(()) +} + +pub async fn delete_identities( + database: &Database, + identity_manager: &IdentityManager, + batching_tree: &TreeVersion, + pending_batch_submissions_queue: &AsyncQueue, + updates: &[AppliedTreeUpdate], + prover: ReadOnlyProver<'_, Prover>, +) -> AnyhowResult<()> { + TaskMonitor::log_identities_queues(database).await?; + + if updates.is_empty() { + warn!("Identity commit requested with zero identities. Continuing."); + return Ok(()); + } + + debug!("Starting identity commit for {} identities.", updates.len()); + + // Grab the initial conditions before the updates are applied to the tree. + let pre_root: U256 = batching_tree.get_root().into(); + let mut commitments: Vec = updates + .iter() + .map(|update| update.update.element.into()) + .collect(); + + let latest_tree_from_updates = updates + .last() + .expect("Updates is non empty.") + .result + .clone(); + + // Next get merkle proofs for each update - note the proofs are acquired from + // intermediate versions of the tree + let mut merkle_proofs: Vec<_> = updates + .iter() + .map(|update_with_tree| { + update_with_tree + .result + .proof(update_with_tree.update.leaf_index) + }) + .collect(); + + // Grab some variables for sizes to make querying easier. + let commitment_count = updates.len(); + + // If these aren't equal then something has gone terribly wrong and is a + // programmer bug, so we abort. + assert_eq!( + commitment_count, + merkle_proofs.len(), + "Number of identities does not match the number of merkle proofs." + ); + + let batch_size = prover.batch_size(); + + // The verifier and prover can only work with a given batch size, so we need to + // ensure that our batches match that size. We do this by padding with + // subsequent zero identities and their associated merkle proofs if the batch is + // too small. + if commitment_count != batch_size { + // FIXME: I dont think this is going to work for deletions + // TODO: need to check this, but basically we are getting the most recent leaf + // and then using that as the start since deletions can happen out of sequence + + // TODO: Calling count is inefficient because it calls `next()` until the + // iterator is exhausted. Update this to be more efficient + let start_index = latest_tree_from_updates.leaves().count(); + let padding = batch_size - commitment_count; + commitments.append(&mut vec![U256::zero(); padding]); + + // TODO: need to check these indices are correct + for i in start_index..(start_index + padding) { + let proof = latest_tree_from_updates.proof(i); + merkle_proofs.push(proof); + } + } + + let deletion_indices = updates + .iter() + .map(|f| f.update.leaf_index as u32) + .collect::>(); + + assert_eq!( + commitments.len(), + batch_size, + "Mismatch between commitments and batch size." + ); + assert_eq!( + merkle_proofs.len(), + batch_size, + "Mismatch between merkle proofs and batch size." + ); + + // With the updates applied we can grab the value of the tree's new root and + // build our identities for sending to the identity manager. + let post_root: U256 = latest_tree_from_updates.root().into(); + let identity_commitments: Vec = commitments + .iter() + .zip(merkle_proofs) + .map(|(id, prf)| { + let commitment: U256 = id.into(); + let proof: Vec = prf + .0 + .iter() + .map(|branch| match branch { + Branch::Left(v) | Branch::Right(v) => U256::from(*v), + }) + .collect(); + Identity::new(commitment, proof) + }) + .collect(); + + identity_manager.validate_merkle_proofs(&identity_commitments)?; + + // We prepare the proof before reserving a slot in the pending identities + let proof = IdentityManager::prepare_deletion_proof( + prover, + pre_root, + &deletion_indices, + identity_commitments, + post_root, + ) + .await?; + + #[allow(clippy::cast_precision_loss)] + PENDING_IDENTITIES_CHANNEL_CAPACITY.observe(pending_batch_submissions_queue.len().await as f64); + + // This queue's capacity provides us with a natural back-pressure mechanism + // to ensure that we don't overwhelm the identity manager with too many + // identities to mine. + let permit = pending_batch_submissions_queue.reserve().await; + + info!(?pre_root, ?post_root, "Submitting deletion batch"); + + // With all the data prepared we can submit the identities to the on-chain + // identity manager and wait for that transaction to be mined. + let transaction_id = identity_manager + .delete_identities(proof, pre_root, deletion_indices, post_root) + .await + .map_err(|e| { + error!(?e, "Failed to insert identity to contract."); + e + })?; + + info!( + ?pre_root, + ?post_root, + ?transaction_id, + "Deletion batch submitted" + ); + + // The transaction will be awaited on asynchronously + permit + .send(PendingBatchSubmission::Deletion(PendingBatchDeletion::new( transaction_id, pre_root, + commitments, post_root, - start_index, - }) + ))) .await; // Update the batching tree only after submitting the identities to the chain batching_tree.apply_updates_up_to(post_root.into()); - info!(start_index, ?pre_root, ?post_root, "Tree updated"); + info!(?pre_root, ?post_root, "Tree updated"); TaskMonitor::log_batch_size(updates.len()); From c3e86485be9058530bad92d3c29d9b96bac67f2d Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Wed, 6 Sep 2023 16:14:16 -0400 Subject: [PATCH 30/45] fixed tests --- src/database/mod.rs | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index e194bca7..97e3442e 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -724,26 +724,6 @@ impl Database { Ok(()) } - // TODO: add docs - pub async fn update_eligibility_timestamp( - &self, - commitment: Hash, - eligibility_timestamp: sqlx::types::chrono::DateTime, - ) -> Result<(), Error> { - let query = sqlx::query( - r#" - UPDATE unprocessed_identities SET eligibility = $1 - WHERE commitment = $2 - "#, - ) - .bind(eligibility_timestamp) - .bind(commitment); - - self.pool.execute(query).await?; - - Ok(()) - } - pub async fn identity_exists(&self, commitment: Hash) -> Result { let query_unprocessed_identity = sqlx::query( r#"SELECT exists(SELECT 1 FROM unprocessed_identities where commitment = $1)"#, @@ -1054,29 +1034,29 @@ mod test { async fn test_get_unprocessed_commitments() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; + // Insert new identity with a valid eligibility timestamp let commitment_0: Uint<256, 4> = Uint::from(1); let eligibility_timestamp_0 = DateTime::from(Utc::now()); - db.insert_new_identity(commitment_0, eligibility_timestamp_0) .await?; + // Insert new identity with eligibility timestamp in the future let commitment_1: Uint<256, 4> = Uint::from(2); let eligibility_timestamp_1 = DateTime::from(Utc::now()) .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); - db.insert_new_identity(commitment_1, eligibility_timestamp_1) .await?; let unprocessed_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; - assert_eq!(unprocessed_commitments.len(), 2); + // Assert unprocessed commitments against expected values + assert_eq!(unprocessed_commitments.len(), 1); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); assert_eq!( unprocessed_commitments[0].eligibility_timestamp, eligibility_timestamp_0 ); - assert_eq!(unprocessed_commitments[1].commitment, commitment_1); assert_eq!( unprocessed_commitments[1].eligibility_timestamp, @@ -1125,14 +1105,13 @@ mod test { .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); - db.update_eligibility_timestamp(commit_hash, eligibility_timestamp) + // Insert new identity with an eligibility timestamp in the future + let commit_hash: Hash = Hash::from(1); + db.insert_new_identity(commit_hash, eligibility_timestamp) .await?; - let commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; - assert_eq!(commitments.len(), 1); - let eligible_commitments = db.get_eligible_unprocessed_commitments(Status::New).await?; - assert_eq!(eligible_commitments.len(), 0); + assert_eq!(eligible_commitments.len(), 1); Ok(()) } From dcbd11321493a9e04a938e601e9909693821bc3d Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:47:45 -0400 Subject: [PATCH 31/45] Deletion proof padding (#593) * updated padding for deletion proof * updated deletion padding * packed deletion indices into bytearray * removed unused import * added padding for merkle proofs and commitments * fixed import * removed deletion index packing from deletion proof, added index packing to contract function input for delete_identities * updated zeroed proof --- src/contracts/abi.rs | 2 +- src/contracts/mod.rs | 13 ++++- src/task_monitor/tasks/process_identities.rs | 54 +++++++++----------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index 2bcdeaee..8a75934d 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -8,7 +8,7 @@ abigen!( struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } event TreeChanged(uint256 indexed preRoot, uint8 indexed kind, uint256 indexed postRoot) function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual - function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, uint32[] calldata deletionIndices, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, bytes calldata deletionIndices, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index c4b4bdd3..99285846 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -7,6 +7,7 @@ use std::sync::Arc; use anyhow::anyhow; use clap::Parser; +use ethers::abi::ethabi::Bytes; use ethers::providers::Middleware; use ethers::types::{Address, U256}; use semaphore::Field; @@ -304,9 +305,19 @@ impl IdentityManager { // We want to send the transaction through our ethereum provider rather than // directly now. To that end, we create it, and then send it later, waiting for // it to complete. + let deletion_indices = deletion_indices + .iter() + .flat_map(|&idx| idx.to_be_bytes().to_vec()) + .collect::>(); + let register_identities_transaction = self .abi - .delete_identities(proof_points_array, pre_root, deletion_indices, post_root) + .delete_identities( + proof_points_array, + pre_root, + deletion_indices.into(), + post_root, + ) .tx; self.ethereum diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 139b704d..0f8fad56 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -7,7 +7,9 @@ use chrono::{Days, Utc}; use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{register_histogram, Histogram}; -use semaphore::poseidon_tree::Branch; +use ruint::Uint; +use semaphore::merkle_tree::Proof; +use semaphore::poseidon_tree::{Branch, PoseidonHash}; use tokio::sync::Notify; use tokio::{select, time}; use tracing::{debug, error, info, instrument, warn}; @@ -19,7 +21,7 @@ use crate::identity_tree::{ }; use crate::prover::identity::Identity; use crate::prover::map::ReadOnlyInsertionProver; -use crate::prover::{Proof, Prover, ReadOnlyProver}; +use crate::prover::{Prover, ReadOnlyProver}; use crate::task_monitor::{ PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, }; @@ -499,42 +501,34 @@ pub async fn delete_identities( let batch_size = prover.batch_size(); + let mut deletion_indices = updates + .iter() + .map(|f| f.update.leaf_index as u32) + .collect::>(); + // The verifier and prover can only work with a given batch size, so we need to - // ensure that our batches match that size. We do this by padding with - // subsequent zero identities and their associated merkle proofs if the batch is - // too small. - if commitment_count != batch_size { - // FIXME: I dont think this is going to work for deletions - // TODO: need to check this, but basically we are getting the most recent leaf - // and then using that as the start since deletions can happen out of sequence + // ensure that our batches match that size. We do this by padding deletion + // indices with tree.depth() ^ 2. The deletion prover will skip the proof for + // any deletion with an index greater than the max tree depth + let pad_index = latest_tree_from_updates.depth().pow(2) as u32; - // TODO: Calling count is inefficient because it calls `next()` until the - // iterator is exhausted. Update this to be more efficient - let start_index = latest_tree_from_updates.leaves().count(); + if commitment_count != batch_size { let padding = batch_size - commitment_count; - commitments.append(&mut vec![U256::zero(); padding]); + commitments.extend(vec![U256::zero(); padding]); + deletion_indices.extend(vec![pad_index; padding]); - // TODO: need to check these indices are correct - for i in start_index..(start_index + padding) { - let proof = latest_tree_from_updates.proof(i); - merkle_proofs.push(proof); - } - } + let zeroed_proof = Proof(vec![ + Branch::Left(Uint::ZERO); + latest_tree_from_updates.depth() + ]); - let deletion_indices = updates - .iter() - .map(|f| f.update.leaf_index as u32) - .collect::>(); + merkle_proofs.extend(vec![zeroed_proof; padding]); + } assert_eq!( - commitments.len(), + deletion_indices.len(), batch_size, - "Mismatch between commitments and batch size." - ); - assert_eq!( - merkle_proofs.len(), - batch_size, - "Mismatch between merkle proofs and batch size." + "Mismatch between deletion indices length and batch size." ); // With the updates applied we can grab the value of the tree's new root and From 261ac8176668942537517c2aded96ed478df6756 Mon Sep 17 00:00:00 2001 From: 0xKitsune <77890308+0xKitsune@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:02:33 -0400 Subject: [PATCH 32/45] Deletion / Recovery Tests (#596) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added deletion test * added deleltion prover setup to spawn_deps * patched test_get_unprocessed_commitments * updated test setup, updated delete identities test, patched get_leaf fucntion for TreeVersionData * updated deletion test * updated identities table to drop unique commitment constraint * added recovery test * added a note that we need a mock deletion proof * updated deletion test * updated mock prover to handle deletion input * patched prove function * updated prove_deletion for mock prover * Add V2 chain mocks (#594) * updated compute_deletion_proof_input_hash * patched mock deletion proof * fixed id commitment population during deletion * updated input hash computation for deletion * updated logging * Fix verifier for deletion * Dzejkop/deletion-recovery-tests-fixes (#595) * Fix deletion tests * Remove commented out code * updated deletion test with todo * updated recovery test * add padded deletion test panicking atm * updated recovery test * updated pad index * added test function to get inclusion status * updated recovery test * Add V2 chain mocks (#594) * patched mock deletion proof * fixed id commitment population during deletion * updated input hash computation for deletion * updated logging * Fix verifier for deletion * Dzejkop/deletion-recovery-tests-fixes (#595) * Fix deletion tests * Remove commented out code * updated deletion test with todo * add padded deletion test panicking atm * fix calculation and rebase on fix still doesn't go through * conflict fix * updated BasicTreeOps to only update next leaf on non zero insertion * updated inclusion proof assertion for recover identity * updated inclusion proof inputs after recoveries * updated recover_identity to check inclusion status of replacement identities * patched recover identity test * add padded deletion tests (#597) * rebase on latest changes * Fix * rebase on latest changes * rebase on latest deletion-recovery-branch commit * fix merge conflict --------- Co-authored-by: Dzejkop * cargo fmt * chore: cargo clippy * chore: removed unused file * chore: removed duplicate test --------- Co-authored-by: Jakub TrÄ…d Co-authored-by: dcbuilder.eth --- schemas/database/004_identities.up.sql | 3 + sol/SimpleStateBridge.json | 414 -- sol/WorldIDIdentityManagerImplV2.json | 6052 ++++++++++++++++++ src/app.rs | 20 +- src/contracts/abi.rs | 2 +- src/contracts/mod.rs | 25 +- src/database/mod.rs | 63 +- src/identity_tree.rs | 56 +- src/prover/map.rs | 2 +- src/prover/mod.rs | 49 +- src/server/mod.rs | 11 +- src/task_monitor.rs | 19 +- src/task_monitor/tasks/delete_identities.rs | 10 +- src/task_monitor/tasks/mine_identities.rs | 6 +- src/task_monitor/tasks/process_identities.rs | 48 +- tests/common/abi.rs | 4 +- tests/common/chain_mock.rs | 66 +- tests/common/mod.rs | 232 +- tests/common/prover_mock.rs | 150 +- tests/delete_identity.rs | 160 + tests/delete_padded_identity.rs | 182 + tests/dynamic_batch_sizes.rs | 10 +- tests/insert_identity_and_proofs.rs | 8 +- tests/malformed_payload.rs | 8 +- tests/multi_prover.rs | 15 +- tests/recover_identity.rs | 201 + tests/unavailable_prover.rs | 8 +- tests/validate_proofs.rs | 8 +- 28 files changed, 7217 insertions(+), 615 deletions(-) delete mode 100644 sol/SimpleStateBridge.json create mode 100644 sol/WorldIDIdentityManagerImplV2.json create mode 100644 tests/delete_identity.rs create mode 100644 tests/delete_padded_identity.rs create mode 100644 tests/recover_identity.rs diff --git a/schemas/database/004_identities.up.sql b/schemas/database/004_identities.up.sql index 3c824bcf..ef302c7f 100644 --- a/schemas/database/004_identities.up.sql +++ b/schemas/database/004_identities.up.sql @@ -4,6 +4,9 @@ ALTER TABLE identities ADD COLUMN id BIGSERIAL; -- Set the new 'id' column as NOT NULL ALTER TABLE identities ALTER COLUMN id SET NOT NULL; +-- Drop the unique commitment constraint to allow for 0x00 to be inserted for deletions +ALTER TABLE identities DROP CONSTRAINT identities_commitment_key; + -- Set the id to be unique ALTER TABLE identities ADD CONSTRAINT id_unique UNIQUE(id); diff --git a/sol/SimpleStateBridge.json b/sol/SimpleStateBridge.json deleted file mode 100644 index c52090c4..00000000 --- a/sol/SimpleStateBridge.json +++ /dev/null @@ -1,414 +0,0 @@ -{ - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "name": "StateRootSentMultichain", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "name": "sendRootMultichain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": { - "object": "0x608060405234801561001057600080fd5b5060ba8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063393170cf14602d575b600080fd5b603c6038366004606c565b603e565b005b60405181907f118a5978e509351fb120eb558e2dc9bd6db3cf57cf66ec9744ef8acabf3b0aec90600090a250565b600060208284031215607d57600080fd5b503591905056fea264697066735822122009366b28a1bae882fe05cdba91a291fdd9387e34205b1448e93122db6c68797264736f6c63430008130033", - "sourceMap": "337:223:57:-:0;;;;;;;;;;;;;;;;;;;", - "linkReferences": {} - }, - "deployedBytecode": { - "object": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063393170cf14602d575b600080fd5b603c6038366004606c565b603e565b005b60405181907f118a5978e509351fb120eb558e2dc9bd6db3cf57cf66ec9744ef8acabf3b0aec90600090a250565b600060208284031215607d57600080fd5b503591905056fea264697066735822122009366b28a1bae882fe05cdba91a291fdd9387e34205b1448e93122db6c68797264736f6c63430008130033", - "sourceMap": "337:223:57:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;439:119;;;;;;:::i;:::-;;:::i;:::-;;;522:29;;546:4;;522:29;;;;;439:119;:::o;14:180:78:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:78;;14:180;-1:-1:-1;14:180:78:o", - "linkReferences": {} - }, - "methodIdentifiers": { - "sendRootMultichain(uint256)": "393170cf" - }, - "rawMetadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"StateRootSentMultichain\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"sendRootMultichain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Worldcoin\",\"kind\":\"dev\",\"methods\":{\"sendRootMultichain(uint256)\":{\"details\":\"Calls this method on the L1 Proxy contract to relay the latest root to all supported networks\",\"params\":{\"root\":\"The latest Semaphore root.\"}}},\"title\":\"State Bridge Mock\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"sendRootMultichain(uint256)\":{\"notice\":\"Sends the latest Semaphore root to Optimism.\"}},\"notice\":\"This purely exists to allow tests to compile and does not have any functionality.A dumb bridge to make it easy to fuzz test successes and failures.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/test/mock/SimpleStateBridge.sol\":\"SimpleStateBridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@zk-kit/=lib/zk-kit/packages/\",\":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":ds-test/=lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/\",\":semaphore/=lib/semaphore/packages/contracts/contracts/\",\":solmate/=lib/solmate/src/\",\":zk-kit/=lib/zk-kit/\"]},\"sources\":{\"src/interfaces/IBridge.sol\":{\"keccak256\":\"0xaa64f67fb28b78d9c270cdbebe00f19611e0eadb67c4287172c805cc2380d8d6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b79e327de5168c65e7d55009533f5d5c2b4262c4c0c86dccd8f8f495e5a7c37d\",\"dweb:/ipfs/QmYCeKYuT84QjdFaVh4vuJYV9aCjB9KyLvcpc73mzc3qXH\"]},\"src/test/mock/SimpleStateBridge.sol\":{\"keccak256\":\"0x70606221ef1952ff696af15db7881b0005b7c10b4934cc4b4f4f61a035792825\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0b451b400c0cb68338d9a09a800f8e259718f19e207a69e159f7117d3a551a10\",\"dweb:/ipfs/QmSgZWVfbnNttEzw8JSbLM2id8uacy7mztwP9EmD59BboC\"]}},\"version\":1}", - "metadata": { - "compiler": { - "version": "0.8.19+commit.7dd6d404" - }, - "language": "Solidity", - "output": { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256", - "indexed": true - } - ], - "type": "event", - "name": "StateRootSentMultichain", - "anonymous": false - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "name": "sendRootMultichain" - } - ], - "devdoc": { - "kind": "dev", - "methods": { - "sendRootMultichain(uint256)": { - "details": "Calls this method on the L1 Proxy contract to relay the latest root to all supported networks", - "params": { - "root": "The latest Semaphore root." - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "sendRootMultichain(uint256)": { - "notice": "Sends the latest Semaphore root to Optimism." - } - }, - "version": 1 - } - }, - "settings": { - "remappings": [ - ":@zk-kit/=lib/zk-kit/packages/", - ":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", - ":ds-test/=lib/ds-test/src/", - ":forge-std/=lib/forge-std/src/", - ":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", - ":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", - ":semaphore/=lib/semaphore/packages/contracts/contracts/", - ":solmate/=lib/solmate/src/", - ":zk-kit/=lib/zk-kit/" - ], - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "compilationTarget": { - "src/test/mock/SimpleStateBridge.sol": "SimpleStateBridge" - }, - "libraries": {} - }, - "sources": { - "src/interfaces/IBridge.sol": { - "keccak256": "0xaa64f67fb28b78d9c270cdbebe00f19611e0eadb67c4287172c805cc2380d8d6", - "urls": [ - "bzz-raw://b79e327de5168c65e7d55009533f5d5c2b4262c4c0c86dccd8f8f495e5a7c37d", - "dweb:/ipfs/QmYCeKYuT84QjdFaVh4vuJYV9aCjB9KyLvcpc73mzc3qXH" - ], - "license": "MIT" - }, - "src/test/mock/SimpleStateBridge.sol": { - "keccak256": "0x70606221ef1952ff696af15db7881b0005b7c10b4934cc4b4f4f61a035792825", - "urls": [ - "bzz-raw://0b451b400c0cb68338d9a09a800f8e259718f19e207a69e159f7117d3a551a10", - "dweb:/ipfs/QmSgZWVfbnNttEzw8JSbLM2id8uacy7mztwP9EmD59BboC" - ], - "license": "MIT" - } - }, - "version": 1 - }, - "ast": { - "absolutePath": "src/test/mock/SimpleStateBridge.sol", - "id": 35680, - "exportedSymbols": { - "IBridge": [ - 26700 - ], - "SimpleStateBridge": [ - 35679 - ] - }, - "nodeType": "SourceUnit", - "src": "32:529:57", - "nodes": [ - { - "id": 35658, - "nodeType": "PragmaDirective", - "src": "32:24:57", - "nodes": [], - "literals": [ - "solidity", - "^", - "0.8", - ".19" - ] - }, - { - "id": 35660, - "nodeType": "ImportDirective", - "src": "58:53:57", - "nodes": [], - "absolutePath": "src/interfaces/IBridge.sol", - "file": "../../interfaces/IBridge.sol", - "nameLocation": "-1:-1:-1", - "scope": 35680, - "sourceUnit": 26701, - "symbolAliases": [ - { - "foreign": { - "id": 35659, - "name": "IBridge", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 26700, - "src": "66:7:57", - "typeDescriptions": {} - }, - "nameLocation": "-1:-1:-1" - } - ], - "unitAlias": "" - }, - { - "id": 35679, - "nodeType": "ContractDefinition", - "src": "337:223:57", - "nodes": [ - { - "id": 35667, - "nodeType": "EventDefinition", - "src": "381:52:57", - "nodes": [], - "anonymous": false, - "eventSelector": "118a5978e509351fb120eb558e2dc9bd6db3cf57cf66ec9744ef8acabf3b0aec", - "name": "StateRootSentMultichain", - "nameLocation": "387:23:57", - "parameters": { - "id": 35666, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 35665, - "indexed": true, - "mutability": "mutable", - "name": "root", - "nameLocation": "427:4:57", - "nodeType": "VariableDeclaration", - "scope": 35667, - "src": "411:20:57", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 35664, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "411:7:57", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "410:22:57" - } - }, - { - "id": 35678, - "nodeType": "FunctionDefinition", - "src": "439:119:57", - "nodes": [], - "body": { - "id": 35677, - "nodeType": "Block", - "src": "507:51:57", - "nodes": [], - "statements": [ - { - "eventCall": { - "arguments": [ - { - "id": 35674, - "name": "root", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 35669, - "src": "546:4:57", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - ], - "id": 35673, - "name": "StateRootSentMultichain", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 35667, - "src": "522:23:57", - "typeDescriptions": { - "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", - "typeString": "function (uint256)" - } - }, - "id": 35675, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "522:29:57", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 35676, - "nodeType": "EmitStatement", - "src": "517:34:57" - } - ] - }, - "baseFunctions": [ - 26699 - ], - "functionSelector": "393170cf", - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "sendRootMultichain", - "nameLocation": "448:18:57", - "overrides": { - "id": 35671, - "nodeType": "OverrideSpecifier", - "overrides": [], - "src": "498:8:57" - }, - "parameters": { - "id": 35670, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 35669, - "mutability": "mutable", - "name": "root", - "nameLocation": "475:4:57", - "nodeType": "VariableDeclaration", - "scope": 35678, - "src": "467:12:57", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 35668, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "467:7:57", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "466:14:57" - }, - "returnParameters": { - "id": 35672, - "nodeType": "ParameterList", - "parameters": [], - "src": "507:0:57" - }, - "scope": 35679, - "stateMutability": "nonpayable", - "virtual": true, - "visibility": "external" - } - ], - "abstract": false, - "baseContracts": [ - { - "baseName": { - "id": 35662, - "name": "IBridge", - "nameLocations": [ - "367:7:57" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 26700, - "src": "367:7:57" - }, - "id": 35663, - "nodeType": "InheritanceSpecifier", - "src": "367:7:57" - } - ], - "canonicalName": "SimpleStateBridge", - "contractDependencies": [], - "contractKind": "contract", - "documentation": { - "id": 35661, - "nodeType": "StructuredDocumentation", - "src": "113:224:57", - "text": "@title State Bridge Mock\n @notice This purely exists to allow tests to compile and does not have any functionality.\n @author Worldcoin\n @notice A dumb bridge to make it easy to fuzz test successes and failures." - }, - "fullyImplemented": true, - "linearizedBaseContracts": [ - 35679, - 26700 - ], - "name": "SimpleStateBridge", - "nameLocation": "346:17:57", - "scope": 35680, - "usedErrors": [] - } - ], - "license": "MIT" - }, - "id": 57 -} \ No newline at end of file diff --git a/sol/WorldIDIdentityManagerImplV2.json b/sol/WorldIDIdentityManagerImplV2.json new file mode 100644 index 00000000..e8eaf181 --- /dev/null +++ b/sol/WorldIDIdentityManagerImplV2.json @@ -0,0 +1,6052 @@ +{ + "abi": [ + { + "inputs": [], + "name": "CannotRenounceOwnership", + "type": "error" + }, + { + "inputs": [], + "name": "ExpiredRoot", + "type": "error" + }, + { + "inputs": [], + "name": "ImplementationNotInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "InvalidCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidStateBridgeAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MismatchedInputLengths", + "type": "error" + }, + { + "inputs": [], + "name": "NonExistentRoot", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "providedRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "latestRoot", + "type": "uint256" + } + ], + "name": "NotLatestRoot", + "type": "error" + }, + { + "inputs": [], + "name": "ProofValidationFailure", + "type": "error" + }, + { + "inputs": [], + "name": "StateBridgeAlreadyDisabled", + "type": "error" + }, + { + "inputs": [], + "name": "StateBridgeAlreadyEnabled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum WorldIDIdentityManagerImplV1.UnreducedElementType", + "name": "elementType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "element", + "type": "uint256" + } + ], + "name": "UnreducedElement", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "depth", + "type": "uint8" + } + ], + "name": "UnsupportedTreeDepth", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum WorldIDIdentityManagerImplV1.Dependency", + "name": "kind", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "DependencyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOperator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "name": "IdentityOperatorChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldExpiryTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256" + } + ], + "name": "RootHistoryExpirySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bool", + "name": "isEnabled", + "type": "bool" + } + ], + "name": "StateBridgeStateChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "enum WorldIDIdentityManagerImplV1.TreeChange", + "name": "kind", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "TreeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256" + } + ], + "name": "WorldIDIdentityManagerImplInitialized", + "type": "event" + }, + { + "inputs": [], + "name": "NO_SUCH_ROOT", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "rootInfo", + "type": "tuple" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + } + ], + "name": "calculateIdentityDeletionInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + } + ], + "name": "calculateIdentityRegistrationInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + } + ], + "name": "calculateIdentityUpdateInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "deletionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "deleteIdentities", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getDeleteIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getIdentityUpdateVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRegisterIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRootHistoryExpiry", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSemaphoreVerifierAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTreeDepth", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "identityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchInsertionVerifiers", + "type": "address" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + }, + { + "internalType": "contract ISemaphoreVerifier", + "name": "_semaphoreVerifier", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + } + ], + "name": "initializeV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "name": "queryRoot", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "insertionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "registerIdentities", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "name": "requireValidRoot", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "name": "setDeleteIdentitiesVerifierLookupTable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newIdentityOperator", + "type": "address" + } + ], + "name": "setIdentityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "name": "setIdentityUpdateVerifierLookupTable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "name": "setRegisterIdentitiesVerifierLookupTable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256" + } + ], + "name": "setRootHistoryExpiry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ISemaphoreVerifier", + "name": "newVerifier", + "type": "address" + } + ], + "name": "setSemaphoreVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "updateProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "name": "updateIdentities", + "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" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "signalHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalNullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256[8]", + "name": "proof", + "type": "uint256[8]" + } + ], + "name": "verifyProof", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": { + "object": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051613e706200027e6000396000818161064e0152818161069701528181610775015281816107b501528181610b8d01528181610bcd0152818161100401528181611044015281816110fb0152818161113b015281816111e701528181611227015281816113270152818161136701528181611577015281816115b701528181611669015281816116a9015281816117ff0152818161183f015281816118ca0152818161190a01528181611985015281816119c501528181611a5c01528181611b0c01528181611b4c01528181611c9b01528181611cdb01528181611da701528181611de701528181611eaa01528181611eea01528181611f8101528181611fc1015281816120570152818161209701528181612177015281816121b70152818161226c015281816122ac0152818161248d015281816124cd015281816125e401528181612624015281816126b1015281816126f101528181612787015281816127c70152818161285b0152818161289b01528181612a8101528181612ac101528181612d3e0152612d7e0152613e706000f3fe6080604052600436106101f95760003560e01c8063715018a61161010d578063aa4a729e116100a0578063e30c39781161006f578063e30c3978146105bc578063f134b6ca146105da578063f2038f95146105ef578063f2358e1d14610604578063f2fde38b1461062457600080fd5b8063aa4a729e14610547578063b843b4e514610567578063c70aa72714610587578063d7b0fef1146105a757600080fd5b80638da5cb5b116100dc5780638da5cb5b146104cd5780638e5cdd50146104eb5780638fc22e9f14610512578063a7bba5821461052757600080fd5b8063715018a61461046357806379ba50971461047857806386ec599a1461048d5780638c76a909146104ad57600080fd5b806338c87065116101905780634f1ef2861161015f5780634f1ef286146103c25780634ffbdde5146103d557806352d1902d146103ea578063561f204b146103ff5780636b0566001461044357600080fd5b806338c87065146103135780633e8919b6146103335780633f7c178d1461036057806343f974cb146103ad57600080fd5b80632f059fca116101cc5780632f059fca1461028057806331e4e992146102a0578063354ca120146102d35780633659cfe6146102f357600080fd5b80630e3a12f3146101fe5780632217b2111461022057806323cfdba51461024057806329b6eca914610260575b600080fd5b34801561020a57600080fd5b5061021e610219366004613375565b610644565b005b34801561022c57600080fd5b5061021e61023b366004613404565b61076b565b34801561024c57600080fd5b5061021e61025b3660046134c3565b610b83565b34801561026c57600080fd5b5061021e61027b366004613375565b610f4c565b34801561028c57600080fd5b5061021e61029b366004613375565b610ffa565b3480156102ac57600080fd5b506102c06102bb36600461353c565b6110ef565b6040519081526020015b60405180910390f35b3480156102df57600080fd5b5061021e6102ee3660046135a3565b6111dd565b3480156102ff57600080fd5b5061021e61030e366004613375565b61131d565b34801561031f57600080fd5b5061021e61032e3660046135e2565b6113e5565b34801561033f57600080fd5b5061034861156b565b6040516001600160a01b0390911681526020016102ca565b34801561036c57600080fd5b5061038061037b366004613650565b611642565b60408051825181526020808401516001600160801b031690820152918101511515908201526060016102ca565b3480156103b957600080fd5b506102c06117f3565b61021e6103d03660046136ac565b6118c0565b3480156103e157600080fd5b50610348611979565b3480156103f657600080fd5b506102c0611a4f565b34801561040b57600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610380565b34801561044f57600080fd5b5061021e61045e366004613375565b611b02565b34801561046f57600080fd5b5061021e611bf7565b34801561048457600080fd5b5061021e611c18565b34801561049957600080fd5b506102c06104a8366004613758565b611c8f565b3480156104b957600080fd5b506102c06104c8366004613805565b611d9b565b3480156104d957600080fd5b506033546001600160a01b0316610348565b3480156104f757600080fd5b50610500611e9e565b60405160ff90911681526020016102ca565b34801561051e57600080fd5b50610348611f75565b34801561053357600080fd5b50610348610542366004613375565b61204b565b34801561055357600080fd5b5061021e610562366004613375565b61216d565b34801561057357600080fd5b5061021e61058236600461386d565b612262565b34801561059357600080fd5b5061021e6105a2366004613650565b612483565b3480156105b357600080fd5b506102c06125d8565b3480156105c857600080fd5b506065546001600160a01b0316610348565b3480156105e657600080fd5b506103486126a5565b3480156105fb57600080fd5b5061034861277b565b34801561061057600080fd5b5061021e61061f366004613650565b612851565b34801561063057600080fd5b5061021e61063f366004613375565b61298e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106955760405162461bcd60e51b815260040161068c90613930565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106c76129ff565b6001600160a01b0316146106ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661071057604051630103019560e11b815260040160405180910390fd5b610718612a1b565b61013380546001600160a01b038381166001600160a01b03198316811790935516908160045b6040517fd194b8423e9cb3c7cbebbbc3fe7f79dc2cbe0b40e03270d975abff491504c7b190600090a45050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107b35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107e56129ff565b6001600160a01b03161461080b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661082e57604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b0316331461085c5760405163472511eb60e11b815233600482015260240161068c565b61012e54851461088e5761012e5460405163542fced960e11b815261068c918791600401918252602082015260400190565b600061089d8587848787611d9b565b905060006108cb7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013154604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa15801561091b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093f91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c60006008811061096e5761096e613a07565b602002013581526020018c60016008811061098b5761098b613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f6004600881106109db576109db613a07565b602002013581526020018f6005600881106109f8576109f8613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610a2c57610a2c613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610a629493929190613a40565b6020604051808303816000875af1925050508015610a9d575060408051601f3d908101601f19168201909252610a9a91810190613ae7565b60015b610afd57610aa9613b09565b806308c379a003610ae25750610abd613b24565b80610ac85750610ae4565b8060405162461bcd60e51b815260040161068c9190613bd2565b505b604051631e716a8b60e01b815260040160405180910390fd5b80610b1b57604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600089815261012f6020526040812080546001600160801b031916426001600160801b031617905585906040518b907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a4505b505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bcb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610bfd6129ff565b6001600160a01b031614610c235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16610c4657604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314610c745760405163472511eb60e11b815233600482015260240161068c565b61012e548214610ca65761012e5460405163542fced960e11b815261068c918491600401918252602082015260400190565b6000610cb5858585858a6110ef565b90506000610ce37f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013554604051638a283fc360e01b815263ffffffff8a1660048201529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c600060088110610d8b57610d8b613a07565b602002013581526020018c600160088110610da857610da8613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f600460088110610df857610df8613a07565b602002013581526020018f600560088110610e1557610e15613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610e4957610e49613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610e7f9493929190613a40565b6020604051808303816000875af1925050508015610eba575060408051601f3d908101601f19168201909252610eb791810190613ae7565b60015b610ec657610aa9613b09565b80610ee457604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600086815261012f6020526040902080546001600160801b031916426001600160801b031617905584600160405188907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b600054600290610100900460ff16158015610f6e575060005460ff8083169116105b610f8a5760405162461bcd60e51b815260040161068c90613c05565b6000805461013580546001600160a01b0319166001600160a01b03861617905561ff001961010060ff851661ffff19909316831717169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110425760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166110746129ff565b6001600160a01b03161461109a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166110bd57604051630103019560e11b815260040160405180910390fd5b6110c5612a1b565b61013180546001600160a01b038381166001600160a01b031983168117909355169081600161073e565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036111395760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661116b6129ff565b6001600160a01b0316146111915760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166111b457604051630103019560e11b815260040160405180910390fd5b604051600483028088833781810195865260209095019390935250506040909101902092915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112255760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112576129ff565b6001600160a01b03161461127d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166112a057604051630103019560e11b815260040160405180910390fd5b6112a985612851565b6101335461013454604051634d65479560e11b81526001600160a01b0390921691639aca8f2a916112f191899188918a9189918991600160a81b900460ff1690600401613c53565b60006040518083038186803b15801561130957600080fd5b505afa158015610b78573d6000803e3d6000fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113655760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166113976129ff565b6001600160a01b0316146113bd5760405162461bcd60e51b815260040161068c9061397c565b6113c681612a77565b604080516000808252602082019092526113e291839190612b1f565b50565b600054600190610100900460ff16158015611407575060005460ff8083169116105b6114235760405162461bcd60e51b815260040161068c90613c05565b6000805461ffff191660ff83161761010017905561143f612c8f565b61144886612cbe565b61146a57604051630220cee360e61b815260ff8716600482015260240161068c565b610134805460ff60a81b1916600160a81b60ff891602179055610e106101305561012e85905561013180546001600160a01b03199081166001600160a01b0387811691909117909255610132805482168684161790556101338054821685841617905560335461012d80549190931691161790556114e6612ce5565b6040805160ff88168152602081018790527fd1bcc66c061c32a21f569d138c2dadef4a38a0636309881954af5f44010ec1d8910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036115b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166115e76129ff565b6001600160a01b03161461160d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661163057604051630103019560e11b815260040160405180910390fd5b50610135546001600160a01b03165b90565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116a75760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166116d96129ff565b6001600160a01b0316146116ff5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661172257604051630103019560e11b815260040160405180910390fd5b61012e5482036117515750506040805160608101825261012e5481526000602082015260019181019190915290565b600082815261012f60205260408120546001600160801b0316908190036117ac5760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b610130546000906117c66001600160801b03841642613c8f565b604080516060810182528781526001600160801b039095166020860152911015908301525090505b919050565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361183d5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661186f6129ff565b6001600160a01b0316146118955760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166118b857604051630103019560e11b815260040160405180910390fd5b506101305490565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119085760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661193a6129ff565b6001600160a01b0316146119605760405162461bcd60e51b815260040161068c9061397c565b61196982612a77565b61197582826001612b1f565b5050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119c35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166119f56129ff565b6001600160a01b031614611a1b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611a3e57604051630103019560e11b815260040160405180910390fd5b50610132546001600160a01b031690565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611aef5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161068c565b50600080516020613df483398151915290565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b4a5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b7c6129ff565b6001600160a01b031614611ba25760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611bc557604051630103019560e11b815260040160405180910390fd5b611bcd612a1b565b61013280546001600160a01b038381166001600160a01b031983168117909355169081600361073e565b611bff612a1b565b6040516377aeb0ad60e01b815260040160405180910390fd5b60655433906001600160a01b03168114611c865760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161068c565b6113e281612d1b565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611cd95760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d0b6129ff565b6001600160a01b031614611d315760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611d5457604051630103019560e11b815260040160405180910390fd5b60008989898989898989604051602001611d75989796959493929190613cd9565b60408051601f1981840301815291905280516020909101209a9950505050505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611de55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611e176129ff565b6001600160a01b031614611e3d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611e6057604051630103019560e11b815260040160405180910390fd5b60008686868686604051602001611e7b959493929190613d3d565b60408051601f198184030181529190528051602090910120979650505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611ee85760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611f1a6129ff565b6001600160a01b031614611f405760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611f6357604051630103019560e11b815260040160405180910390fd5b5061013454600160a81b900460ff1690565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611fbf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ff16129ff565b6001600160a01b0316146120175760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661203a57604051630103019560e11b815260040160405180910390fd5b50610131546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120955760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120c76129ff565b6001600160a01b0316146120ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661211057604051630103019560e11b815260040160405180910390fd5b612118612a1b565b61012d80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f5a674c516c196404869e5f502b5634ce442416bb016dde54b5de4c812cc019e690600090a392915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036121b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166121e76129ff565b6001600160a01b03161461220d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661223057604051630103019560e11b815260040160405180910390fd5b612238612a1b565b61013580546001600160a01b038381166001600160a01b031983168117909355169081600261073e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122aa5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122dc6129ff565b6001600160a01b0316146123025760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661232557604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b031633146123535760405163472511eb60e11b815233600482015260240161068c565b61012e5488146123855761012e5460405163542fced960e11b815261068c918a91600401918252602082015260400190565b85841415806123945750858214155b156123b25760405163a0b1d72d60e01b815260040160405180910390fd5b60006123c489838a8a8a8a8a8a611c8f565b905060006123f27f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013254604051638a283fc360e01b8152600481018b90529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246691906139ea565b9050612475818d848e88612d34565b505050505050505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124cb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166124fd6129ff565b6001600160a01b0316146125235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661254657604051630103019560e11b815260040160405180910390fd5b61254e612a1b565b8060000361259e5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e0000000000604482015260640161068c565b610130805490829055604051829082907ff62a6f06fde00a303cd5939e6b53762854412c96a196cda26720cedd28af9e7090600090a35050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126225760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166126546129ff565b6001600160a01b03161461267a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661269d57604051630103019560e11b815260040160405180910390fd5b5061012e5490565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126ef5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127216129ff565b6001600160a01b0316146127475760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661276a57604051630103019560e11b815260040160405180910390fd5b5061012d546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036127c55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127f76129ff565b6001600160a01b03161461281d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661284057604051630103019560e11b815260040160405180910390fd5b50610133546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036128995760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166128cb6129ff565b6001600160a01b0316146128f15760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661291457604051630103019560e11b815260040160405180910390fd5b61012e5481146113e257600081815261012f60205260408120546001600160801b0316908190036129585760405163ddae3b7160e01b815260040160405180910390fd5b6101305461296f6001600160801b03831642613c8f565b111561197557604051631d739acf60e11b815260040160405180910390fd5b612996612a1b565b606580546001600160a01b0383166001600160a01b031990911681179091556129c76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080516020613df4833981519152546001600160a01b031690565b6033546001600160a01b03163314612a755760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161068c565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612abf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612af16129ff565b6001600160a01b031614612b175760405162461bcd60e51b815260040161068c9061397c565b6113e2612a1b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612b5757612b528361302b565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bb1575060408051601f3d908101601f19168201909252612bae91810190613d73565b60015b612c145760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161068c565b600080516020613df48339815191528114612c835760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161068c565b50612b528383836130c7565b600054610100900460ff16612cb65760405162461bcd60e51b815260040161068c90613d8c565b612a756130f2565b60006010602060ff84168211801590612cdd57508060ff168460ff1611155b949350505050565b600054610100900460ff16612d0c5760405162461bcd60e51b815260040161068c90613d8c565b60fb805460ff19166001179055565b606580546001600160a01b03191690556113e281613129565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612d7c5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612dae6129ff565b6001600160a01b031614612dd45760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16612df757604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314612e255760405163472511eb60e11b815233600482015260240161068c565b6000604051806040016040528086600060088110612e4557612e45613a07565b6020020135815260200186600160088110612e6257612e62613a07565b6020020135905260408051608081018252878201359181019182529192506000919081906060820189600360200201358152508152602001604051806040016040528089600460088110612eb857612eb8613a07565b6020020135815260200189600560088110612ed557612ed5613a07565b60200201359052905260408051808201909152909150600090808860066020020135815260200188600760088110612f0f57612f0f613a07565b6020020135815250905060006040518060200160405280888152509050886001600160a01b03166343753b4d858585856040518563ffffffff1660e01b8152600401612f5e9493929190613a40565b6020604051808303816000875af1925050508015612f99575060408051601f3d908101601f19168201909252612f9691810190613ae7565b60015b612fa557610aa9613b09565b80612fc357604051631e716a8b60e01b815260040160405180910390fd5b61012e869055600087815261012f6020526040902080546001600160801b031916426001600160801b031617905585600260405189907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b6001600160a01b0381163b6130985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161068c565b600080516020613df483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6130d08361317b565b6000825111806130dd5750805b15612b52576130ec83836131bb565b50505050565b600054610100900460ff166131195760405162461bcd60e51b815260040161068c90613d8c565b6131216132b1565b612a756132e0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6131848161302b565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6132235760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161068c565b600080846001600160a01b03168460405161323e9190613dd7565b600060405180830381855af49150503d8060008114613279576040519150601f19603f3d011682016040523d82523d6000602084013e61327e565b606091505b50915091506132a68282604051806060016040528060278152602001613e1460279139613307565b925050505b92915050565b600054610100900460ff166132d85760405162461bcd60e51b815260040161068c90613d8c565b612a75613320565b600054610100900460ff16612a755760405162461bcd60e51b815260040161068c90613d8c565b606083156133165750816117a5565b6117a58383613350565b600054610100900460ff166133475760405162461bcd60e51b815260040161068c90613d8c565b612a7533612d1b565b815115610ac85781518083602001fd5b6001600160a01b03811681146113e257600080fd5b60006020828403121561338757600080fd5b81356117a581613360565b8061010081018310156132ab57600080fd5b803563ffffffff811681146117ee57600080fd5b60008083601f8401126133ca57600080fd5b50813567ffffffffffffffff8111156133e257600080fd5b6020830191508360208260051b85010111156133fd57600080fd5b9250929050565b600080600080600080610180878903121561341e57600080fd5b6134288888613392565b9550610100870135945061343f61012088016133a4565b935061014087013567ffffffffffffffff81111561345c57600080fd5b61346889828a016133b8565b979a969950949794969561016090950135949350505050565b60008083601f84011261349357600080fd5b50813567ffffffffffffffff8111156134ab57600080fd5b6020830191508360208285010111156133fd57600080fd5b60008060008060008061018087890312156134dd57600080fd5b6134e78888613392565b95506134f661010088016133a4565b945061012087013567ffffffffffffffff81111561351357600080fd5b61351f89828a01613481565b979a96995097610140810135966101609091013595509350505050565b60008060008060006080868803121561355457600080fd5b853567ffffffffffffffff81111561356b57600080fd5b61357788828901613481565b9096509450506020860135925060408601359150613597606087016133a4565b90509295509295909350565b600080600080600061018086880312156135bc57600080fd5b853594506020860135935060408601359250606086013591506135978760808801613392565b600080600080600060a086880312156135fa57600080fd5b853560ff8116811461360b57600080fd5b945060208601359350604086013561362281613360565b9250606086013561363281613360565b9150608086013561364281613360565b809150509295509295909350565b60006020828403121561366257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff811182821017156136a5576136a5613669565b6040525050565b600080604083850312156136bf57600080fd5b82356136ca81613360565b915060208381013567ffffffffffffffff808211156136e857600080fd5b818601915086601f8301126136fc57600080fd5b81358181111561370e5761370e613669565b6040519150613726601f8201601f191685018361367f565b808252878482850101111561373a57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060008060008060008060a0898b03121561377457600080fd5b8835975060208901359650604089013567ffffffffffffffff8082111561379a57600080fd5b6137a68c838d016133b8565b909850965060608b01359150808211156137bf57600080fd5b6137cb8c838d016133b8565b909650945060808b01359150808211156137e457600080fd5b506137f18b828c016133b8565b999c989b5096995094979396929594505050565b60008060008060006080868803121561381d57600080fd5b613826866133a4565b94506020860135935060408601359250606086013567ffffffffffffffff81111561385057600080fd5b61385c888289016133b8565b969995985093965092949392505050565b60008060008060008060008060006101a08a8c03121561388c57600080fd5b6138968b8b613392565b98506101008a013597506101208a013567ffffffffffffffff808211156138bc57600080fd5b6138c88d838e016133b8565b90995097506101408c01359150808211156138e257600080fd5b6138ee8d838e016133b8565b90975095506101608c013591508082111561390857600080fd5b506139158c828d016133b8565b9a9d999c50979a969995989497966101800135949350505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6000826139e557634e487b7160e01b600052601260045260246000fd5b500690565b6000602082840312156139fc57600080fd5b81516117a581613360565b634e487b7160e01b600052603260045260246000fd5b8060005b60028110156130ec578151845260209384019390910190600101613a21565b6101208101613a4f8287613a1d565b60408083018660005b6002808210613a675750613aa2565b82518460005b83811015613a8b578251825260209283019290910190600101613a6d565b505050928401925060209190910190600101613a58565b50505050613ab360c0830185613a1d565b61010082018360005b6001811015613adb578151835260209283019290910190600101613abc565b50505095945050505050565b600060208284031215613af957600080fd5b815180151581146117a557600080fd5b600060033d111561163f5760046000803e5060005160e01c90565b600060443d1015613b325790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715613b6257505050505090565b8285019150815181811115613b7a5750505050505090565b843d8701016020828501011115613b945750505050505090565b613ba36020828601018761367f565b509095945050505050565b60005b83811015613bc9578181015183820152602001613bb1565b50506000910152565b6020815260008251806020840152613bf1816040850160208701613bae565b601f01601f19169190910160400192915050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006101a08201905087825286602083015285604083015284606083015261010084608084013760ff8316610180830152979650505050505050565b818103818111156132ab57634e487b7160e01b600052601160045260246000fd5b60006001600160fb1b03831115613cc657600080fd5b8260051b80838637939093019392505050565b888152600060208981840152604083018960005b8a811015613d165763ffffffff613d03836133a4565b1683529183019190830190600101613ced565b5050613d2d613d2682898b613cb0565b8688613cb0565b9c9b505050505050505050505050565b63ffffffff60e01b8660e01b1681528460048201528360248201526000613d68604483018486613cb0565b979650505050505050565b600060208284031215613d8557600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251613de9818460208701613bae565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202258b63db6550ae18ade93a6816c682fce5f6960e9619c49b1085dddff743c4364736f6c63430008150033", + "sourceMap": "443:11607:43:-:0;;;1332:4:23;1289:48;;443:11607:43;;;;;;;;;-1:-1:-1;12497:22:42;:20;:22::i;:::-;443:11607:43;;5928:279:22;5996:13;;;;;;;5995:14;5987:66;;;;-1:-1:-1;;;5987:66:22;;216:2:80;5987:66:22;;;198:21:80;255:2;235:18;;;228:30;294:34;274:18;;;267:62;-1:-1:-1;;;345:18:80;;;338:37;392:19;;5987:66:22;;;;;;;;6067:12;;6082:15;6067:12;;;:30;6063:138;;;6113:12;:30;;-1:-1:-1;;6113:30:22;6128:15;6113:30;;;;;;6162:28;;564:36:80;;;6162:28:22;;552:2:80;537:18;6162:28:22;;;;;;;6063:138;5928:279::o;422:184:80:-;443:11607:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x6080604052600436106101f95760003560e01c8063715018a61161010d578063aa4a729e116100a0578063e30c39781161006f578063e30c3978146105bc578063f134b6ca146105da578063f2038f95146105ef578063f2358e1d14610604578063f2fde38b1461062457600080fd5b8063aa4a729e14610547578063b843b4e514610567578063c70aa72714610587578063d7b0fef1146105a757600080fd5b80638da5cb5b116100dc5780638da5cb5b146104cd5780638e5cdd50146104eb5780638fc22e9f14610512578063a7bba5821461052757600080fd5b8063715018a61461046357806379ba50971461047857806386ec599a1461048d5780638c76a909146104ad57600080fd5b806338c87065116101905780634f1ef2861161015f5780634f1ef286146103c25780634ffbdde5146103d557806352d1902d146103ea578063561f204b146103ff5780636b0566001461044357600080fd5b806338c87065146103135780633e8919b6146103335780633f7c178d1461036057806343f974cb146103ad57600080fd5b80632f059fca116101cc5780632f059fca1461028057806331e4e992146102a0578063354ca120146102d35780633659cfe6146102f357600080fd5b80630e3a12f3146101fe5780632217b2111461022057806323cfdba51461024057806329b6eca914610260575b600080fd5b34801561020a57600080fd5b5061021e610219366004613375565b610644565b005b34801561022c57600080fd5b5061021e61023b366004613404565b61076b565b34801561024c57600080fd5b5061021e61025b3660046134c3565b610b83565b34801561026c57600080fd5b5061021e61027b366004613375565b610f4c565b34801561028c57600080fd5b5061021e61029b366004613375565b610ffa565b3480156102ac57600080fd5b506102c06102bb36600461353c565b6110ef565b6040519081526020015b60405180910390f35b3480156102df57600080fd5b5061021e6102ee3660046135a3565b6111dd565b3480156102ff57600080fd5b5061021e61030e366004613375565b61131d565b34801561031f57600080fd5b5061021e61032e3660046135e2565b6113e5565b34801561033f57600080fd5b5061034861156b565b6040516001600160a01b0390911681526020016102ca565b34801561036c57600080fd5b5061038061037b366004613650565b611642565b60408051825181526020808401516001600160801b031690820152918101511515908201526060016102ca565b3480156103b957600080fd5b506102c06117f3565b61021e6103d03660046136ac565b6118c0565b3480156103e157600080fd5b50610348611979565b3480156103f657600080fd5b506102c0611a4f565b34801561040b57600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610380565b34801561044f57600080fd5b5061021e61045e366004613375565b611b02565b34801561046f57600080fd5b5061021e611bf7565b34801561048457600080fd5b5061021e611c18565b34801561049957600080fd5b506102c06104a8366004613758565b611c8f565b3480156104b957600080fd5b506102c06104c8366004613805565b611d9b565b3480156104d957600080fd5b506033546001600160a01b0316610348565b3480156104f757600080fd5b50610500611e9e565b60405160ff90911681526020016102ca565b34801561051e57600080fd5b50610348611f75565b34801561053357600080fd5b50610348610542366004613375565b61204b565b34801561055357600080fd5b5061021e610562366004613375565b61216d565b34801561057357600080fd5b5061021e61058236600461386d565b612262565b34801561059357600080fd5b5061021e6105a2366004613650565b612483565b3480156105b357600080fd5b506102c06125d8565b3480156105c857600080fd5b506065546001600160a01b0316610348565b3480156105e657600080fd5b506103486126a5565b3480156105fb57600080fd5b5061034861277b565b34801561061057600080fd5b5061021e61061f366004613650565b612851565b34801561063057600080fd5b5061021e61063f366004613375565b61298e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106955760405162461bcd60e51b815260040161068c90613930565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106c76129ff565b6001600160a01b0316146106ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661071057604051630103019560e11b815260040160405180910390fd5b610718612a1b565b61013380546001600160a01b038381166001600160a01b03198316811790935516908160045b6040517fd194b8423e9cb3c7cbebbbc3fe7f79dc2cbe0b40e03270d975abff491504c7b190600090a45050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107b35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107e56129ff565b6001600160a01b03161461080b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661082e57604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b0316331461085c5760405163472511eb60e11b815233600482015260240161068c565b61012e54851461088e5761012e5460405163542fced960e11b815261068c918791600401918252602082015260400190565b600061089d8587848787611d9b565b905060006108cb7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013154604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa15801561091b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093f91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c60006008811061096e5761096e613a07565b602002013581526020018c60016008811061098b5761098b613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f6004600881106109db576109db613a07565b602002013581526020018f6005600881106109f8576109f8613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610a2c57610a2c613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610a629493929190613a40565b6020604051808303816000875af1925050508015610a9d575060408051601f3d908101601f19168201909252610a9a91810190613ae7565b60015b610afd57610aa9613b09565b806308c379a003610ae25750610abd613b24565b80610ac85750610ae4565b8060405162461bcd60e51b815260040161068c9190613bd2565b505b604051631e716a8b60e01b815260040160405180910390fd5b80610b1b57604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600089815261012f6020526040812080546001600160801b031916426001600160801b031617905585906040518b907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a4505b505050505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bcb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610bfd6129ff565b6001600160a01b031614610c235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16610c4657604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314610c745760405163472511eb60e11b815233600482015260240161068c565b61012e548214610ca65761012e5460405163542fced960e11b815261068c918491600401918252602082015260400190565b6000610cb5858585858a6110ef565b90506000610ce37f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013554604051638a283fc360e01b815263ffffffff8a1660048201529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c91906139ea565b9050806001600160a01b03166343753b4d60405180604001604052808c600060088110610d8b57610d8b613a07565b602002013581526020018c600160088110610da857610da8613a07565b60200201359052604080516080810182528d820135918101918252908190606082018f60036020020135815250815260200160405180604001604052808f600460088110610df857610df8613a07565b602002013581526020018f600560088110610e1557610e15613a07565b60200201359052905260408051808201909152808e6006602002013581526020018e600760088110610e4957610e49613a07565b60200201358152506040518060200160405280888152506040518563ffffffff1660e01b8152600401610e7f9493929190613a40565b6020604051808303816000875af1925050508015610eba575060408051601f3d908101601f19168201909252610eb791810190613ae7565b60015b610ec657610aa9613b09565b80610ee457604051631e716a8b60e01b815260040160405180910390fd5b61012e859055600086815261012f6020526040902080546001600160801b031916426001600160801b031617905584600160405188907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b600054600290610100900460ff16158015610f6e575060005460ff8083169116105b610f8a5760405162461bcd60e51b815260040161068c90613c05565b6000805461013580546001600160a01b0319166001600160a01b03861617905561ff001961010060ff851661ffff19909316831717169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110425760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166110746129ff565b6001600160a01b03161461109a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166110bd57604051630103019560e11b815260040160405180910390fd5b6110c5612a1b565b61013180546001600160a01b038381166001600160a01b031983168117909355169081600161073e565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036111395760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661116b6129ff565b6001600160a01b0316146111915760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166111b457604051630103019560e11b815260040160405180910390fd5b604051600483028088833781810195865260209095019390935250506040909101902092915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112255760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112576129ff565b6001600160a01b03161461127d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166112a057604051630103019560e11b815260040160405180910390fd5b6112a985612851565b6101335461013454604051634d65479560e11b81526001600160a01b0390921691639aca8f2a916112f191899188918a9189918991600160a81b900460ff1690600401613c53565b60006040518083038186803b15801561130957600080fd5b505afa158015610b78573d6000803e3d6000fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113655760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166113976129ff565b6001600160a01b0316146113bd5760405162461bcd60e51b815260040161068c9061397c565b6113c681612a77565b604080516000808252602082019092526113e291839190612b1f565b50565b600054600190610100900460ff16158015611407575060005460ff8083169116105b6114235760405162461bcd60e51b815260040161068c90613c05565b6000805461ffff191660ff83161761010017905561143f612c8f565b61144886612cbe565b61146a57604051630220cee360e61b815260ff8716600482015260240161068c565b610134805460ff60a81b1916600160a81b60ff891602179055610e106101305561012e85905561013180546001600160a01b03199081166001600160a01b0387811691909117909255610132805482168684161790556101338054821685841617905560335461012d80549190931691161790556114e6612ce5565b6040805160ff88168152602081018790527fd1bcc66c061c32a21f569d138c2dadef4a38a0636309881954af5f44010ec1d8910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036115b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166115e76129ff565b6001600160a01b03161461160d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661163057604051630103019560e11b815260040160405180910390fd5b50610135546001600160a01b03165b90565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116a75760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166116d96129ff565b6001600160a01b0316146116ff5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661172257604051630103019560e11b815260040160405180910390fd5b61012e5482036117515750506040805160608101825261012e5481526000602082015260019181019190915290565b600082815261012f60205260408120546001600160801b0316908190036117ac5760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b610130546000906117c66001600160801b03841642613c8f565b604080516060810182528781526001600160801b039095166020860152911015908301525090505b919050565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361183d5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661186f6129ff565b6001600160a01b0316146118955760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff166118b857604051630103019560e11b815260040160405180910390fd5b506101305490565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119085760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661193a6129ff565b6001600160a01b0316146119605760405162461bcd60e51b815260040161068c9061397c565b61196982612a77565b61197582826001612b1f565b5050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119c35760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166119f56129ff565b6001600160a01b031614611a1b5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611a3e57604051630103019560e11b815260040160405180910390fd5b50610132546001600160a01b031690565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611aef5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161068c565b50600080516020613df483398151915290565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b4a5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b7c6129ff565b6001600160a01b031614611ba25760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611bc557604051630103019560e11b815260040160405180910390fd5b611bcd612a1b565b61013280546001600160a01b038381166001600160a01b031983168117909355169081600361073e565b611bff612a1b565b6040516377aeb0ad60e01b815260040160405180910390fd5b60655433906001600160a01b03168114611c865760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161068c565b6113e281612d1b565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611cd95760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d0b6129ff565b6001600160a01b031614611d315760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611d5457604051630103019560e11b815260040160405180910390fd5b60008989898989898989604051602001611d75989796959493929190613cd9565b60408051601f1981840301815291905280516020909101209a9950505050505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611de55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611e176129ff565b6001600160a01b031614611e3d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611e6057604051630103019560e11b815260040160405180910390fd5b60008686868686604051602001611e7b959493929190613d3d565b60408051601f198184030181529190528051602090910120979650505050505050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611ee85760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611f1a6129ff565b6001600160a01b031614611f405760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16611f6357604051630103019560e11b815260040160405180910390fd5b5061013454600160a81b900460ff1690565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611fbf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ff16129ff565b6001600160a01b0316146120175760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661203a57604051630103019560e11b815260040160405180910390fd5b50610131546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120955760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120c76129ff565b6001600160a01b0316146120ed5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661211057604051630103019560e11b815260040160405180910390fd5b612118612a1b565b61012d80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f5a674c516c196404869e5f502b5634ce442416bb016dde54b5de4c812cc019e690600090a392915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036121b55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166121e76129ff565b6001600160a01b03161461220d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661223057604051630103019560e11b815260040160405180910390fd5b612238612a1b565b61013580546001600160a01b038381166001600160a01b031983168117909355169081600261073e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122aa5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122dc6129ff565b6001600160a01b0316146123025760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661232557604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b031633146123535760405163472511eb60e11b815233600482015260240161068c565b61012e5488146123855761012e5460405163542fced960e11b815261068c918a91600401918252602082015260400190565b85841415806123945750858214155b156123b25760405163a0b1d72d60e01b815260040160405180910390fd5b60006123c489838a8a8a8a8a8a611c8f565b905060006123f27f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001836139c8565b61013254604051638a283fc360e01b8152600481018b90529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246691906139ea565b9050612475818d848e88612d34565b505050505050505050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036124cb5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166124fd6129ff565b6001600160a01b0316146125235760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661254657604051630103019560e11b815260040160405180910390fd5b61254e612a1b565b8060000361259e5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e0000000000604482015260640161068c565b610130805490829055604051829082907ff62a6f06fde00a303cd5939e6b53762854412c96a196cda26720cedd28af9e7090600090a35050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126225760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166126546129ff565b6001600160a01b03161461267a5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661269d57604051630103019560e11b815260040160405180910390fd5b5061012e5490565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036126ef5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127216129ff565b6001600160a01b0316146127475760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661276a57604051630103019560e11b815260040160405180910390fd5b5061012d546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036127c55760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166127f76129ff565b6001600160a01b03161461281d5760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661284057604051630103019560e11b815260040160405180910390fd5b50610133546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036128995760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166128cb6129ff565b6001600160a01b0316146128f15760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff1661291457604051630103019560e11b815260040160405180910390fd5b61012e5481146113e257600081815261012f60205260408120546001600160801b0316908190036129585760405163ddae3b7160e01b815260040160405180910390fd5b6101305461296f6001600160801b03831642613c8f565b111561197557604051631d739acf60e11b815260040160405180910390fd5b612996612a1b565b606580546001600160a01b0383166001600160a01b031990911681179091556129c76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080516020613df4833981519152546001600160a01b031690565b6033546001600160a01b03163314612a755760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161068c565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612abf5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612af16129ff565b6001600160a01b031614612b175760405162461bcd60e51b815260040161068c9061397c565b6113e2612a1b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612b5757612b528361302b565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bb1575060408051601f3d908101601f19168201909252612bae91810190613d73565b60015b612c145760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161068c565b600080516020613df48339815191528114612c835760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161068c565b50612b528383836130c7565b600054610100900460ff16612cb65760405162461bcd60e51b815260040161068c90613d8c565b612a756130f2565b60006010602060ff84168211801590612cdd57508060ff168460ff1611155b949350505050565b600054610100900460ff16612d0c5760405162461bcd60e51b815260040161068c90613d8c565b60fb805460ff19166001179055565b606580546001600160a01b03191690556113e281613129565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612d7c5760405162461bcd60e51b815260040161068c90613930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612dae6129ff565b6001600160a01b031614612dd45760405162461bcd60e51b815260040161068c9061397c565b60fb5460ff16612df757604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314612e255760405163472511eb60e11b815233600482015260240161068c565b6000604051806040016040528086600060088110612e4557612e45613a07565b6020020135815260200186600160088110612e6257612e62613a07565b6020020135905260408051608081018252878201359181019182529192506000919081906060820189600360200201358152508152602001604051806040016040528089600460088110612eb857612eb8613a07565b6020020135815260200189600560088110612ed557612ed5613a07565b60200201359052905260408051808201909152909150600090808860066020020135815260200188600760088110612f0f57612f0f613a07565b6020020135815250905060006040518060200160405280888152509050886001600160a01b03166343753b4d858585856040518563ffffffff1660e01b8152600401612f5e9493929190613a40565b6020604051808303816000875af1925050508015612f99575060408051601f3d908101601f19168201909252612f9691810190613ae7565b60015b612fa557610aa9613b09565b80612fc357604051631e716a8b60e01b815260040160405180910390fd5b61012e869055600087815261012f6020526040902080546001600160801b031916426001600160801b031617905585600260405189907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a450505050505050505050565b6001600160a01b0381163b6130985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161068c565b600080516020613df483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6130d08361317b565b6000825111806130dd5750805b15612b52576130ec83836131bb565b50505050565b600054610100900460ff166131195760405162461bcd60e51b815260040161068c90613d8c565b6131216132b1565b612a756132e0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6131848161302b565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6132235760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161068c565b600080846001600160a01b03168460405161323e9190613dd7565b600060405180830381855af49150503d8060008114613279576040519150601f19603f3d011682016040523d82523d6000602084013e61327e565b606091505b50915091506132a68282604051806060016040528060278152602001613e1460279139613307565b925050505b92915050565b600054610100900460ff166132d85760405162461bcd60e51b815260040161068c90613d8c565b612a75613320565b600054610100900460ff16612a755760405162461bcd60e51b815260040161068c90613d8c565b606083156133165750816117a5565b6117a58383613350565b600054610100900460ff166133475760405162461bcd60e51b815260040161068c90613d8c565b612a7533612d1b565b815115610ac85781518083602001fd5b6001600160a01b03811681146113e257600080fd5b60006020828403121561338757600080fd5b81356117a581613360565b8061010081018310156132ab57600080fd5b803563ffffffff811681146117ee57600080fd5b60008083601f8401126133ca57600080fd5b50813567ffffffffffffffff8111156133e257600080fd5b6020830191508360208260051b85010111156133fd57600080fd5b9250929050565b600080600080600080610180878903121561341e57600080fd5b6134288888613392565b9550610100870135945061343f61012088016133a4565b935061014087013567ffffffffffffffff81111561345c57600080fd5b61346889828a016133b8565b979a969950949794969561016090950135949350505050565b60008083601f84011261349357600080fd5b50813567ffffffffffffffff8111156134ab57600080fd5b6020830191508360208285010111156133fd57600080fd5b60008060008060008061018087890312156134dd57600080fd5b6134e78888613392565b95506134f661010088016133a4565b945061012087013567ffffffffffffffff81111561351357600080fd5b61351f89828a01613481565b979a96995097610140810135966101609091013595509350505050565b60008060008060006080868803121561355457600080fd5b853567ffffffffffffffff81111561356b57600080fd5b61357788828901613481565b9096509450506020860135925060408601359150613597606087016133a4565b90509295509295909350565b600080600080600061018086880312156135bc57600080fd5b853594506020860135935060408601359250606086013591506135978760808801613392565b600080600080600060a086880312156135fa57600080fd5b853560ff8116811461360b57600080fd5b945060208601359350604086013561362281613360565b9250606086013561363281613360565b9150608086013561364281613360565b809150509295509295909350565b60006020828403121561366257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff811182821017156136a5576136a5613669565b6040525050565b600080604083850312156136bf57600080fd5b82356136ca81613360565b915060208381013567ffffffffffffffff808211156136e857600080fd5b818601915086601f8301126136fc57600080fd5b81358181111561370e5761370e613669565b6040519150613726601f8201601f191685018361367f565b808252878482850101111561373a57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060008060008060008060a0898b03121561377457600080fd5b8835975060208901359650604089013567ffffffffffffffff8082111561379a57600080fd5b6137a68c838d016133b8565b909850965060608b01359150808211156137bf57600080fd5b6137cb8c838d016133b8565b909650945060808b01359150808211156137e457600080fd5b506137f18b828c016133b8565b999c989b5096995094979396929594505050565b60008060008060006080868803121561381d57600080fd5b613826866133a4565b94506020860135935060408601359250606086013567ffffffffffffffff81111561385057600080fd5b61385c888289016133b8565b969995985093965092949392505050565b60008060008060008060008060006101a08a8c03121561388c57600080fd5b6138968b8b613392565b98506101008a013597506101208a013567ffffffffffffffff808211156138bc57600080fd5b6138c88d838e016133b8565b90995097506101408c01359150808211156138e257600080fd5b6138ee8d838e016133b8565b90975095506101608c013591508082111561390857600080fd5b506139158c828d016133b8565b9a9d999c50979a969995989497966101800135949350505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6000826139e557634e487b7160e01b600052601260045260246000fd5b500690565b6000602082840312156139fc57600080fd5b81516117a581613360565b634e487b7160e01b600052603260045260246000fd5b8060005b60028110156130ec578151845260209384019390910190600101613a21565b6101208101613a4f8287613a1d565b60408083018660005b6002808210613a675750613aa2565b82518460005b83811015613a8b578251825260209283019290910190600101613a6d565b505050928401925060209190910190600101613a58565b50505050613ab360c0830185613a1d565b61010082018360005b6001811015613adb578151835260209283019290910190600101613abc565b50505095945050505050565b600060208284031215613af957600080fd5b815180151581146117a557600080fd5b600060033d111561163f5760046000803e5060005160e01c90565b600060443d1015613b325790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715613b6257505050505090565b8285019150815181811115613b7a5750505050505090565b843d8701016020828501011115613b945750505050505090565b613ba36020828601018761367f565b509095945050505050565b60005b83811015613bc9578181015183820152602001613bb1565b50506000910152565b6020815260008251806020840152613bf1816040850160208701613bae565b601f01601f19169190910160400192915050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006101a08201905087825286602083015285604083015284606083015261010084608084013760ff8316610180830152979650505050505050565b818103818111156132ab57634e487b7160e01b600052601160045260246000fd5b60006001600160fb1b03831115613cc657600080fd5b8260051b80838637939093019392505050565b888152600060208981840152604083018960005b8a811015613d165763ffffffff613d03836133a4565b1683529183019190830190600101613ced565b5050613d2d613d2682898b613cb0565b8688613cb0565b9c9b505050505050505050505050565b63ffffffff60e01b8660e01b1681528460048201528360248201526000613d68604483018486613cb0565b979650505050505050565b600060208284031215613d8557600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251613de9818460208701613bae565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202258b63db6550ae18ade93a6816c682fce5f6960e9619c49b1085dddff743c4364736f6c63430008150033", + "sourceMap": "443:11607:43:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37178:393:42;;;;;;;;;;-1:-1:-1;37178:393:42;;;;;:::i;:::-;;:::i;:::-;;17580:2498;;;;;;;;;;-1:-1:-1;17580:2498:42;;;;;:::i;:::-;;:::i;6380:2438:43:-;;;;;;;;;;-1:-1:-1;6380:2438:43;;;;;:::i;:::-;;:::i;3800:152::-;;;;;;;;;;-1:-1:-1;3800:152:43;;;;;:::i;:::-;;:::i;34738:423:42:-;;;;;;;;;;-1:-1:-1;34738:423:42;;;;;:::i;:::-;;:::i;11363:685:43:-;;;;;;;;;;-1:-1:-1;11363:685:43;;;;;:::i;:::-;;:::i;:::-;;;4125:25:80;;;4113:2;4098:18;11363:685:43;;;;;;;;40699:508:42;;;;;;;;;;-1:-1:-1;40699:508:42;;;;;:::i;:::-;;:::i;3317:197:23:-;;;;;;;;;;-1:-1:-1;3317:197:23;;;;;:::i;:::-;;:::i;13806:1014:42:-;;;;;;;;;;-1:-1:-1;13806:1014:42;;;;;:::i;:::-;;:::i;9156:228:43:-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;6024:32:80;;;6006:51;;5994:2;5979:18;9156:228:43;5860:203:80;32299:567:42;;;;;;;;;;-1:-1:-1;32299:567:42;;;;;:::i;:::-;;:::i;:::-;;;;6471:13:80;;6453:32;;6545:4;6533:17;;;6527:24;-1:-1:-1;;;;;6523:65:80;6501:20;;;6494:95;6647:17;;;6641:24;6634:32;6627:40;6605:20;;;6598:70;6441:2;6426:18;32299:567:42;6253:421:80;37747:189:42;;;;;;;;;;;;;:::i;3763:222:23:-;;;;;;:::i;:::-;;:::i;35454:227:42:-;;;;;;;;;;;;;:::i;3006:131:23:-;;;;;;;;;;;;;:::i;7130:120:42:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;7218:25:42;;;;;;;;;;;;;;;;;;;;7130:120;;36071:416;;;;;;;;;;-1:-1:-1;36071:416:42;;;;;:::i;:::-;;:::i;4649:109:44:-;;;;;;;;;;;;;:::i;2010:206:17:-;;;;;;;;;;;;;:::i;31089:465:42:-;;;;;;;;;;-1:-1:-1;31089:465:42;;;;;:::i;:::-;;:::i;29135:413::-;;;;;;;;;;-1:-1:-1;29135:413:42;;;;;:::i;:::-;;:::i;1441:85:18:-;;;;;;;;;;-1:-1:-1;1513:6:18;;-1:-1:-1;;;;;1513:6:18;1441:85;;38714:119:42;;;;;;;;;;;;;:::i;:::-;;;10258:4:80;10246:17;;;10228:36;;10216:2;10201:18;38714:119:42;10086:184:80;34179:231:42;;;;;;;;;;;;;:::i;39480:384::-;;;;;;;;;;-1:-1:-1;39480:384:42;;;;;:::i;:::-;;:::i;9704:418:43:-;;;;;;;;;;-1:-1:-1;9704:418:43;;;;;:::i;:::-;;:::i;22820:1590:42:-;;;;;;;;;;-1:-1:-1;22820:1590:42;;;;;:::i;:::-;;:::i;38168:402::-;;;;;;;;;;-1:-1:-1;38168:402:42;;;;;:::i;:::-;;:::i;31682:121::-;;;;;;;;;;;;;:::i;1123:99:17:-;;;;;;;;;;-1:-1:-1;1202:13:17;;-1:-1:-1;;;;;1202:13:17;1123:99;;39054:133:42;;;;;;;;;;;;;:::i;36670:205::-;;;;;;;;;;;;;:::i;33309:638::-;;;;;;;;;;-1:-1:-1;33309:638:42;;;;;:::i;:::-;;:::i;1415:178:17:-;;;;;;;;;;-1:-1:-1;1415:178:17;;;;;:::i;:::-;;:::i;37178:393:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;;;;;;;;;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;37378:17:42::3;::::0;;-1:-1:-1;;;;;37405:31:42;;::::3;-1:-1:-1::0;;;;;;37405:31:42;::::3;::::0;::::3;::::0;;;37378:17:::3;::::0;;37482:28:::3;37451:113;;::::0;::::3;::::0;;;::::3;37335:236;37178:393:::0;:::o;17580:2498::-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;17871:11:::3;;17860:7;:22;17856:95;;17928:11;::::0;17905:35:::3;::::0;-1:-1:-1;;;17905:35:42;;::::3;::::0;17919:7;;17905:35:::3;;12764:25:80::0;;;12820:2;12805:18;;12798:34;12752:2;12737:18;;12590:248;17856:95:42::3;18042:17;18062:112;18114:10;18126:7;18135:8;18145:19;;18062:38;:112::i;:::-;18042:132:::0;-1:-1:-1;18445:22:42::3;18470:39;4368:77;18042:132:::0;18470:39:::3;:::i;:::-;18639:23;::::0;:66:::3;::::0;-1:-1:-1;;;18639:66:42;;::::3;::::0;::::3;4125:25:80::0;;;18445:64:42;;-1:-1:-1;18593:31:42::3;::::0;-1:-1:-1;;;;;18639:23:42;;::::3;::::0;:38:::3;::::0;4098:18:80;;18639:66:42::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18593:112;;18774:17;-1:-1:-1::0;;;;;18774:29:42::3;;:267;;;;;;;;18818:14;18833:1;18818:17;;;;;;;:::i;:::-;;;;;18774:267;;;;18837:14;18852:1;18837:17;;;;;;;:::i;:::-;;;;;18774:267:::0;;::::3;::::0;;;;;;;18871:17;;::::3;;18774:267:::0;;::::3;::::0;;;;;;;;;18871:14;18905:1:::3;18890:17;;;;18774:267;;::::0;::::3;;;;;;;;;;;;18911:14;18926:1;18911:17;;;;;;;:::i;:::-;;;;;18774:267;;;;18930:14;18945:1;18930:17;;;;;;;:::i;:::-;;;;;18774:267:::0;;;;::::3;::::0;;;;::::3;::::0;;;;18964:14;18979:1:::3;18964:17;;;;18774:267;;;;18983:14;18998:1;18983:17;;;;;;;:::i;:::-;;;;;18774:267;;::::0;::::3;;;;;;;;19016:14;18774:267;;::::0;::::3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;18774:267:42::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;18774:267:42::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;18770:1302;;;;:::i;:::-;;;::::0;::::3;;;;;:::i;:::-;;;;;;;;19824:9;19817:17;;-1:-1:-1::0;;;19817:17:42::3;;;;;;;;:::i;18770:1302::-;;;20037:24;;-1:-1:-1::0;;;20037:24:42::3;;;;;;;;;;;18770:1302;19161:14;19156:85;;19202:24;;-1:-1:-1::0;;;19202:24:42::3;;;;;;;;;;;19156:85;19409:11;:22:::0;;;19577:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;19577:47:42::3;19608:15;-1:-1:-1::0;;;;;19577:47:42::3;;::::0;;19409:22;;19644:52:::3;::::0;19656:7;;19644:52:::3;::::0;;;::::3;19042:665;18770:1302;17846:2232;;;17580:2498:::0;;;;;;:::o;6380:2438:43:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;6665:11:43::3;;6654:7;:22;6650:95;;6722:11;::::0;6699:35:::3;::::0;-1:-1:-1;;;6699:35:43;;::::3;::::0;6713:7;;6699:35:::3;;12764:25:80::0;;;12820:2;12805:18;;12798:34;12752:2;12737:18;;12590:248;6650:95:43::3;6836:17;6868:87;6903:21;;6926:7;6935:8;6945:9;6868:34;:87::i;:::-;6836:119:::0;-1:-1:-1;7226:22:43::3;7251:39;4368:77:42;6836:119:43::0;7251:39:::3;:::i;:::-;7407:22;::::0;:48:::3;::::0;-1:-1:-1;;;7407:48:43;;17424:10:80;17412:23;;7407:48:43::3;::::0;::::3;17394:42:80::0;7226:64:43;;-1:-1:-1;7374:30:43::3;::::0;-1:-1:-1;;;;;7407:22:43;;::::3;::::0;:37:::3;::::0;17367:18:80;;7407:48:43::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7374:81;;7524:16;-1:-1:-1::0;;;;;7524:28:43::3;;:258;;;;;;;;7567:13;7581:1;7567:16;;;;;;;:::i;:::-;;;;;7524:258;;;;7585:13;7599:1;7585:16;;;;;;;:::i;:::-;;;;;7524:258:::0;;::::3;::::0;;;;;;;7618:16;;::::3;;7524:258:::0;;::::3;::::0;;;;;;;;;7618:13;7650:1:::3;7636:16;;;;7524:258;;::::0;::::3;;;;;;;;;;;;7656:13;7670:1;7656:16;;;;;;;:::i;:::-;;;;;7524:258;;;;7674:13;7688:1;7674:16;;;;;;;:::i;:::-;;;;;7524:258:::0;;;;::::3;::::0;;;;::::3;::::0;;;;7707:13;7721:1:::3;7707:16;;;;7524:258;;;;7725:13;7739:1;7725:16;;;;;;;:::i;:::-;;;;;7524:258;;::::0;::::3;;;;;;;;7757:14;7524:258;;::::0;::::3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;7524:258:43::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;7524:258:43::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;7520:1292;;;;:::i;:::-;7902:14;7897:85;;7943:24;;-1:-1:-1::0;;;7943:24:43::3;;;;;;;;;;;7897:85;8150:11;:22:::0;;;8318:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;8318:47:43::3;8349:15;-1:-1:-1::0;;;;;8318:47:43::3;;::::0;;8150:22;-1:-1:-1;8385:51:43::3;::::0;8397:7;;8385:51:::3;::::0;;;::::3;7783:664;6640:2178;;;6380:2438:::0;;;;;;:::o;3800:152::-;4871:13:22;;3886:1:43;;4871:13:22;;;;;4870:14;:40;;;;-1:-1:-1;4888:12:22;;:22;;;;:12;;:22;4870:40;4862:99;;;;-1:-1:-1;;;4862:99:22;;;;;;;:::i;:::-;4971:12;:22;;3899::43::1;:46:::0;;-1:-1:-1;;;;;;3899:46:43::1;-1:-1:-1::0;;;;;3899:46:43;::::1;;::::0;;-1:-1:-1;;4971:22:22;;;;-1:-1:-1;;5003:20:22;;;;;;5044:21;;;;5080:20;;10228:36:80;;;5080:20:22;;10216:2:80;10201:18;5080:20:22;;;;;;;3800:152:43;;:::o;34738:423:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;34954:23:42::3;::::0;;-1:-1:-1;;;;;34987:34:42;;::::3;-1:-1:-1::0;;;;;;34987:34:42;::::3;::::0;::::3;::::0;;;34954:23:::3;::::0;;;35036:118:::3;::::0;11363:685:43;11591:12;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;11663:4:43::2;11657:11;11719:1;11708:9;11704:17;11790:15;11760:28;11747:11;11734:72;11838:33:::0;;::::2;11884:28:::0;;;11949:2:::2;11932:20:::0;;::::2;11925:38:::0;;;;-1:-1:-1;;12011:2:43::2;12007:24:::0;;::::2;11984:48:::0;;;11363:685;-1:-1:-1;;11363:685:43:o;40699:508:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;40987:22:42::2;41004:4;40987:16;:22::i;:::-;41075:17;::::0;41181:9:::2;::::0;41075:125:::2;::::0;-1:-1:-1;;;41075:125:42;;-1:-1:-1;;;;;41075:17:42;;::::2;::::0;:29:::2;::::0;:125:::2;::::0;41118:4;;41124:13;;41139:10;;41151:21;;41174:5;;-1:-1:-1;;;41181:9:42;::::2;;;::::0;41075:125:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;3317:197:23::0;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;3400:36:::1;3418:17;3400;:36::i;:::-;3487:12;::::0;;3497:1:::1;3487:12:::0;;;::::1;::::0;::::1;::::0;;;3446:61:::1;::::0;3468:17;;3487:12;3446:21:::1;:61::i;:::-;3317:197:::0;:::o;13806:1014:42:-;4871:13:22;;14060:1:42;;4871:13:22;;;;;4870:14;:40;;;;-1:-1:-1;4888:12:22;;:22;;;;:12;;:22;4870:40;4862:99;;;;-1:-1:-1;;;4862:99:22;;;;;;;:::i;:::-;4971:12;:22;;-1:-1:-1;;5003:20:22;4971:22;;;5003:20;4971:22;5003:20;;;14148:16:42::1;:14;:16::i;:::-;14180:48;14217:10;14180:36;:48::i;:::-;14175:119;;14251:32;::::0;-1:-1:-1;;;14251:32:42;;10258:4:80;10246:17;;14251:32:42::1;::::0;::::1;10228:36:80::0;10201:18;;14251:32:42::1;10086:184:80::0;14175:119:42::1;14361:9;:22:::0;;-1:-1:-1;;;;14361:22:42::1;-1:-1:-1::0;;;14361:22:42::1;::::0;::::1;;;::::0;;14413:7:::1;14393:17;:27:::0;14430:11:::1;:25:::0;;;14465:23:::1;:50:::0;;-1:-1:-1;;;;;;14465:50:42;;::::1;-1:-1:-1::0;;;;;14465:50:42;;::::1;::::0;;;::::1;::::0;;;14525:23:::1;:47:::0;;;::::1;::::0;;::::1;;::::0;;14582:17:::1;:38:::0;;;::::1;::::0;;::::1;;::::0;;1513:6:18;;14630:17:42::1;:27:::0;;1513:6:18;;;;14630:27:42;::::1;;::::0;;14717:18:::1;:16;:18::i;:::-;14751:62;::::0;;18673:4:80;18661:17;;18643:36;;18710:2;18695:18;;18688:34;;;14751:62:42::1;::::0;18616:18:80;14751:62:42::1;;;;;;;5060:5:22::0;5044:21;;-1:-1:-1;;5044:21:22;;;5080:20;;10258:4:80;10246:17;;10228:36;;5080:20:22;;10216:2:80;10201:18;5080:20:22;;;;;;;13806:1014:42;;;;;;:::o;9156:228:43:-;9316:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;9354:22:43::2;::::0;-1:-1:-1;;;;;9354:22:43::2;1144:1:77;9156:228:43::0;:::o;32299:567:42:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;32478:11:42::2;;32470:4;:19:::0;32466:394:::2;;-1:-1:-1::0;;32512:30:42::2;::::0;;::::2;::::0;::::2;::::0;;32521:11:::2;::::0;32512:30;;-1:-1:-1;32512:30:42::2;::::0;::::2;::::0;32537:4:::2;32512:30:::0;;;;;;;;32299:567::o;32466:394::-:2;32573:21;32597:17:::0;;;:11:::2;:17;::::0;;;;;-1:-1:-1;;;;;32597:17:42::2;::::0;32633:18;;;32629:78:::2;;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;;;;;7218:25:42;;;;;;;;;;;;;;;;;;;;32678:14:::2;32671:21:::0;32299:567;-1:-1:-1;;;32299:567:42:o;32629:78::-:2;32772:17;::::0;32721:12:::2;::::0;32738:31:::2;-1:-1:-1::0;;;;;32738:31:42;::::2;:15;:31;:::i;:::-;32811:38;::::0;;::::2;::::0;::::2;::::0;;;;;-1:-1:-1;;;;;32811:38:42;;::::2;;::::0;::::2;::::0;32738:51;-1:-1:-1;32736:54:42::2;32811:38:::0;;;;-1:-1:-1;32811:38:42;-1:-1:-1;32466:394:42::2;32299:567:::0;;;:::o;37747:189::-;37882:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;37912:17:42::2;::::0;37747:189;:::o;3763:222:23:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;3880:36:::1;3898:17;3880;:36::i;:::-;3926:52;3948:17;3967:4;3973;3926:21;:52::i;:::-;3763:222:::0;;:::o;35454:227:42:-;35612:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;35650:23:42::2;::::0;-1:-1:-1;;;;;35650:23:42::2;35454:227:::0;:::o;3006:131:23:-;3084:7;2324:4;-1:-1:-1;;;;;2333:6:23;2316:23;;2308:92;;;;-1:-1:-1;;;2308:92:23;;19165:2:80;2308:92:23;;;19147:21:80;19204:2;19184:18;;;19177:30;19243:34;19223:18;;;19216:62;19314:26;19294:18;;;19287:54;19358:19;;2308:92:23;18963:420:80;2308:92:23;-1:-1:-1;;;;;;;;;;;;3006:131:23;:::o;36071:416:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;36283:23:42::3;::::0;;-1:-1:-1;;;;;36316:34:42;;::::3;-1:-1:-1::0;;;;;;36316:34:42;::::3;::::0;::::3;::::0;;;36283:23:::3;::::0;;36396:36:::3;36365:115;::::0;4649:109:44;1334:13:18;:11;:13::i;:::-;4726:25:44::1;;-1:-1:-1::0;;;4726:25:44::1;;;;;;;;;;;2010:206:17::0;1202:13;;929:10:25;;-1:-1:-1;;;;;1202:13:17;2103:24;;2095:78;;;;-1:-1:-1;;;2095:78:17;;19590:2:80;2095:78:17;;;19572:21:80;19629:2;19609:18;;;19602:30;19668:34;19648:18;;;19641:62;-1:-1:-1;;;19719:18:80;;;19712:39;19768:19;;2095:78:17;19388:405:80;2095:78:17;2183:26;2202:6;2183:18;:26::i;31089:465:42:-;31366:12;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;31390:24:42::2;31446:7;31455:8;31465:11;;31478:13;;31493;;31429:78;;;;;;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;31429:78:42;;::::2;::::0;;;;;;31525:22;;31429:78:::2;31525:22:::0;;::::2;::::0;;31089:465;-1:-1:-1;;;;;;;;;;31089:465:42:o;29135:413::-;29370:12;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;29394:24:42::2;29450:10;29462:7;29471:8;29481:19;;29433:68;;;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;29433:68:42;;::::2;::::0;;;;;;29519:22;;29433:68:::2;29519:22:::0;;::::2;::::0;;29135:413;-1:-1:-1;;;;;;;29135:413:42:o;38714:119::-;38793:5;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;38817:9:42::2;::::0;-1:-1:-1;;;38817:9:42;::::2;;;::::0;38714:119::o;34179:231::-;34341:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;34379:23:42::2;::::0;-1:-1:-1;;;;;34379:23:42::2;34179:231:::0;:::o;39480:384::-;39646:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;39691:17:42::3;::::0;;-1:-1:-1;;;;;39718:39:42;;::::3;-1:-1:-1::0;;;;;;39718:39:42;::::3;::::0;::::3;::::0;;;39772:57:::3;::::0;39691:17;::::3;::::0;39718:39;39691:17;;39772:57:::3;::::0;39669:19:::3;::::0;39772:57:::3;39846:11:::0;39480:384;-1:-1:-1;;39480:384:42:o;9704:418:43:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;9918:22:43::3;::::0;;-1:-1:-1;;;;;9950:33:43;;::::3;-1:-1:-1::0;;;;;;9950:33:43;::::3;::::0;::::3;::::0;;;9918:22:::3;::::0;;10029:38:::3;9998:117;::::0;22820:1590:42;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;23154:11:::3;;23143:7;:22;23139:95;;23211:11;::::0;23188:35:::3;::::0;-1:-1:-1;;;23188:35:42;;::::3;::::0;23202:7;;23188:35:::3;;12764:25:80::0;;;12820:2;12805:18;;12798:34;12752:2;12737:18;;12590:248;23139:95:42::3;23322:42:::0;;::::3;;::::0;:88:::3;;-1:-1:-1::0;23368:42:42;;::::3;;23322:88;23305:172;;;23442:24;;-1:-1:-1::0;;;23442:24:42::3;;;;;;;;;;;23305:172;23564:17;23584:116;23630:7;23639:8;23649:11;;23662:13;;23677;;23584:32;:116::i;:::-;23564:136:::0;-1:-1:-1;23971:24:42::3;23998:39;4368:77;23564:136:::0;23998:39:::3;:::i;:::-;24152:23;::::0;:58:::3;::::0;-1:-1:-1;;;24152:58:42;;::::3;::::0;::::3;4125:25:80::0;;;23971:66:42;;-1:-1:-1;24121:28:42::3;::::0;-1:-1:-1;;;;;24152:23:42;;::::3;::::0;:38:::3;::::0;4098:18:80;;24152:58:42::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24121:89;;24316:87;24338:14;24354:11;24367:16;24385:7;24394:8;24316:21;:87::i;:::-;23129:1281;;;22820:1590:::0;;;;;;;;;:::o;38168:402::-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;1334:13:18::2;:11;:13::i;:::-;38330::42::3;38347:1;38330:18:::0;38326:86:::3;;38364:37;::::0;-1:-1:-1;;;38364:37:42;;21716:2:80;38364:37:42::3;::::0;::::3;21698:21:80::0;21755:2;21735:18;;;21728:30;21794:29;21774:18;;;21767:57;21841:18;;38364:37:42::3;21514:351:80::0;38326:86:42::3;38441:17;::::0;;38468:33;;;;38517:46:::3;::::0;38488:13;;38441:17;;38517:46:::3;::::0;38421:17:::3;::::0;38517:46:::3;38316:254;38168:402:::0;:::o;31682:121::-;31759:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;31785:11:42::2;::::0;31682:121;:::o;39054:133::-;39137:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;39163:17:42::2;::::0;-1:-1:-1;;;;;39163:17:42::2;39054:133:::0;:::o;36670:205::-;36812:7;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;-1:-1:-1::0;36850:17:42::2;::::0;-1:-1:-1;;;;;36850:17:42::2;36670:205:::0;:::o;33309:638::-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;33461:11:42::2;::::0;33449:56;;33488:7:::2;33449:56;33580:21;33604:17:::0;;;:11:::2;:17;::::0;;;;;-1:-1:-1;;;;;33604:17:42::2;::::0;33704:18;;;33700:73:::2;;33745:17;;-1:-1:-1::0;;;33745:17:42::2;;;;;;;;;;;33700:73;33877:17;::::0;33843:31:::2;-1:-1:-1::0;;;;;33843:31:42;::::2;:15;:31;:::i;:::-;:51;33839:102;;;33917:13;;-1:-1:-1::0;;;33917:13:42::2;;;;;;;;;;;1415:178:17::0;1334:13:18;:11;:13::i;:::-;1504::17::1;:24:::0;;-1:-1:-1;;;;;1504:24:17;::::1;-1:-1:-1::0;;;;;;1504:24:17;;::::1;::::0;::::1;::::0;;;1568:7:::1;1513:6:18::0;;-1:-1:-1;;;;;1513:6:18;;1441:85;1568:7:17::1;-1:-1:-1::0;;;;;1543:43:17::1;;;;;;;;;;;1415:178:::0;:::o;1563:151:20:-;-1:-1:-1;;;;;;;;;;;1642:65:20;-1:-1:-1;;;;;1642:65:20;;1563:151::o;1599:130:18:-;1513:6;;-1:-1:-1;;;;;1513:6:18;929:10:25;1662:23:18;1654:68;;;;-1:-1:-1;;;1654:68:18;;22072:2:80;1654:68:18;;;22054:21:80;;;22091:18;;;22084:30;22150:34;22130:18;;;22123:62;22202:18;;1654:68:18;21870:356:80;1654:68:18;1599:130::o;4067:204:44:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1334:13:18::1;:11;:13::i;2938:974:20:-:0;951:66;3384:59;;;3380:526;;;3459:37;3478:17;3459:18;:37::i;:::-;2938:974;;;:::o;3380:526::-;3560:17;-1:-1:-1;;;;;3531:61:20;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3531:63:20;;;;;;;;-1:-1:-1;;3531:63:20;;;;;;;;;;;;:::i;:::-;;;3527:302;;3758:56;;-1:-1:-1;;;3758:56:20;;22622:2:80;3758:56:20;;;22604:21:80;22661:2;22641:18;;;22634:30;22700:34;22680:18;;;22673:62;-1:-1:-1;;;22751:18:80;;;22744:44;22805:19;;3758:56:20;22420:410:80;3527:302:20;-1:-1:-1;;;;;;;;;;;3644:28:20;;3636:82;;;;-1:-1:-1;;;3636:82:20;;23037:2:80;3636:82:20;;;23019:21:80;23076:2;23056:18;;;23049:30;23115:34;23095:18;;;23088:62;-1:-1:-1;;;23166:18:80;;;23159:39;23215:19;;3636:82:20;22835:405:80;3636:82:20;3595:138;3842:53;3860:17;3879:4;3885:9;3842:17;:53::i;15154:97:42:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;15224:20:42::1;:18;:20::i;434:207:78:-:0;492:19;540:2;569;588:21;;;;-1:-1:-1;588:21:78;;;:46;;;626:8;613:21;;:9;:21;;;;588:46;581:53;434:207;-1:-1:-1;;;;434:207:78:o;794:90:77:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;858:12:77::1;:19:::0;;-1:-1:-1;;858:19:77::1;873:4;858:19;::::0;;794:90::o;1777:153:17:-;1866:13;1859:20;;-1:-1:-1;;;;;;1859:20:17;;;1889:34;1914:8;1889:24;:34::i;26242:1763:42:-;-1:-1:-1;;;;;1898:6:23;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:23;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:23;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:23;;1963:87;;;;-1:-1:-1;;;1963:87:23;;;;;;;:::i;:::-;1059:12:77::1;::::0;::::1;;1054:81;;1094:30;;-1:-1:-1::0;;;1094:30:77::1;;;;;;;;;;;1054:81;41750:17:42::2;::::0;-1:-1:-1;;;;;41750:17:42::2;41736:10;:31;41732:93;;41790:24;::::0;-1:-1:-1;;;41790:24:42;;41803:10:::2;41790:24;::::0;::::2;6006:51:80::0;5979:18;;41790:24:42::2;5860:203:80::0;41732:93:42::2;26566:20:::3;:55;;;;;;;;26590:11;26602:1;26590:14;;;;;;;:::i;:::-;;;;;26566:55;;;;26606:11;26618:1;26606:14;;;;;;;:::i;:::-;;;;;26566:55:::0;;26631:106:::3;::::0;;;;;;;26671:14;;::::3;;26631:106:::0;;::::3;::::0;;;26566:55;;-1:-1:-1;;;26631:106:42;;;;;;26671:11;26699:1:::3;26687:14;;;;26631:106;;::::0;::::3;;;;;;;;;;;;26705:11;26717:1;26705:14;;;;;;;:::i;:::-;;;;;26631:106;;;;26721:11;26733:1;26721:14;;;;;;;:::i;:::-;;;;;26631:106:::0;;;;26747:56:::3;::::0;;;;::::3;::::0;;;26631:106;;-1:-1:-1;26747:21:42::3;::::0;:56;26772:11;26784:1:::3;26772:14;;;;26747:56;;;;26788:11;26800:1;26788:14;;;;;;;:::i;:::-;;;;;26747:56;;::::0;::::3;;26813:28;:42;;;;;;;;26845:9;26813:42;;::::0;::::3;;26920:14;-1:-1:-1::0;;;;;26920:26:42::3;;26947:2;26951;26955:3;26960:10;26920:51;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;26920:51:42::3;::::0;;::::3;;::::0;;::::3;-1:-1:-1::0;;26920:51:42::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;::::3;:::i;:::-;;;26916:1083;;;;:::i;:::-;27091:14;27086:85;;27132:24;;-1:-1:-1::0;;;27132:24:42::3;;;;;;;;;;;27086:85;27339:11;:22:::0;;;27507:20:::3;::::0;;;:11:::3;:20;::::0;;;;:47;;-1:-1:-1;;;;;;27507:47:42::3;27538:15;-1:-1:-1::0;;;;;27507:47:42::3;;::::0;;27339:22;27595:17:::3;27574:49;::::0;27586:7;;27574:49:::3;::::0;;;::::3;26972:662;26500:1505;;;;26242:1763:::0;;;;;:::o;1805:281:20:-;-1:-1:-1;;;;;1476:19:24;;;1878:106:20;;;;-1:-1:-1;;;1878:106:20;;23859:2:80;1878:106:20;;;23841:21:80;23898:2;23878:18;;;23871:30;23937:34;23917:18;;;23910:62;-1:-1:-1;;;23988:18:80;;;23981:43;24041:19;;1878:106:20;23657:409:80;1878:106:20;-1:-1:-1;;;;;;;;;;;1994:85:20;;-1:-1:-1;;;;;;1994:85:20;-1:-1:-1;;;;;1994:85:20;;;;;;;;;;1805:281::o;2478:288::-;2616:29;2627:17;2616:10;:29::i;:::-;2673:1;2659:4;:11;:15;:28;;;;2678:9;2659:28;2655:105;;;2703:46;2725:17;2744:4;2703:21;:46::i;:::-;;2478:288;;;:::o;3048:131:44:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;3122:16:44::1;:14;:16::i;:::-;3148:24;:22;:24::i;2673:187:18:-:0;2765:6;;;-1:-1:-1;;;;;2781:17:18;;;-1:-1:-1;;;;;;2781:17:18;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2736:124;2673:187;:::o;2192:152:20:-;2258:37;2277:17;2258:18;:37::i;:::-;2310:27;;-1:-1:-1;;;;;2310:27:20;;;;;;;;2192:152;:::o;7088:455::-;7171:12;-1:-1:-1;;;;;1476:19:24;;;7195:88:20;;;;-1:-1:-1;;;7195:88:20;;24273:2:80;7195:88:20;;;24255:21:80;24312:2;24292:18;;;24285:30;24351:34;24331:18;;;24324:62;-1:-1:-1;;;24402:18:80;;;24395:36;24448:19;;7195:88:20;24071:402:80;7195:88:20;7354:12;7368:23;7395:6;-1:-1:-1;;;;;7395:19:20;7415:4;7395:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7353:67;;;;7437:99;7473:7;7482:10;7437:99;;;;;;;;;;;;;;;;;:35;:99::i;:::-;7430:106;;;;7088:455;;;;;:::o;1003:95:18:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;1065:26:18::1;:24;:26::i;1042:67:23:-:0;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;7438:295:24:-;7584:12;7612:7;7608:119;;;-1:-1:-1;7642:10:24;7635:17;;7608:119;7683:33;7691:10;7703:12;7683:7;:33::i;1104:111:18:-;5363:13:22;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:22;;;;;;;:::i;:::-;1176:32:18::1;929:10:25::0;1176:18:18::1;:32::i;7739:540:24:-:0;7898:17;;:21;7894:379;;8126:10;8120:17;8182:15;8169:10;8165:2;8161:19;8154:44;14:151:80;-1:-1:-1;;;;;109:31:80;;99:42;;89:70;;155:1;152;145:12;170:295;257:6;310:2;298:9;289:7;285:23;281:32;278:52;;;326:1;323;316:12;278:52;365:9;352:23;384:51;429:5;384:51;:::i;470:160::-;564:6;597:3;585:16;;582:25;-1:-1:-1;579:45:80;;;620:1;617;610:12;635:163;702:20;;762:10;751:22;;741:33;;731:61;;788:1;785;778:12;803:367;866:8;876:6;930:3;923:4;915:6;911:17;907:27;897:55;;948:1;945;938:12;897:55;-1:-1:-1;971:20:80;;1014:18;1003:30;;1000:50;;;1046:1;1043;1036:12;1000:50;1083:4;1075:6;1071:17;1059:29;;1143:3;1136:4;1126:6;1123:1;1119:14;1111:6;1107:27;1103:38;1100:47;1097:67;;;1160:1;1157;1150:12;1097:67;803:367;;;;;:::o;1175:773::-;1321:6;1329;1337;1345;1353;1361;1414:3;1402:9;1393:7;1389:23;1385:33;1382:53;;;1431:1;1428;1421:12;1382:53;1454;1499:7;1488:9;1454:53;:::i;:::-;1444:63;;1554:3;1543:9;1539:19;1526:33;1516:43;;1578:38;1611:3;1600:9;1596:19;1578:38;:::i;:::-;1568:48;;1667:3;1656:9;1652:19;1639:33;1695:18;1687:6;1684:30;1681:50;;;1727:1;1724;1717:12;1681:50;1766:70;1828:7;1819:6;1808:9;1804:22;1766:70;:::i;:::-;1175:773;;;;-1:-1:-1;1175:773:80;;;;;1937:3;1922:19;;;1909:33;;1175:773;-1:-1:-1;;;;1175:773:80:o;1953:347::-;2004:8;2014:6;2068:3;2061:4;2053:6;2049:17;2045:27;2035:55;;2086:1;2083;2076:12;2035:55;-1:-1:-1;2109:20:80;;2152:18;2141:30;;2138:50;;;2184:1;2181;2174:12;2138:50;2221:4;2213:6;2209:17;2197:29;;2273:3;2266:4;2257:6;2249;2245:19;2241:30;2238:39;2235:59;;;2290:1;2287;2280:12;2305:745;2435:6;2443;2451;2459;2467;2475;2528:3;2516:9;2507:7;2503:23;2499:33;2496:53;;;2545:1;2542;2535:12;2496:53;2568;2613:7;2602:9;2568:53;:::i;:::-;2558:63;;2640:38;2673:3;2662:9;2658:19;2640:38;:::i;:::-;2630:48;;2729:3;2718:9;2714:19;2701:33;2757:18;2749:6;2746:30;2743:50;;;2789:1;2786;2779:12;2743:50;2828:58;2878:7;2869:6;2858:9;2854:22;2828:58;:::i;:::-;2305:745;;;;-1:-1:-1;2905:8:80;2987:3;2972:19;;2959:33;;3039:3;3024:19;;;3011:33;;-1:-1:-1;2305:745:80;-1:-1:-1;;;;2305:745:80:o;3356:618::-;3452:6;3460;3468;3476;3484;3537:3;3525:9;3516:7;3512:23;3508:33;3505:53;;;3554:1;3551;3544:12;3505:53;3594:9;3581:23;3627:18;3619:6;3616:30;3613:50;;;3659:1;3656;3649:12;3613:50;3698:58;3748:7;3739:6;3728:9;3724:22;3698:58;:::i;:::-;3775:8;;-1:-1:-1;3672:84:80;-1:-1:-1;;3857:2:80;3842:18;;3829:32;;-1:-1:-1;3908:2:80;3893:18;;3880:32;;-1:-1:-1;3931:37:80;3964:2;3949:18;;3931:37;:::i;:::-;3921:47;;3356:618;;;;;;;;:::o;4161:509::-;4281:6;4289;4297;4305;4313;4366:3;4354:9;4345:7;4341:23;4337:33;4334:53;;;4383:1;4380;4373:12;4334:53;4419:9;4406:23;4396:33;;4476:2;4465:9;4461:18;4448:32;4438:42;;4527:2;4516:9;4512:18;4499:32;4489:42;;4578:2;4567:9;4563:18;4550:32;4540:42;;4601:63;4656:7;4650:3;4639:9;4635:19;4601:63;:::i;4947:908::-;5126:6;5134;5142;5150;5158;5211:3;5199:9;5190:7;5186:23;5182:33;5179:53;;;5228:1;5225;5218:12;5179:53;5267:9;5254:23;5317:4;5310:5;5306:16;5299:5;5296:27;5286:55;;5337:1;5334;5327:12;5286:55;5360:5;-1:-1:-1;5412:2:80;5397:18;;5384:32;;-1:-1:-1;5468:2:80;5453:18;;5440:32;5481:53;5440:32;5481:53;:::i;:::-;5553:7;-1:-1:-1;5612:2:80;5597:18;;5584:32;5625:53;5584:32;5625:53;:::i;:::-;5697:7;-1:-1:-1;5756:3:80;5741:19;;5728:33;5770:53;5728:33;5770:53;:::i;:::-;5842:7;5832:17;;;4947:908;;;;;;;;:::o;6068:180::-;6127:6;6180:2;6168:9;6159:7;6155:23;6151:32;6148:52;;;6196:1;6193;6186:12;6148:52;-1:-1:-1;6219:23:80;;6068:180;-1:-1:-1;6068:180:80:o;6861:127::-;6922:10;6917:3;6913:20;6910:1;6903:31;6953:4;6950:1;6943:15;6977:4;6974:1;6967:15;6993:249;7103:2;7084:13;;-1:-1:-1;;7080:27:80;7068:40;;7138:18;7123:34;;7159:22;;;7120:62;7117:88;;;7185:18;;:::i;:::-;7221:2;7214:22;-1:-1:-1;;6993:249:80:o;7247:953::-;7324:6;7332;7385:2;7373:9;7364:7;7360:23;7356:32;7353:52;;;7401:1;7398;7391:12;7353:52;7440:9;7427:23;7459:51;7504:5;7459:51;:::i;:::-;7529:5;-1:-1:-1;7553:2:80;7591:18;;;7578:32;7629:18;7659:14;;;7656:34;;;7686:1;7683;7676:12;7656:34;7724:6;7713:9;7709:22;7699:32;;7769:7;7762:4;7758:2;7754:13;7750:27;7740:55;;7791:1;7788;7781:12;7740:55;7827:2;7814:16;7849:2;7845;7842:10;7839:36;;;7855:18;;:::i;:::-;7904:2;7898:9;;-1:-1:-1;7916:65:80;7971:2;7952:13;;-1:-1:-1;;7948:27:80;7944:36;;7898:9;7916:65;:::i;:::-;8005:2;7997:6;7990:18;8045:7;8040:2;8035;8031;8027:11;8023:20;8020:33;8017:53;;;8066:1;8063;8056:12;8017:53;8122:2;8117;8113;8109:11;8104:2;8096:6;8092:15;8079:46;8167:1;8162:2;8157;8149:6;8145:15;8141:24;8134:35;;8188:6;8178:16;;;;;7247:953;;;;;:::o;8205:1225::-;8380:6;8388;8396;8404;8412;8420;8428;8436;8489:3;8477:9;8468:7;8464:23;8460:33;8457:53;;;8506:1;8503;8496:12;8457:53;8542:9;8529:23;8519:33;;8599:2;8588:9;8584:18;8571:32;8561:42;;8654:2;8643:9;8639:18;8626:32;8677:18;8718:2;8710:6;8707:14;8704:34;;;8734:1;8731;8724:12;8704:34;8773:70;8835:7;8826:6;8815:9;8811:22;8773:70;:::i;:::-;8862:8;;-1:-1:-1;8747:96:80;-1:-1:-1;8950:2:80;8935:18;;8922:32;;-1:-1:-1;8966:16:80;;;8963:36;;;8995:1;8992;8985:12;8963:36;9034:72;9098:7;9087:8;9076:9;9072:24;9034:72;:::i;:::-;9125:8;;-1:-1:-1;9008:98:80;-1:-1:-1;9213:3:80;9198:19;;9185:33;;-1:-1:-1;9230:16:80;;;9227:36;;;9259:1;9256;9249:12;9227:36;;9298:72;9362:7;9351:8;9340:9;9336:24;9298:72;:::i;:::-;8205:1225;;;;-1:-1:-1;8205:1225:80;;-1:-1:-1;8205:1225:80;;;;;;9389:8;-1:-1:-1;;;8205:1225:80:o;9435:646::-;9547:6;9555;9563;9571;9579;9632:3;9620:9;9611:7;9607:23;9603:33;9600:53;;;9649:1;9646;9639:12;9600:53;9672:28;9690:9;9672:28;:::i;:::-;9662:38;;9747:2;9736:9;9732:18;9719:32;9709:42;;9798:2;9787:9;9783:18;9770:32;9760:42;;9853:2;9842:9;9838:18;9825:32;9880:18;9872:6;9869:30;9866:50;;;9912:1;9909;9902:12;9866:50;9951:70;10013:7;10004:6;9993:9;9989:22;9951:70;:::i;:::-;9435:646;;;;-1:-1:-1;9435:646:80;;-1:-1:-1;10040:8:80;;9925:96;9435:646;-1:-1:-1;;;9435:646:80:o;10275:1352::-;10484:6;10492;10500;10508;10516;10524;10532;10540;10548;10601:3;10589:9;10580:7;10576:23;10572:33;10569:53;;;10618:1;10615;10608:12;10569:53;10641;10686:7;10675:9;10641:53;:::i;:::-;10631:63;;10741:3;10730:9;10726:19;10713:33;10703:43;;10797:3;10786:9;10782:19;10769:33;10821:18;10862:2;10854:6;10851:14;10848:34;;;10878:1;10875;10868:12;10848:34;10917:70;10979:7;10970:6;10959:9;10955:22;10917:70;:::i;:::-;11006:8;;-1:-1:-1;10891:96:80;-1:-1:-1;11094:3:80;11079:19;;11066:33;;-1:-1:-1;11111:16:80;;;11108:36;;;11140:1;11137;11130:12;11108:36;11179:72;11243:7;11232:8;11221:9;11217:24;11179:72;:::i;:::-;11270:8;;-1:-1:-1;11153:98:80;-1:-1:-1;11358:3:80;11343:19;;11330:33;;-1:-1:-1;11375:16:80;;;11372:36;;;11404:1;11401;11394:12;11372:36;;11443:72;11507:7;11496:8;11485:9;11481:24;11443:72;:::i;:::-;10275:1352;;;;-1:-1:-1;10275:1352:80;;;;;;;;11534:8;11616:3;11601:19;11588:33;;10275:1352;-1:-1:-1;;;;10275:1352:80:o;11632:408::-;11834:2;11816:21;;;11873:2;11853:18;;;11846:30;11912:34;11907:2;11892:18;;11885:62;-1:-1:-1;;;11978:2:80;11963:18;;11956:42;12030:3;12015:19;;11632:408::o;12045:::-;12247:2;12229:21;;;12286:2;12266:18;;;12259:30;12325:34;12320:2;12305:18;;12298:62;-1:-1:-1;;;12391:2:80;12376:18;;12369:42;12443:3;12428:19;;12045:408::o;12843:209::-;12875:1;12901;12891:132;;12945:10;12940:3;12936:20;12933:1;12926:31;12980:4;12977:1;12970:15;13008:4;13005:1;12998:15;12891:132;-1:-1:-1;13037:9:80;;12843:209::o;13057:294::-;13150:6;13203:2;13191:9;13182:7;13178:23;13174:32;13171:52;;;13219:1;13216;13209:12;13171:52;13251:9;13245:16;13270:51;13315:5;13270:51;:::i;13356:127::-;13417:10;13412:3;13408:20;13405:1;13398:31;13448:4;13445:1;13438:15;13472:4;13469:1;13462:15;13488:326;13581:5;13604:1;13614:194;13628:4;13625:1;13622:11;13614:194;;;13687:13;;13675:26;;13724:4;13748:12;;;;13783:15;;;;13648:1;13641:9;13614:194;;13819:1627;14267:3;14252:19;;14280:43;14256:9;14305:6;14280:43;:::i;:::-;14342:2;14379;14368:9;14364:18;14424:6;14448:1;14458:586;14522:4;14555:2;14552:1;14549:9;14539:30;;14562:5;;;14539:30;14592:13;;14631:3;14714:1;14728:234;14744:2;14739:3;14736:11;14728:234;;;14815:15;;14801:30;;14858:4;14931:17;;;;14888:14;;;;14766:1;14757:11;14728:234;;;-1:-1:-1;;;14982:12:80;;;;-1:-1:-1;15029:4:80;15017:17;;;;;14485:1;14478:9;14458:586;;;14462:3;;;;15053:53;15101:3;15090:9;15086:19;15078:6;15053:53;:::i;:::-;15143:3;15132:9;15128:19;15195:6;15221:1;15231:209;15247:1;15242:3;15239:10;15231:209;;;15309:15;;15295:30;;15348:4;15374:14;;;;15413:17;;;;15268:1;15259:11;15231:209;;;15235:3;;;13819:1627;;;;;;;:::o;15451:277::-;15518:6;15571:2;15559:9;15550:7;15546:23;15542:32;15539:52;;;15587:1;15584;15577:12;15539:52;15619:9;15613:16;15672:5;15665:13;15658:21;15651:5;15648:32;15638:60;;15694:1;15691;15684:12;15733:179;15768:3;15810:1;15792:16;15789:23;15786:120;;;15856:1;15853;15850;15835:23;-1:-1:-1;15893:1:80;15887:8;15882:3;15878:18;15733:179;:::o;15917:671::-;15956:3;15998:4;15980:16;15977:26;15974:39;;;15917:671;:::o;15974:39::-;16040:2;16034:9;-1:-1:-1;;16105:16:80;16101:25;;16098:1;16034:9;16077:50;16156:4;16150:11;16180:16;16215:18;16286:2;16279:4;16271:6;16267:17;16264:25;16259:2;16251:6;16248:14;16245:45;16242:58;;;16293:5;;;;;15917:671;:::o;16242:58::-;16330:6;16324:4;16320:17;16309:28;;16366:3;16360:10;16393:2;16385:6;16382:14;16379:27;;;16399:5;;;;;;15917:671;:::o;16379:27::-;16483:2;16464:16;16458:4;16454:27;16450:36;16443:4;16434:6;16429:3;16425:16;16421:27;16418:69;16415:82;;;16490:5;;;;;;15917:671;:::o;16415:82::-;16506:57;16557:4;16548:6;16540;16536:19;16532:30;16526:4;16506:57;:::i;:::-;-1:-1:-1;16579:3:80;;15917:671;-1:-1:-1;;;;;15917:671:80:o;16593:250::-;16678:1;16688:113;16702:6;16699:1;16696:13;16688:113;;;16778:11;;;16772:18;16759:11;;;16752:39;16724:2;16717:10;16688:113;;;-1:-1:-1;;16835:1:80;16817:16;;16810:27;16593:250::o;16848:396::-;16997:2;16986:9;16979:21;16960:4;17029:6;17023:13;17072:6;17067:2;17056:9;17052:18;17045:34;17088:79;17160:6;17155:2;17144:9;17140:18;17135:2;17127:6;17123:15;17088:79;:::i;:::-;17228:2;17207:15;-1:-1:-1;;17203:29:80;17188:45;;;;17235:2;17184:54;;16848:396;-1:-1:-1;;16848:396:80:o;17447:410::-;17649:2;17631:21;;;17688:2;17668:18;;;17661:30;17727:34;17722:2;17707:18;;17700:62;-1:-1:-1;;;17793:2:80;17778:18;;17771:44;17847:3;17832:19;;17447:410::o;17862:606::-;18140:4;18182:3;18171:9;18167:19;18159:27;;18213:6;18202:9;18195:25;18256:6;18251:2;18240:9;18236:18;18229:34;18299:6;18294:2;18283:9;18279:18;18272:34;18342:6;18337:2;18326:9;18322:18;18315:34;18400:6;18392;18386:3;18375:9;18371:19;18358:49;18456:4;18448:6;18444:17;18438:3;18427:9;18423:19;18416:46;17862:606;;;;;;;;;:::o;18733:225::-;18800:9;;;18821:11;;;18818:134;;;18874:10;18869:3;18865:20;18862:1;18855:31;18909:4;18906:1;18899:15;18937:4;18934:1;18927:15;19798:261;19868:3;-1:-1:-1;;;;;19889:31:80;;19886:51;;;19933:1;19930;19923:12;19886:51;19969:6;19966:1;19962:14;20010:8;20003:5;19998:3;19985:34;20035:18;;;;;19798:261;-1:-1:-1;;;19798:261:80:o;20064:951::-;20495:6;20490:3;20483:19;20465:3;20521:2;20553:6;20548:2;20543:3;20539:12;20532:28;20591:2;20586:3;20582:12;20640:6;20664:1;20674:204;20688:6;20685:1;20682:13;20674:204;;;20782:10;20755:25;20773:6;20755:25;:::i;:::-;20751:42;20737:57;;20816:14;;;;20853:15;;;;20710:1;20703:9;20674:204;;;20678:3;;20894:115;20948:60;21002:5;20994:6;20986;20948:60;:::i;:::-;20940:6;20932;20894:115;:::i;:::-;20887:122;20064:951;-1:-1:-1;;;;;;;;;;;;20064:951:80:o;21020:489::-;21334:10;21329:3;21325:20;21316:6;21311:3;21307:16;21303:43;21298:3;21291:56;21376:6;21372:1;21367:3;21363:11;21356:27;21413:6;21408:2;21403:3;21399:12;21392:28;21273:3;21436:67;21499:2;21494:3;21490:12;21482:6;21474;21436:67;:::i;:::-;21429:74;21020:489;-1:-1:-1;;;;;;;21020:489:80:o;22231:184::-;22301:6;22354:2;22342:9;22333:7;22329:23;22325:32;22322:52;;;22370:1;22367;22360:12;22322:52;-1:-1:-1;22393:16:80;;22231:184;-1:-1:-1;22231:184:80:o;23245:407::-;23447:2;23429:21;;;23486:2;23466:18;;;23459:30;23525:34;23520:2;23505:18;;23498:62;-1:-1:-1;;;23591:2:80;23576:18;;23569:41;23642:3;23627:19;;23245:407::o;24478:287::-;24607:3;24645:6;24639:13;24661:66;24720:6;24715:3;24708:4;24700:6;24696:17;24661:66;:::i;:::-;24743:16;;;;;24478:287;-1:-1:-1;;24478:287:80:o", + "linkReferences": {}, + "immutableReferences": { + "29832": [ + { + "start": 1614, + "length": 32 + }, + { + "start": 1687, + "length": 32 + }, + { + "start": 1909, + "length": 32 + }, + { + "start": 1973, + "length": 32 + }, + { + "start": 2957, + "length": 32 + }, + { + "start": 3021, + "length": 32 + }, + { + "start": 4100, + "length": 32 + }, + { + "start": 4164, + "length": 32 + }, + { + "start": 4347, + "length": 32 + }, + { + "start": 4411, + "length": 32 + }, + { + "start": 4583, + "length": 32 + }, + { + "start": 4647, + "length": 32 + }, + { + "start": 4903, + "length": 32 + }, + { + "start": 4967, + "length": 32 + }, + { + "start": 5495, + "length": 32 + }, + { + "start": 5559, + "length": 32 + }, + { + "start": 5737, + "length": 32 + }, + { + "start": 5801, + "length": 32 + }, + { + "start": 6143, + "length": 32 + }, + { + "start": 6207, + "length": 32 + }, + { + "start": 6346, + "length": 32 + }, + { + "start": 6410, + "length": 32 + }, + { + "start": 6533, + "length": 32 + }, + { + "start": 6597, + "length": 32 + }, + { + "start": 6748, + "length": 32 + }, + { + "start": 6924, + "length": 32 + }, + { + "start": 6988, + "length": 32 + }, + { + "start": 7323, + "length": 32 + }, + { + "start": 7387, + "length": 32 + }, + { + "start": 7591, + "length": 32 + }, + { + "start": 7655, + "length": 32 + }, + { + "start": 7850, + "length": 32 + }, + { + "start": 7914, + "length": 32 + }, + { + "start": 8065, + "length": 32 + }, + { + "start": 8129, + "length": 32 + }, + { + "start": 8279, + "length": 32 + }, + { + "start": 8343, + "length": 32 + }, + { + "start": 8567, + "length": 32 + }, + { + "start": 8631, + "length": 32 + }, + { + "start": 8812, + "length": 32 + }, + { + "start": 8876, + "length": 32 + }, + { + "start": 9357, + "length": 32 + }, + { + "start": 9421, + "length": 32 + }, + { + "start": 9700, + "length": 32 + }, + { + "start": 9764, + "length": 32 + }, + { + "start": 9905, + "length": 32 + }, + { + "start": 9969, + "length": 32 + }, + { + "start": 10119, + "length": 32 + }, + { + "start": 10183, + "length": 32 + }, + { + "start": 10331, + "length": 32 + }, + { + "start": 10395, + "length": 32 + }, + { + "start": 10881, + "length": 32 + }, + { + "start": 10945, + "length": 32 + }, + { + "start": 11582, + "length": 32 + }, + { + "start": 11646, + "length": 32 + } + ] + } + }, + "methodIdentifiers": { + "NO_SUCH_ROOT()": "561f204b", + "acceptOwnership()": "79ba5097", + "calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)": "31e4e992", + "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": "8c76a909", + "calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])": "86ec599a", + "deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)": "23cfdba5", + "getDeleteIdentitiesVerifierLookupTableAddress()": "3e8919b6", + "getIdentityUpdateVerifierLookupTableAddress()": "4ffbdde5", + "getRegisterIdentitiesVerifierLookupTableAddress()": "8fc22e9f", + "getRootHistoryExpiry()": "43f974cb", + "getSemaphoreVerifierAddress()": "f2038f95", + "getTreeDepth()": "8e5cdd50", + "identityOperator()": "f134b6ca", + "initialize(uint8,uint256,address,address,address)": "38c87065", + "initializeV2(address)": "29b6eca9", + "latestRoot()": "d7b0fef1", + "owner()": "8da5cb5b", + "pendingOwner()": "e30c3978", + "proxiableUUID()": "52d1902d", + "queryRoot(uint256)": "3f7c178d", + "registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)": "2217b211", + "renounceOwnership()": "715018a6", + "requireValidRoot(uint256)": "f2358e1d", + "setDeleteIdentitiesVerifierLookupTable(address)": "aa4a729e", + "setIdentityOperator(address)": "a7bba582", + "setIdentityUpdateVerifierLookupTable(address)": "6b056600", + "setRegisterIdentitiesVerifierLookupTable(address)": "2f059fca", + "setRootHistoryExpiry(uint256)": "c70aa727", + "setSemaphoreVerifier(address)": "0e3a12f3", + "transferOwnership(address)": "f2fde38b", + "updateIdentities(uint256[8],uint256,uint32[],uint256[],uint256[],uint256)": "b843b4e5", + "upgradeTo(address)": "3659cfe6", + "upgradeToAndCall(address,bytes)": "4f1ef286", + "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": "354ca120" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CannotRenounceOwnership\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExpiredRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ImplementationNotInitialized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"InvalidCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStateBridgeAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedInputLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"latestRoot\",\"type\":\"uint256\"}],\"name\":\"NotLatestRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProofValidationFailure\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeAlreadyDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StateBridgeAlreadyEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WorldIDIdentityManagerImplV1.UnreducedElementType\",\"name\":\"elementType\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"element\",\"type\":\"uint256\"}],\"name\":\"UnreducedElement\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"depth\",\"type\":\"uint8\"}],\"name\":\"UnsupportedTreeDepth\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum WorldIDIdentityManagerImplV1.Dependency\",\"name\":\"kind\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"DependencyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldOperator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOperator\",\"type\":\"address\"}],\"name\":\"IdentityOperatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldExpiryTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newExpiryTime\",\"type\":\"uint256\"}],\"name\":\"RootHistoryExpirySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"name\":\"StateBridgeStateChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum WorldIDIdentityManagerImplV1.TreeChange\",\"name\":\"kind\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"TreeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"_treeDepth\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialRoot\",\"type\":\"uint256\"}],\"name\":\"WorldIDIdentityManagerImplInitialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NO_SUCH_ROOT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"supersededTimestamp\",\"type\":\"uint128\"},{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.RootInfo\",\"name\":\"rootInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"packedDeletionIndices\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"batchSize\",\"type\":\"uint32\"}],\"name\":\"calculateIdentityDeletionInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"startIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"identityCommitments\",\"type\":\"uint256[]\"}],\"name\":\"calculateIdentityRegistrationInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"leafIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"oldIdentities\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newIdentities\",\"type\":\"uint256[]\"}],\"name\":\"calculateIdentityUpdateInputHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"deletionProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint32\",\"name\":\"batchSize\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"packedDeletionIndices\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"deleteIdentities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDeleteIdentitiesVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getIdentityUpdateVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegisterIdentitiesVerifierLookupTableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRootHistoryExpiry\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSemaphoreVerifierAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTreeDepth\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"identityOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_treeDepth\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"initialRoot\",\"type\":\"uint256\"},{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchInsertionVerifiers\",\"type\":\"address\"},{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchUpdateVerifiers\",\"type\":\"address\"},{\"internalType\":\"contract ISemaphoreVerifier\",\"name\":\"_semaphoreVerifier\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"_batchUpdateVerifiers\",\"type\":\"address\"}],\"name\":\"initializeV2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"queryRoot\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"supersededTimestamp\",\"type\":\"uint128\"},{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"internalType\":\"struct WorldIDIdentityManagerImplV1.RootInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"insertionProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256[]\",\"name\":\"identityCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"registerIdentities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"name\":\"requireValidRoot\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setDeleteIdentitiesVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newIdentityOperator\",\"type\":\"address\"}],\"name\":\"setIdentityOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setIdentityUpdateVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VerifierLookupTable\",\"name\":\"newTable\",\"type\":\"address\"}],\"name\":\"setRegisterIdentitiesVerifierLookupTable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newExpiryTime\",\"type\":\"uint256\"}],\"name\":\"setRootHistoryExpiry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ISemaphoreVerifier\",\"name\":\"newVerifier\",\"type\":\"address\"}],\"name\":\"setSemaphoreVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[8]\",\"name\":\"updateProof\",\"type\":\"uint256[8]\"},{\"internalType\":\"uint256\",\"name\":\"preRoot\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"leafIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"oldIdentities\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newIdentities\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"postRoot\",\"type\":\"uint256\"}],\"name\":\"updateIdentities\",\"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\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signalHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nullifierHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalNullifierHash\",\"type\":\"uint256\"},{\"internalType\":\"uint256[8]\",\"name\":\"proof\",\"type\":\"uint256[8]\"}],\"name\":\"verifyProof\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Worldcoin\",\"details\":\"The manager is based on the principle of verifying externally-created Zero Knowledge Proofs to perform the insertions.This is the implementation delegated to by a proxy.\",\"errors\":{\"InvalidCommitment(uint256)\":[{\"params\":{\"index\":\"The index in the array of identity commitments where the invalid commitment was found.\"}}],\"NotLatestRoot(uint256,uint256)\":[{\"params\":{\"latestRoot\":\"The actual latest root at the time of the transaction.\",\"providedRoot\":\"The root that was provided as the `preRoot` for a transaction.\"}}],\"Unauthorized(address)\":[{\"params\":{\"user\":\"The user that attempted the action that they were not authorised for.\"}}],\"UnreducedElement(uint8,uint256)\":[{\"details\":\"`r` in this case is given by `SNARK_SCALAR_FIELD`.\",\"params\":{\"element\":\"The value of that element.\",\"elementType\":\"The kind of element that was encountered unreduced.\"}}],\"UnsupportedTreeDepth(uint8)\":[{\"params\":{\"depth\":\"Passed tree depth.\"}}]},\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is upgraded.\"},\"DependencyUpdated(uint8,address,address)\":{\"params\":{\"kind\":\"The kind of dependency that was updated.\",\"newAddress\":\"The new address of that dependency.\",\"oldAddress\":\"The old address of that dependency.\"}},\"IdentityOperatorChanged(address,address)\":{\"params\":{\"newOperator\":\"The address of the new identity operator.\",\"oldOperator\":\"The address of the old identity operator.\"}},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"RootHistoryExpirySet(uint256,uint256)\":{\"params\":{\"newExpiryTime\":\"The expiry time after the change.\",\"oldExpiryTime\":\"The expiry time prior to the change.\"}},\"StateBridgeStateChange(bool)\":{\"params\":{\"isEnabled\":\"Set to `true` if the event comes from the state bridge being enabled, `false` otherwise.\"}},\"TreeChanged(uint256,uint8,uint256)\":{\"params\":{\"kind\":\"Either \\\"insertion\\\" or \\\"update\\\", the kind of alteration that was made to the tree.\",\"postRoot\":\"The value of the tree's root after the update.\",\"preRoot\":\"The value of the tree's root before the update.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"},\"WorldIDIdentityManagerImplInitialized(uint8,uint256)\":{\"params\":{\"_treeDepth\":\"The depth of the MerkeTree\",\"initialRoot\":\"The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree.\"}}},\"kind\":\"dev\",\"methods\":{\"NO_SUCH_ROOT()\":{\"details\":\"Can be checked against when querying for root data.\"},\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)\":{\"details\":\"Implements the computation described below.the deletion indices are packed into bytes calldata where each deletion index is 32 bits wide. The indices are encoded using abi.encodePacked for testing. We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows: packedDeletionIndices || PreRoot || PostRoot 32 bits * batchSize || 256 || 256\",\"params\":{\"batchSize\":\"The number of identities that were deleted in this batch\",\"packedDeletionIndices\":\"The indices of the identities that were deleted from the tree.\",\"postRoot\":\"The root value of the tree after these insertions were made.\",\"preRoot\":\"The root value of the tree before these insertions were made.\"},\"returns\":{\"hash\":\"The input hash calculated as described below.\"}},\"calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])\":{\"details\":\"Implements the computation described below.\",\"params\":{\"identityCommitments\":\"The identities that were added to the tree to produce `postRoot`.\",\"postRoot\":\"The root value of the tree after these insertions were made.\",\"preRoot\":\"The root value of the tree before these insertions were made.\",\"startIndex\":\"The index in the tree from which inserting started.\"},\"returns\":{\"hash\":\"The input hash calculated as described below. We keccak hash all input to save verification gas. Inputs are arranged as follows: StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] 32\\t || 256 || 256 || 256 || 256 || ... || 256 bits\"}},\"calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])\":{\"details\":\"Implements the computation described below.\",\"params\":{\"leafIndices\":\"The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.\",\"newIdentities\":\"The array of new values for the identities. Length must match that of `leafIndices`.\",\"oldIdentities\":\"The array of old values for the identities. Length must match that of `leafIndices`.\",\"postRoot\":\"The root value of the tree after the updates were made.\",\"preRoot\":\"The root value of the tree before the updates were made.\"},\"returns\":{\"hash\":\"The input hash calculated as described below. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation. We keccak hash all input to save verification gas. The inputs are arranged as follows: preRoot || postRoot || ix[0] || ... || ix[n] || oi[0] || ... || oi[n] || ni[0] || ... || ni[n] || 256 || 256 || 256 || ... || 256 || 256 || ... || 256 || 256 || ... || 256 || where: - `ix[i] == leafIndices[i]` - `oi[i] == oldIdentities[i]` - `ni[i] == newIdentities[i]` - `id[i] == identities[i]` - `n == batchSize - 1`\"}},\"deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to add identities.InvalidCommitment If one or more of the provided commitments is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `deletionProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identityCommitments` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.\",\"details\":\"Can only be called by the owner.Deletion is performed off-chain and verified on-chain via the `deletionProof`. This saves gas and time over deleting identities one at a time.\",\"params\":{\"batchSize\":\"The number of identities that are to be deleted in the current batch.\",\"deletionProof\":\"The proof that given the conditions (`preRoot` and `packedDeletionIndices`), deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y` coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`, and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x` and `y` coordinates for `krs`.\",\"packedDeletionIndices\":\"The indices of the identities that were deleted from the tree.\",\"postRoot\":\"The root obtained after deleting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`.\",\"preRoot\":\"The value for the root of the tree before the `identityCommitments` have been inserted. Must be an element of the field `Kr`.\"}},\"getDeleteIdentitiesVerifierLookupTableAddress()\":{\"details\":\"The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch.\",\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier lookup table.\"}},\"getIdentityUpdateVerifierLookupTableAddress()\":{\"details\":\"The update verifier is also used for member removals.\",\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier lookup table.\"}},\"getRegisterIdentitiesVerifierLookupTableAddress()\":{\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier lookup table.\"}},\"getRootHistoryExpiry()\":{\"returns\":{\"_0\":\"expiryTime The amount of time it takes for a root to expire.\"}},\"getSemaphoreVerifierAddress()\":{\"returns\":{\"_0\":\"addr The address of the contract being used as the verifier.\"}},\"getTreeDepth()\":{\"returns\":{\"_0\":\"initializedTreeDepth Tree depth.\"}},\"identityOperator()\":{\"returns\":{\"_0\":\"_ The address authorized to perform identity operations.\"}},\"initialize(uint8,uint256,address,address,address)\":{\"custom:reverts\":\"string If called more than once at the same initialisation number.UnsupportedTreeDepth If passed tree depth is not among defined values.\",\"details\":\"Must be called exactly once.This is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead.\",\"params\":{\"_batchInsertionVerifiers\":\"The verifier lookup table for batch insertions.\",\"_batchUpdateVerifiers\":\"The verifier lookup table for batch updates.\",\"_semaphoreVerifier\":\"The verifier to use for semaphore protocol proofs.\",\"_treeDepth\":\"The depth of the MerkeTree\",\"initialRoot\":\"The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree.\"}},\"initializeV2(address)\":{\"details\":\"Must be called exactly onceThis is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead.\"},\"latestRoot()\":{\"returns\":{\"_0\":\"root The value of the latest tree root.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"queryRoot(uint256)\":{\"details\":\"Should be used sparingly as the query can be quite expensive.\",\"params\":{\"root\":\"The root for which you are querying information.\"},\"returns\":{\"_0\":\"rootInfo The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. Note that if the queried root is the current, the timestamp will be invalid as the root has not been superseded.\"}},\"registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to add identities.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `insertionProof` cannot be verified using the provided inputs.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.\",\"params\":{\"identityCommitments\":\"The identities that were inserted into the tree starting at `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be elements of the field `Kr`.\",\"postRoot\":\"The root obtained after inserting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`. (alread in reduced form)\",\"startIndex\":\"The position in the tree at which the insertions were made.\"}},\"renounceOwnership()\":{\"details\":\"This function is intentionally not `virtual` as we do not want it to be possible to renounce ownership for any WorldID implementation.This function is marked as `onlyOwner` to maintain the access restriction from the base contract.\"},\"requireValidRoot(uint256)\":{\"custom:reverts\":\"ExpiredRoot If the provided `root` has expired.NonExistentRoot If the provided `root` does not exist in the history.\",\"details\":\"A root is valid if it is either the latest root, or not the latest root but has not expired.\",\"params\":{\"root\":\"The root of the merkle tree to check for validity.\"}},\"setDeleteIdentitiesVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newTable\":\"The new verifier lookup table to be used for verifying identity deletions.\"}},\"setIdentityOperator(address)\":{\"params\":{\"newIdentityOperator\":\"The address of the new identity operator.\"},\"returns\":{\"_0\":\"_ The address of the old identity operator.\"}},\"setIdentityUpdateVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.The update verifier is also used for member removals.\",\"params\":{\"newTable\":\"The new lookup table instance to be used for verifying identity updates.\"}},\"setRegisterIdentitiesVerifierLookupTable(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newTable\":\"The new verifier lookup table to be used for verifying identity registrations.\"}},\"setRootHistoryExpiry(uint256)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newExpiryTime\":\"The new time to use to expire roots.\"}},\"setSemaphoreVerifier(address)\":{\"details\":\"Only the owner of the contract can call this function.\",\"params\":{\"newVerifier\":\"The new verifier instance to be used for verifying semaphore proofs.\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateIdentities(uint256[8],uint256,uint32[],uint256[],uint256[],uint256)\":{\"custom:reverts\":\"Unauthorized If the message sender is not authorised to update identities.NotLatestRoot If the provided `preRoot` is not the latest root.MismatchedInputLengths If the provided arrays for `leafIndices`, `oldIdentities` and `newIdentities` do not match in length.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.NoSuchVerifier If the batch sizes doesn't match a known verifier.\",\"params\":{\"leafIndices\":\"The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.\",\"newIdentities\":\"The array of new values for the identities. Length must match that of `leafIndices`.\",\"oldIdentities\":\"The array of old values for the identities. Length must match that of `leafIndices`.\",\"postRoot\":\"The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation.\"}},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"verifyProof(uint256,uint256,uint256,uint256,uint256[8])\":{\"custom:reverts\":\"string If the zero-knowledge proof cannot be verified for the public inputs.\",\"details\":\"Note that a double-signaling check is not included here, and should be carried by the caller.\",\"params\":{\"externalNullifierHash\":\"A keccak256 hash of the external nullifier\",\"nullifierHash\":\"The nullifier hash\",\"proof\":\"The zero-knowledge proof\",\"root\":\"The of the Merkle tree\",\"signalHash\":\"A keccak256 hash of the Semaphore signal\"}}},\"title\":\"WorldID Identity Manager Implementation Version 2\",\"version\":1},\"userdoc\":{\"errors\":{\"CannotRenounceOwnership()\":[{\"notice\":\"Thrown when an attempt is made to renounce ownership.\"}],\"ExpiredRoot()\":[{\"notice\":\"Thrown when attempting to validate a root that has expired.\"}],\"ImplementationNotInitialized()\":[{\"notice\":\"Thrown when attempting to call a function while the implementation has not been initialized.\"}],\"InvalidCommitment(uint256)\":[{\"notice\":\"Thrown when one or more of the identity commitments to be inserted is invalid.\"}],\"InvalidStateBridgeAddress()\":[{\"notice\":\"Thrown when attempting to set the state bridge address to the zero address.\"}],\"MismatchedInputLengths()\":[{\"notice\":\"Thrown when the inputs to `removeIdentities` or `updateIdentities` do not match in length.\"}],\"NonExistentRoot()\":[{\"notice\":\"Thrown when attempting to validate a root that has yet to be added to the root history.\"}],\"NotLatestRoot(uint256,uint256)\":[{\"notice\":\"Thrown when the provided root is not the very latest root.\"}],\"ProofValidationFailure()\":[{\"notice\":\"Thrown when the provided proof cannot be verified for the accompanying inputs.\"}],\"StateBridgeAlreadyDisabled()\":[{\"notice\":\"Thrown when attempting to disable the bridge when it is already disabled.\"}],\"StateBridgeAlreadyEnabled()\":[{\"notice\":\"Thrown when attempting to enable the bridge when it is already enabled.\"}],\"Unauthorized(address)\":[{\"notice\":\"Thrown when trying to execute a privileged action without being the contract manager.\"}],\"UnreducedElement(uint8,uint256)\":[{\"notice\":\"Thrown when encountering an element that should be reduced as a member of `Fr` but is not.\"}],\"UnsupportedTreeDepth(uint8)\":[{\"notice\":\"Thrown when Semaphore tree depth is not supported.\"}]},\"events\":{\"DependencyUpdated(uint8,address,address)\":{\"notice\":\"Emitted when a dependency's address is updated via an admin action.\"},\"IdentityOperatorChanged(address,address)\":{\"notice\":\"Emitted when the identity operator is changed.\"},\"RootHistoryExpirySet(uint256,uint256)\":{\"notice\":\"Emitted when the root history expiry time is changed.\"},\"StateBridgeStateChange(bool)\":{\"notice\":\"Emitted when the state bridge is enabled or disabled.\"},\"TreeChanged(uint256,uint8,uint256)\":{\"notice\":\"Emitted when the current root of the tree is updated.\"}},\"kind\":\"user\",\"methods\":{\"NO_SUCH_ROOT()\":{\"notice\":\"A constant representing a root that doesn't exist.\"},\"calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)\":{\"notice\":\"Calculates the input hash for the identity deletion verifier.\"},\"calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])\":{\"notice\":\"Calculates the input hash for the identity registration verifier.\"},\"calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])\":{\"notice\":\"Calculates the input hash for the identity update verifier.\"},\"deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)\":{\"notice\":\"Deletes identities from the WorldID system.\"},\"getDeleteIdentitiesVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for batch identity deletions.\"},\"getIdentityUpdateVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for identity updates.\"},\"getRegisterIdentitiesVerifierLookupTableAddress()\":{\"notice\":\"Gets the address for the lookup table of merkle tree verifiers used for identity registrations.\"},\"getRootHistoryExpiry()\":{\"notice\":\"Gets the current amount of time used to expire roots in the history.\"},\"getSemaphoreVerifierAddress()\":{\"notice\":\"Gets the address of the verifier used for verification of semaphore proofs.\"},\"getTreeDepth()\":{\"notice\":\"Gets the Semaphore tree depth the contract was initialized with.\"},\"identityOperator()\":{\"notice\":\"Gets the address that is authorised to perform identity operations on this identity manager instance.\"},\"initialize(uint8,uint256,address,address,address)\":{\"notice\":\"Initializes the contract.\"},\"initializeV2(address)\":{\"notice\":\"Initializes the V2 implementation contract.\"},\"latestRoot()\":{\"notice\":\"Allows a caller to query the latest root.\"},\"queryRoot(uint256)\":{\"notice\":\"Allows a caller to query the root history for information about a given root.\"},\"renounceOwnership()\":{\"notice\":\"Ensures that ownership of WorldID implementations cannot be renounced.\"},\"requireValidRoot(uint256)\":{\"notice\":\"Reverts if the provided root value is not valid.\"},\"setDeleteIdentitiesVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers used for identity deletions.\"},\"setIdentityOperator(address)\":{\"notice\":\"Sets the address that is authorised to perform identity operations on this identity manager instance.\"},\"setIdentityUpdateVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers to be used for verification of identity updates.\"},\"setRegisterIdentitiesVerifierLookupTable(address)\":{\"notice\":\"Sets the address for the lookup table of merkle tree verifiers used for identity registrations.\"},\"setRootHistoryExpiry(uint256)\":{\"notice\":\"Sets the time to wait before expiring a root from the root history.\"},\"setSemaphoreVerifier(address)\":{\"notice\":\"Sets the address for the semaphore verifier to be used for verification of semaphore proofs.\"},\"verifyProof(uint256,uint256,uint256,uint256,uint256[8])\":{\"notice\":\"A verifier for the semaphore protocol.\"}},\"notice\":\"An implementation of a batch-based identity manager for the WorldID protocol.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/WorldIDIdentityManagerImplV2.sol\":\"WorldIDIdentityManagerImplV2\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@zk-kit/=lib/zk-kit/packages/\",\":contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":ds-test/=lib/ds-test/src/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/\",\":openzeppelin/=lib/openzeppelin-contracts/contracts/\",\":semaphore/=lib/semaphore/packages/contracts/contracts/\",\":solmate/=lib/solmate/src/\",\":zk-kit/=lib/zk-kit/\"]},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol\":{\"keccak256\":\"0xd712fb45b3ea0ab49679164e3895037adc26ce12879d5184feb040e01c1c07a9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://79ecc0838b0649460c0a538a4adb55b2b530e726c5526afc5e09c8eea4f3af13\",\"dweb:/ipfs/QmUxugyGDGGeLzDFi8QDH2vQMtCFaheiujWv58SuGVx4bZ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol\":{\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053\",\"dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"keccak256\":\"0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2\",\"dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol\":{\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1\",\"dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8a313cf42389440e2706837c91370323b85971c06afd6d056d21e2bc86459618\",\"dweb:/ipfs/QmT8XUrUvQ9aZaPKrqgRU2JVGWnaxBcUYJA7Q7K5KcLBSZ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0x7967d130887c4b40666cd88f8744691d4527039a1b2a38aa0de41481ef646778\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40e60cbf0e2efede4d9c169e66336a64615af7b719a896ef1f37ae8cd4614ec1\",\"dweb:/ipfs/QmYNiwY22ifhfa8yK6mLCEKfj39caYUHLqe2VBtzDnvdsV\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06\",\"dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol\":{\"keccak256\":\"0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3\",\"dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0x923b9774b81c1abfb992262ae7763b6e6de77b077a7180d53c6ebb7b1c8bd648\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://53445dc0431f9b45c06f567c6091da961d4087bec0010cca5bd62100fa624a38\",\"dweb:/ipfs/QmNvBYpBv183czrAqNXr76E8M3LF93ouAJFeAcHfb59Rcx\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol\":{\"keccak256\":\"0x7cdab82b437a17902683a413c86d14f512674a0710007bf44c584a2d2d3ca833\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ffe4db7a9f3cdd5a5d019462c2859f4f98f7aae08704afdcb3ef0d08d966bbeb\",\"dweb:/ipfs/QmTCHSuoi22dAu55qv4TcENyTmv5mTpAoxmYWD8cRnEp3M\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"lib/semaphore/packages/contracts/contracts/base/Pairing.sol\":{\"keccak256\":\"0x44390032d1247a0e3931eb39f1220f170db653c6b3b4321b2e2b0034f5e07334\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://725cc4bdf047d17bf9d47c9a0205d90897c0da334de8e556c1a3049b1beb9aed\",\"dweb:/ipfs/QmSo7SXpqyrqHFhYi7F8SGjcVxCdVr6FNdgiw7Qfre1NGt\"]},\"lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol\":{\"keccak256\":\"0x5b5b1118ed7936014d3e410419d6048cc9c0ae69fd700442593f2c2cc782e1af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://601cf2c7e3c98735ff38eaff225af090ec847d63ec599ecc2340323145430668\",\"dweb:/ipfs/QmUoZYgge8GmQokXrYiRXn24s4HgBZetiNWQssiSoTFrdi\"]},\"src/WorldIDIdentityManagerImplV1.sol\":{\"keccak256\":\"0xa1065360c830348be5e6f45dfb766d9f415d0321170a804da0b2f56338c14b36\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cd10fbb5eaf1f57cfe026baf79ee8cb7ca9d7db50599b77062d2634a147e9645\",\"dweb:/ipfs/QmdtRnh5nPkRFynH2mNsYvaAur8QPwsuCg6A1AAQnKB291\"]},\"src/WorldIDIdentityManagerImplV2.sol\":{\"keccak256\":\"0xa88ed74cd795d2a9a7cbb99f88fa1393c25d7807525c6f081b57d163180f887b\",\"urls\":[\"bzz-raw://5e045ea6313140813d515f5ceb43624cba08cfd14657445a731ba76a1e8252f1\",\"dweb:/ipfs/Qmb4kfWzbV3gVjrhfVo2PphCijTXxdBUvz9N1mV3Mivcd5\"]},\"src/abstract/WorldIDImpl.sol\":{\"keccak256\":\"0xccfff2c5d7af4e505ed13b7d46011d5544317343ea92e7beb874e4d69358e6d0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://428860598ca38e42e29892a0b4759c4d3010378f54c3b3e4392f965ff091076e\",\"dweb:/ipfs/QmYPjcDRTr1UEeSbS7ssdGjbDHzAqjRNKBsYJqKJWeL8bZ\"]},\"src/data/VerifierLookupTable.sol\":{\"keccak256\":\"0xfd213b79aaec8d205c50ab3ed5c4ebed06ae602ed526a820340adc1c76745fbc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6af992a56a7cee8124af7f16d74dc8a2a7ae5f8b3059b92d46862e44c3804b83\",\"dweb:/ipfs/QmV9bQtJ9PjnwsiiZMUGJANB3znSxJ6ACTqWv9WkQeoeB3\"]},\"src/interfaces/IBaseWorldID.sol\":{\"keccak256\":\"0xcec58605726864d72e35d62c85e002acc98d3f8fa19d01b49fff461c2767c144\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://57714fcbceb0497f3fe8906778a837082939489fbb0bd930d015ad6e971913d5\",\"dweb:/ipfs/QmQVVmLr9CEkR727ByMF96a8MbwAeB4AQQWvxneg2Avkq8\"]},\"src/interfaces/IBridge.sol\":{\"keccak256\":\"0x0931c789450d21479da5d4de8c6435fca965660f6e1bd746fff958f4c20cf2ac\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0c564b4d4a15e8075555077a043d773bb20133548376402ff3dbc0eccb57435d\",\"dweb:/ipfs/QmXQRihAFdtfyjTNeHmx9nmNHiS1wy2658Y5aXCXo2tKSQ\"]},\"src/interfaces/ITreeVerifier.sol\":{\"keccak256\":\"0xb572aeae7331d96981d46b0dd4408db9ad507a06a2dbf0624386114b2244c8ad\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6159630f78e9e0b3a326d064772713f8c1e73172718c2a6d5af1fb36b35c5991\",\"dweb:/ipfs/QmPN5VyQvonPfPdTvrmP5wqsFT3QNW3RwC8DHYdEtwXZT4\"]},\"src/interfaces/IWorldID.sol\":{\"keccak256\":\"0x577908eff2d29d96354a06ab2602ffe6b97aa9d491330efcc2fcd0a88a8acbb1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa0a36a598a851b88cff364b4211dc32081f51940aa8076d9c9b7de8ab126b2f\",\"dweb:/ipfs/QmSne8aRiE8C8RuwEUSk4doETKAGaavrEYyUkwiJc5H8qc\"]},\"src/utils/CheckInitialized.sol\":{\"keccak256\":\"0xfab096b633efd580548007e97920f6088e6d8a5287db84b9aa3d595c02fefcf4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dee612c9dbad59d535e7a72b79191187fd91c06af9cb5b6f68d60274d0ee2c04\",\"dweb:/ipfs/QmVJbSQ8DAN6igasbgHjZTM4NRZ3EjrhK8wFcvUG1wPYtZ\"]},\"src/utils/SemaphoreTreeDepthValidator.sol\":{\"keccak256\":\"0x50140161de381aa963457cfd2ee8831a435bd79040f38794e6ef07365c49c872\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bcc5b8a3a6f5146aa3fdee550c3e80d828b55df63223485da3d5655a591ad661\",\"dweb:/ipfs/QmWfUzbeFoSaPV1E8QxagUnpt5zfmPXgiropUg1GcV6oZs\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.21+commit.d9974bed" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [], + "type": "error", + "name": "CannotRenounceOwnership" + }, + { + "inputs": [], + "type": "error", + "name": "ExpiredRoot" + }, + { + "inputs": [], + "type": "error", + "name": "ImplementationNotInitialized" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "type": "error", + "name": "InvalidCommitment" + }, + { + "inputs": [], + "type": "error", + "name": "InvalidStateBridgeAddress" + }, + { + "inputs": [], + "type": "error", + "name": "MismatchedInputLengths" + }, + { + "inputs": [], + "type": "error", + "name": "NonExistentRoot" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "providedRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "latestRoot", + "type": "uint256" + } + ], + "type": "error", + "name": "NotLatestRoot" + }, + { + "inputs": [], + "type": "error", + "name": "ProofValidationFailure" + }, + { + "inputs": [], + "type": "error", + "name": "StateBridgeAlreadyDisabled" + }, + { + "inputs": [], + "type": "error", + "name": "StateBridgeAlreadyEnabled" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "type": "error", + "name": "Unauthorized" + }, + { + "inputs": [ + { + "internalType": "enum WorldIDIdentityManagerImplV1.UnreducedElementType", + "name": "elementType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "element", + "type": "uint256" + } + ], + "type": "error", + "name": "UnreducedElement" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "depth", + "type": "uint8" + } + ], + "type": "error", + "name": "UnsupportedTreeDepth" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousAdmin", + "type": "address", + "indexed": false + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "AdminChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "BeaconUpgraded", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "enum WorldIDIdentityManagerImplV1.Dependency", + "name": "kind", + "type": "uint8", + "indexed": true + }, + { + "internalType": "address", + "name": "oldAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newAddress", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "DependencyUpdated", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oldOperator", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOperator", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "IdentityOperatorChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8", + "indexed": false + } + ], + "type": "event", + "name": "Initialized", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousOwner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "OwnershipTransferStarted", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousOwner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "OwnershipTransferred", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "oldExpiryTime", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256", + "indexed": true + } + ], + "type": "event", + "name": "RootHistoryExpirySet", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "isEnabled", + "type": "bool", + "indexed": true + } + ], + "type": "event", + "name": "StateBridgeStateChange", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256", + "indexed": true + }, + { + "internalType": "enum WorldIDIdentityManagerImplV1.TreeChange", + "name": "kind", + "type": "uint8", + "indexed": true + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256", + "indexed": true + } + ], + "type": "event", + "name": "TreeChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "Upgraded", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8", + "indexed": false + }, + { + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "WorldIDIdentityManagerImplInitialized", + "anonymous": false + }, + { + "inputs": [], + "stateMutability": "pure", + "type": "function", + "name": "NO_SUCH_ROOT", + "outputs": [ + { + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "rootInfo", + "type": "tuple", + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ] + } + ] + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "name": "acceptOwnership" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function", + "name": "calculateIdentityDeletionInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function", + "name": "calculateIdentityRegistrationInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function", + "name": "calculateIdentityUpdateInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "deletionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint32", + "name": "batchSize", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "packedDeletionIndices", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "deleteIdentities" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getDeleteIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getIdentityUpdateVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getRegisterIdentitiesVerifierLookupTableAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getRootHistoryExpiry", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getSemaphoreVerifierAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "getTreeDepth", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "identityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_treeDepth", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "initialRoot", + "type": "uint256" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchInsertionVerifiers", + "type": "address" + }, + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + }, + { + "internalType": "contract ISemaphoreVerifier", + "name": "_semaphoreVerifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "initialize" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "_batchUpdateVerifiers", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "initializeV2" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "latestRoot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "queryRoot", + "outputs": [ + { + "internalType": "struct WorldIDIdentityManagerImplV1.RootInfo", + "name": "", + "type": "tuple", + "components": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "supersededTimestamp", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ] + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "insertionProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "startIndex", + "type": "uint32" + }, + { + "internalType": "uint256[]", + "name": "identityCommitments", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "registerIdentities" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "renounceOwnership" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "requireValidRoot" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setDeleteIdentitiesVerifierLookupTable" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newIdentityOperator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setIdentityOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setIdentityUpdateVerifierLookupTable" + }, + { + "inputs": [ + { + "internalType": "contract VerifierLookupTable", + "name": "newTable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setRegisterIdentitiesVerifierLookupTable" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newExpiryTime", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setRootHistoryExpiry" + }, + { + "inputs": [ + { + "internalType": "contract ISemaphoreVerifier", + "name": "newVerifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setSemaphoreVerifier" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferOwnership" + }, + { + "inputs": [ + { + "internalType": "uint256[8]", + "name": "updateProof", + "type": "uint256[8]" + }, + { + "internalType": "uint256", + "name": "preRoot", + "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "leafIndices", + "type": "uint32[]" + }, + { + "internalType": "uint256[]", + "name": "oldIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newIdentities", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "postRoot", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "updateIdentities" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "upgradeTo" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function", + "name": "upgradeToAndCall" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "root", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "signalHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalNullifierHash", + "type": "uint256" + }, + { + "internalType": "uint256[8]", + "name": "proof", + "type": "uint256[8]" + } + ], + "stateMutability": "view", + "type": "function", + "name": "verifyProof" + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "NO_SUCH_ROOT()": { + "details": "Can be checked against when querying for root data." + }, + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)": { + "details": "Implements the computation described below.the deletion indices are packed into bytes calldata where each deletion index is 32 bits wide. The indices are encoded using abi.encodePacked for testing. We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows: packedDeletionIndices || PreRoot || PostRoot 32 bits * batchSize || 256 || 256", + "params": { + "batchSize": "The number of identities that were deleted in this batch", + "packedDeletionIndices": "The indices of the identities that were deleted from the tree.", + "postRoot": "The root value of the tree after these insertions were made.", + "preRoot": "The root value of the tree before these insertions were made." + }, + "returns": { + "hash": "The input hash calculated as described below." + } + }, + "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": { + "details": "Implements the computation described below.", + "params": { + "identityCommitments": "The identities that were added to the tree to produce `postRoot`.", + "postRoot": "The root value of the tree after these insertions were made.", + "preRoot": "The root value of the tree before these insertions were made.", + "startIndex": "The index in the tree from which inserting started." + }, + "returns": { + "hash": "The input hash calculated as described below. We keccak hash all input to save verification gas. Inputs are arranged as follows: StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] 32\t || 256 || 256 || 256 || 256 || ... || 256 bits" + } + }, + "calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])": { + "details": "Implements the computation described below.", + "params": { + "leafIndices": "The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.", + "newIdentities": "The array of new values for the identities. Length must match that of `leafIndices`.", + "oldIdentities": "The array of old values for the identities. Length must match that of `leafIndices`.", + "postRoot": "The root value of the tree after the updates were made.", + "preRoot": "The root value of the tree before the updates were made." + }, + "returns": { + "hash": "The input hash calculated as described below. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation. We keccak hash all input to save verification gas. The inputs are arranged as follows: preRoot || postRoot || ix[0] || ... || ix[n] || oi[0] || ... || oi[n] || ni[0] || ... || ni[n] || 256 || 256 || 256 || ... || 256 || 256 || ... || 256 || 256 || ... || 256 || where: - `ix[i] == leafIndices[i]` - `oi[i] == oldIdentities[i]` - `ni[i] == newIdentities[i]` - `id[i] == identities[i]` - `n == batchSize - 1`" + } + }, + "deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)": { + "custom:reverts": "Unauthorized If the message sender is not authorised to add identities.InvalidCommitment If one or more of the provided commitments is invalid.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `deletionProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identityCommitments` is not an element of the field `Kr`. It describes the type and value of the unreduced element.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.", + "details": "Can only be called by the owner.Deletion is performed off-chain and verified on-chain via the `deletionProof`. This saves gas and time over deleting identities one at a time.", + "params": { + "batchSize": "The number of identities that are to be deleted in the current batch.", + "deletionProof": "The proof that given the conditions (`preRoot` and `packedDeletionIndices`), deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y` coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`, and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x` and `y` coordinates for `krs`.", + "packedDeletionIndices": "The indices of the identities that were deleted from the tree.", + "postRoot": "The root obtained after deleting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`.", + "preRoot": "The value for the root of the tree before the `identityCommitments` have been inserted. Must be an element of the field `Kr`." + } + }, + "getDeleteIdentitiesVerifierLookupTableAddress()": { + "details": "The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch.", + "returns": { + "_0": "addr The address of the contract being used as the verifier lookup table." + } + }, + "getIdentityUpdateVerifierLookupTableAddress()": { + "details": "The update verifier is also used for member removals.", + "returns": { + "_0": "addr The address of the contract being used as the verifier lookup table." + } + }, + "getRegisterIdentitiesVerifierLookupTableAddress()": { + "returns": { + "_0": "addr The address of the contract being used as the verifier lookup table." + } + }, + "getRootHistoryExpiry()": { + "returns": { + "_0": "expiryTime The amount of time it takes for a root to expire." + } + }, + "getSemaphoreVerifierAddress()": { + "returns": { + "_0": "addr The address of the contract being used as the verifier." + } + }, + "getTreeDepth()": { + "returns": { + "_0": "initializedTreeDepth Tree depth." + } + }, + "identityOperator()": { + "returns": { + "_0": "_ The address authorized to perform identity operations." + } + }, + "initialize(uint8,uint256,address,address,address)": { + "custom:reverts": "string If called more than once at the same initialisation number.UnsupportedTreeDepth If passed tree depth is not among defined values.", + "details": "Must be called exactly once.This is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead.", + "params": { + "_batchInsertionVerifiers": "The verifier lookup table for batch insertions.", + "_batchUpdateVerifiers": "The verifier lookup table for batch updates.", + "_semaphoreVerifier": "The verifier to use for semaphore protocol proofs.", + "_treeDepth": "The depth of the MerkeTree", + "initialRoot": "The initial value for the `latestRoot` in the contract. When deploying this should be set to the root of the empty tree." + } + }, + "initializeV2(address)": { + "details": "Must be called exactly onceThis is marked `reinitializer()` to allow for updated initialisation steps when working with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) initialisations allowed, so decide carefully when to use them. Many cases can safely be replaced by use of setters.This function is explicitly not virtual as it does not make sense to override even when upgrading. Create a separate initializer function instead." + }, + "latestRoot()": { + "returns": { + "_0": "root The value of the latest tree root." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "proxiableUUID()": { + "details": "Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "queryRoot(uint256)": { + "details": "Should be used sparingly as the query can be quite expensive.", + "params": { + "root": "The root for which you are querying information." + }, + "returns": { + "_0": "rootInfo The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. Note that if the queried root is the current, the timestamp will be invalid as the root has not been superseded." + } + }, + "registerIdentities(uint256[8],uint256,uint32,uint256[],uint256)": { + "custom:reverts": "Unauthorized If the message sender is not authorised to add identities.NotLatestRoot If the provided `preRoot` is not the latest root.ProofValidationFailure If `insertionProof` cannot be verified using the provided inputs.VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known verifier.VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum batch size.", + "params": { + "identityCommitments": "The identities that were inserted into the tree starting at `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be elements of the field `Kr`.", + "postRoot": "The root obtained after inserting all of `identityCommitments` into the tree described by `preRoot`. Must be an element of the field `Kr`. (alread in reduced form)", + "startIndex": "The position in the tree at which the insertions were made." + } + }, + "renounceOwnership()": { + "details": "This function is intentionally not `virtual` as we do not want it to be possible to renounce ownership for any WorldID implementation.This function is marked as `onlyOwner` to maintain the access restriction from the base contract." + }, + "requireValidRoot(uint256)": { + "custom:reverts": "ExpiredRoot If the provided `root` has expired.NonExistentRoot If the provided `root` does not exist in the history.", + "details": "A root is valid if it is either the latest root, or not the latest root but has not expired.", + "params": { + "root": "The root of the merkle tree to check for validity." + } + }, + "setDeleteIdentitiesVerifierLookupTable(address)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newTable": "The new verifier lookup table to be used for verifying identity deletions." + } + }, + "setIdentityOperator(address)": { + "params": { + "newIdentityOperator": "The address of the new identity operator." + }, + "returns": { + "_0": "_ The address of the old identity operator." + } + }, + "setIdentityUpdateVerifierLookupTable(address)": { + "details": "Only the owner of the contract can call this function.The update verifier is also used for member removals.", + "params": { + "newTable": "The new lookup table instance to be used for verifying identity updates." + } + }, + "setRegisterIdentitiesVerifierLookupTable(address)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newTable": "The new verifier lookup table to be used for verifying identity registrations." + } + }, + "setRootHistoryExpiry(uint256)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newExpiryTime": "The new time to use to expire roots." + } + }, + "setSemaphoreVerifier(address)": { + "details": "Only the owner of the contract can call this function.", + "params": { + "newVerifier": "The new verifier instance to be used for verifying semaphore proofs." + } + }, + "transferOwnership(address)": { + "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." + }, + "updateIdentities(uint256[8],uint256,uint32[],uint256[],uint256[],uint256)": { + "custom:reverts": "Unauthorized If the message sender is not authorised to update identities.NotLatestRoot If the provided `preRoot` is not the latest root.MismatchedInputLengths If the provided arrays for `leafIndices`, `oldIdentities` and `newIdentities` do not match in length.ProofValidationFailure If `removalProof` cannot be verified using the provided inputs.UnreducedElement If any of the `preRoot`, `postRoot` and `identities` is not an element of the field `Kr`. It describes the type and value of the unreduced element.NoSuchVerifier If the batch sizes doesn't match a known verifier.", + "params": { + "leafIndices": "The array of leaf indices at which the update operations take place in the tree. Elements in this array are extended to 256 bits when encoding.", + "newIdentities": "The array of new values for the identities. Length must match that of `leafIndices`.", + "oldIdentities": "The array of old values for the identities. Length must match that of `leafIndices`.", + "postRoot": "The root obtained after removing all of `removedIdentities` from the tree described by `preRoot`. Must be an element of the field `Kr`. The arrays `leafIndices`, `oldIdentities` and `newIdentities` are arranged such that the triple at an element `i` in those arrays corresponds to one update operation." + } + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": { + "custom:reverts": "string If the zero-knowledge proof cannot be verified for the public inputs.", + "details": "Note that a double-signaling check is not included here, and should be carried by the caller.", + "params": { + "externalNullifierHash": "A keccak256 hash of the external nullifier", + "nullifierHash": "The nullifier hash", + "proof": "The zero-knowledge proof", + "root": "The of the Merkle tree", + "signalHash": "A keccak256 hash of the Semaphore signal" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "NO_SUCH_ROOT()": { + "notice": "A constant representing a root that doesn't exist." + }, + "calculateIdentityDeletionInputHash(bytes,uint256,uint256,uint32)": { + "notice": "Calculates the input hash for the identity deletion verifier." + }, + "calculateIdentityRegistrationInputHash(uint32,uint256,uint256,uint256[])": { + "notice": "Calculates the input hash for the identity registration verifier." + }, + "calculateIdentityUpdateInputHash(uint256,uint256,uint32[],uint256[],uint256[])": { + "notice": "Calculates the input hash for the identity update verifier." + }, + "deleteIdentities(uint256[8],uint32,bytes,uint256,uint256)": { + "notice": "Deletes identities from the WorldID system." + }, + "getDeleteIdentitiesVerifierLookupTableAddress()": { + "notice": "Gets the address for the lookup table of merkle tree verifiers used for batch identity deletions." + }, + "getIdentityUpdateVerifierLookupTableAddress()": { + "notice": "Gets the address for the lookup table of merkle tree verifiers used for identity updates." + }, + "getRegisterIdentitiesVerifierLookupTableAddress()": { + "notice": "Gets the address for the lookup table of merkle tree verifiers used for identity registrations." + }, + "getRootHistoryExpiry()": { + "notice": "Gets the current amount of time used to expire roots in the history." + }, + "getSemaphoreVerifierAddress()": { + "notice": "Gets the address of the verifier used for verification of semaphore proofs." + }, + "getTreeDepth()": { + "notice": "Gets the Semaphore tree depth the contract was initialized with." + }, + "identityOperator()": { + "notice": "Gets the address that is authorised to perform identity operations on this identity manager instance." + }, + "initialize(uint8,uint256,address,address,address)": { + "notice": "Initializes the contract." + }, + "initializeV2(address)": { + "notice": "Initializes the V2 implementation contract." + }, + "latestRoot()": { + "notice": "Allows a caller to query the latest root." + }, + "queryRoot(uint256)": { + "notice": "Allows a caller to query the root history for information about a given root." + }, + "renounceOwnership()": { + "notice": "Ensures that ownership of WorldID implementations cannot be renounced." + }, + "requireValidRoot(uint256)": { + "notice": "Reverts if the provided root value is not valid." + }, + "setDeleteIdentitiesVerifierLookupTable(address)": { + "notice": "Sets the address for the lookup table of merkle tree verifiers used for identity deletions." + }, + "setIdentityOperator(address)": { + "notice": "Sets the address that is authorised to perform identity operations on this identity manager instance." + }, + "setIdentityUpdateVerifierLookupTable(address)": { + "notice": "Sets the address for the lookup table of merkle tree verifiers to be used for verification of identity updates." + }, + "setRegisterIdentitiesVerifierLookupTable(address)": { + "notice": "Sets the address for the lookup table of merkle tree verifiers used for identity registrations." + }, + "setRootHistoryExpiry(uint256)": { + "notice": "Sets the time to wait before expiring a root from the root history." + }, + "setSemaphoreVerifier(address)": { + "notice": "Sets the address for the semaphore verifier to be used for verification of semaphore proofs." + }, + "verifyProof(uint256,uint256,uint256,uint256,uint256[8])": { + "notice": "A verifier for the semaphore protocol." + } + }, + "version": 1 + } + }, + "settings": { + "remappings": [ + "@zk-kit/=lib/zk-kit/packages/", + "contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-std/=lib/forge-std/src/", + "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "semaphore/=lib/semaphore/packages/contracts/contracts/", + "solmate/=lib/solmate/src/", + "zk-kit/=lib/zk-kit/" + ], + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/WorldIDIdentityManagerImplV2.sol": "WorldIDIdentityManagerImplV2" + }, + "libraries": {} + }, + "sources": { + "lib/openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol": { + "keccak256": "0xd712fb45b3ea0ab49679164e3895037adc26ce12879d5184feb040e01c1c07a9", + "urls": [ + "bzz-raw://79ecc0838b0649460c0a538a4adb55b2b530e726c5526afc5e09c8eea4f3af13", + "dweb:/ipfs/QmUxugyGDGGeLzDFi8QDH2vQMtCFaheiujWv58SuGVx4bZ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol": { + "keccak256": "0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888", + "urls": [ + "bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a", + "dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol": { + "keccak256": "0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f", + "urls": [ + "bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053", + "dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "keccak256": "0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823", + "urls": [ + "bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2", + "dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol": { + "keccak256": "0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908", + "urls": [ + "bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1", + "dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": { + "keccak256": "0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271", + "urls": [ + "bzz-raw://8a313cf42389440e2706837c91370323b85971c06afd6d056d21e2bc86459618", + "dweb:/ipfs/QmT8XUrUvQ9aZaPKrqgRU2JVGWnaxBcUYJA7Q7K5KcLBSZ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol": { + "keccak256": "0x7967d130887c4b40666cd88f8744691d4527039a1b2a38aa0de41481ef646778", + "urls": [ + "bzz-raw://40e60cbf0e2efede4d9c169e66336a64615af7b719a896ef1f37ae8cd4614ec1", + "dweb:/ipfs/QmYNiwY22ifhfa8yK6mLCEKfj39caYUHLqe2VBtzDnvdsV" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": { + "keccak256": "0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183", + "urls": [ + "bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06", + "dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": { + "keccak256": "0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149", + "urls": [ + "bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c", + "dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol": { + "keccak256": "0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a", + "urls": [ + "bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3", + "dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/access/Ownable.sol": { + "keccak256": "0x923b9774b81c1abfb992262ae7763b6e6de77b077a7180d53c6ebb7b1c8bd648", + "urls": [ + "bzz-raw://53445dc0431f9b45c06f567c6091da961d4087bec0010cca5bd62100fa624a38", + "dweb:/ipfs/QmNvBYpBv183czrAqNXr76E8M3LF93ouAJFeAcHfb59Rcx" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol": { + "keccak256": "0x7cdab82b437a17902683a413c86d14f512674a0710007bf44c584a2d2d3ca833", + "urls": [ + "bzz-raw://ffe4db7a9f3cdd5a5d019462c2859f4f98f7aae08704afdcb3ef0d08d966bbeb", + "dweb:/ipfs/QmTCHSuoi22dAu55qv4TcENyTmv5mTpAoxmYWD8cRnEp3M" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "keccak256": "0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7", + "urls": [ + "bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92", + "dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3" + ], + "license": "MIT" + }, + "lib/semaphore/packages/contracts/contracts/base/Pairing.sol": { + "keccak256": "0x44390032d1247a0e3931eb39f1220f170db653c6b3b4321b2e2b0034f5e07334", + "urls": [ + "bzz-raw://725cc4bdf047d17bf9d47c9a0205d90897c0da334de8e556c1a3049b1beb9aed", + "dweb:/ipfs/QmSo7SXpqyrqHFhYi7F8SGjcVxCdVr6FNdgiw7Qfre1NGt" + ], + "license": "MIT" + }, + "lib/semaphore/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol": { + "keccak256": "0x5b5b1118ed7936014d3e410419d6048cc9c0ae69fd700442593f2c2cc782e1af", + "urls": [ + "bzz-raw://601cf2c7e3c98735ff38eaff225af090ec847d63ec599ecc2340323145430668", + "dweb:/ipfs/QmUoZYgge8GmQokXrYiRXn24s4HgBZetiNWQssiSoTFrdi" + ], + "license": "MIT" + }, + "src/WorldIDIdentityManagerImplV1.sol": { + "keccak256": "0xa1065360c830348be5e6f45dfb766d9f415d0321170a804da0b2f56338c14b36", + "urls": [ + "bzz-raw://cd10fbb5eaf1f57cfe026baf79ee8cb7ca9d7db50599b77062d2634a147e9645", + "dweb:/ipfs/QmdtRnh5nPkRFynH2mNsYvaAur8QPwsuCg6A1AAQnKB291" + ], + "license": "MIT" + }, + "src/WorldIDIdentityManagerImplV2.sol": { + "keccak256": "0xa88ed74cd795d2a9a7cbb99f88fa1393c25d7807525c6f081b57d163180f887b", + "urls": [ + "bzz-raw://5e045ea6313140813d515f5ceb43624cba08cfd14657445a731ba76a1e8252f1", + "dweb:/ipfs/Qmb4kfWzbV3gVjrhfVo2PphCijTXxdBUvz9N1mV3Mivcd5" + ], + "license": null + }, + "src/abstract/WorldIDImpl.sol": { + "keccak256": "0xccfff2c5d7af4e505ed13b7d46011d5544317343ea92e7beb874e4d69358e6d0", + "urls": [ + "bzz-raw://428860598ca38e42e29892a0b4759c4d3010378f54c3b3e4392f965ff091076e", + "dweb:/ipfs/QmYPjcDRTr1UEeSbS7ssdGjbDHzAqjRNKBsYJqKJWeL8bZ" + ], + "license": "MIT" + }, + "src/data/VerifierLookupTable.sol": { + "keccak256": "0xfd213b79aaec8d205c50ab3ed5c4ebed06ae602ed526a820340adc1c76745fbc", + "urls": [ + "bzz-raw://6af992a56a7cee8124af7f16d74dc8a2a7ae5f8b3059b92d46862e44c3804b83", + "dweb:/ipfs/QmV9bQtJ9PjnwsiiZMUGJANB3znSxJ6ACTqWv9WkQeoeB3" + ], + "license": "MIT" + }, + "src/interfaces/IBaseWorldID.sol": { + "keccak256": "0xcec58605726864d72e35d62c85e002acc98d3f8fa19d01b49fff461c2767c144", + "urls": [ + "bzz-raw://57714fcbceb0497f3fe8906778a837082939489fbb0bd930d015ad6e971913d5", + "dweb:/ipfs/QmQVVmLr9CEkR727ByMF96a8MbwAeB4AQQWvxneg2Avkq8" + ], + "license": "MIT" + }, + "src/interfaces/IBridge.sol": { + "keccak256": "0x0931c789450d21479da5d4de8c6435fca965660f6e1bd746fff958f4c20cf2ac", + "urls": [ + "bzz-raw://0c564b4d4a15e8075555077a043d773bb20133548376402ff3dbc0eccb57435d", + "dweb:/ipfs/QmXQRihAFdtfyjTNeHmx9nmNHiS1wy2658Y5aXCXo2tKSQ" + ], + "license": "MIT" + }, + "src/interfaces/ITreeVerifier.sol": { + "keccak256": "0xb572aeae7331d96981d46b0dd4408db9ad507a06a2dbf0624386114b2244c8ad", + "urls": [ + "bzz-raw://6159630f78e9e0b3a326d064772713f8c1e73172718c2a6d5af1fb36b35c5991", + "dweb:/ipfs/QmPN5VyQvonPfPdTvrmP5wqsFT3QNW3RwC8DHYdEtwXZT4" + ], + "license": "MIT" + }, + "src/interfaces/IWorldID.sol": { + "keccak256": "0x577908eff2d29d96354a06ab2602ffe6b97aa9d491330efcc2fcd0a88a8acbb1", + "urls": [ + "bzz-raw://fa0a36a598a851b88cff364b4211dc32081f51940aa8076d9c9b7de8ab126b2f", + "dweb:/ipfs/QmSne8aRiE8C8RuwEUSk4doETKAGaavrEYyUkwiJc5H8qc" + ], + "license": "MIT" + }, + "src/utils/CheckInitialized.sol": { + "keccak256": "0xfab096b633efd580548007e97920f6088e6d8a5287db84b9aa3d595c02fefcf4", + "urls": [ + "bzz-raw://dee612c9dbad59d535e7a72b79191187fd91c06af9cb5b6f68d60274d0ee2c04", + "dweb:/ipfs/QmVJbSQ8DAN6igasbgHjZTM4NRZ3EjrhK8wFcvUG1wPYtZ" + ], + "license": "MIT" + }, + "src/utils/SemaphoreTreeDepthValidator.sol": { + "keccak256": "0x50140161de381aa963457cfd2ee8831a435bd79040f38794e6ef07365c49c872", + "urls": [ + "bzz-raw://bcc5b8a3a6f5146aa3fdee550c3e80d828b55df63223485da3d5655a591ad661", + "dweb:/ipfs/QmWfUzbeFoSaPV1E8QxagUnpt5zfmPXgiropUg1GcV6oZs" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "src/WorldIDIdentityManagerImplV2.sol", + "id": 34136, + "exportedSymbols": { + "IBridge": [ + 34450 + ], + "ISemaphoreVerifier": [ + 32716 + ], + "ITreeVerifier": [ + 34478 + ], + "IWorldID": [ + 34502 + ], + "SemaphoreTreeDepthValidator": [ + 47908 + ], + "VerifierLookupTable": [ + 34425 + ], + "WorldIDIdentityManagerImplV1": [ + 33896 + ], + "WorldIDIdentityManagerImplV2": [ + 34135 + ], + "WorldIDImpl": [ + 34190 + ] + }, + "nodeType": "SourceUnit", + "src": "0:12051:43", + "nodes": [ + { + "id": 33898, + "nodeType": "PragmaDirective", + "src": "0:24:43", + "nodes": [], + "literals": [ + "solidity", + "^", + "0.8", + ".21" + ] + }, + { + "id": 33899, + "nodeType": "ImportDirective", + "src": "26:44:43", + "nodes": [], + "absolutePath": "src/WorldIDIdentityManagerImplV1.sol", + "file": "./WorldIDIdentityManagerImplV1.sol", + "nameLocation": "-1:-1:-1", + "scope": 34136, + "sourceUnit": 33897, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 34135, + "nodeType": "ContractDefinition", + "src": "443:11607:43", + "nodes": [ + { + "id": 33906, + "nodeType": "VariableDeclaration", + "src": "3108:51:43", + "nodes": [], + "constant": false, + "documentation": { + "id": 33903, + "nodeType": "StructuredDocumentation", + "src": "3029:74:43", + "text": "@notice The table of verifiers for verifying batch identity deletions." + }, + "mutability": "mutable", + "name": "batchDeletionVerifiers", + "nameLocation": "3137:22:43", + "scope": 34135, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 33905, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 33904, + "name": "VerifierLookupTable", + "nameLocations": [ + "3108:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "3108:19:43" + }, + "referencedDeclaration": 34425, + "src": "3108:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + }, + { + "id": 33921, + "nodeType": "FunctionDefinition", + "src": "3800:152:43", + "nodes": [], + "body": { + "id": 33920, + "nodeType": "Block", + "src": "3889:63:43", + "nodes": [], + "statements": [ + { + "expression": { + "id": 33918, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 33916, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "3899:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 33917, + "name": "_batchUpdateVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33910, + "src": "3924:21:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "src": "3899:46:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "id": 33919, + "nodeType": "ExpressionStatement", + "src": "3899:46:43" + } + ] + }, + "documentation": { + "id": 33907, + "nodeType": "StructuredDocumentation", + "src": "3166:629:43", + "text": "@notice Initializes the V2 implementation contract.\n @dev Must be called exactly once\n @dev This is marked `reinitializer()` to allow for updated initialisation steps when working\n with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed)\n initialisations allowed, so decide carefully when to use them. Many cases can safely be\n replaced by use of setters.\n @dev This function is explicitly not virtual as it does not make sense to override even when\n upgrading. Create a separate initializer function instead." + }, + "functionSelector": "29b6eca9", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": [ + { + "hexValue": "32", + "id": 33913, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3886:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + } + ], + "id": 33914, + "kind": "modifierInvocation", + "modifierName": { + "id": 33912, + "name": "reinitializer", + "nameLocations": [ + "3872:13:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29736, + "src": "3872:13:43" + }, + "nodeType": "ModifierInvocation", + "src": "3872:16:43" + } + ], + "name": "initializeV2", + "nameLocation": "3809:12:43", + "parameters": { + "id": 33911, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 33910, + "mutability": "mutable", + "name": "_batchUpdateVerifiers", + "nameLocation": "3842:21:43", + "nodeType": "VariableDeclaration", + "scope": 33921, + "src": "3822:41:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 33909, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 33908, + "name": "VerifierLookupTable", + "nameLocations": [ + "3822:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "3822:19:43" + }, + "referencedDeclaration": 34425, + "src": "3822:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + } + ], + "src": "3821:43:43" + }, + "returnParameters": { + "id": 33915, + "nodeType": "ParameterList", + "parameters": [], + "src": "3889:0:43" + }, + "scope": 34135, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 34062, + "nodeType": "FunctionDefinition", + "src": "6380:2438:43", + "nodes": [], + "body": { + "id": 34061, + "nodeType": "Block", + "src": "6640:2178:43", + "nodes": [], + "statements": [ + { + "condition": { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 33945, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 33943, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "6654:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "id": 33944, + "name": "_latestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32764, + "src": "6665:11:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6654:22:43", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 33952, + "nodeType": "IfStatement", + "src": "6650:95:43", + "trueBody": { + "id": 33951, + "nodeType": "Block", + "src": "6678:67:43", + "statements": [ + { + "errorCall": { + "arguments": [ + { + "id": 33947, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "6713:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "id": 33948, + "name": "_latestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32764, + "src": "6722:11:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 33946, + "name": "NotLatestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32868, + "src": "6699:13:43", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$_t_uint256_$_t_uint256_$returns$__$", + "typeString": "function (uint256,uint256) pure" + } + }, + "id": 33949, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "6699:35:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 33950, + "nodeType": "RevertStatement", + "src": "6692:42:43" + } + ] + } + }, + { + "assignments": [ + 33954 + ], + "declarations": [ + { + "constant": false, + "id": 33954, + "mutability": "mutable", + "name": "inputHash", + "nameLocation": "6844:9:43", + "nodeType": "VariableDeclaration", + "scope": 34061, + "src": "6836:17:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 33953, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "6836:7:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "id": 33961, + "initialValue": { + "arguments": [ + { + "id": 33956, + "name": "packedDeletionIndices", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33930, + "src": "6903:21:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + { + "id": 33957, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "6926:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "id": 33958, + "name": "postRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33934, + "src": "6935:8:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "id": 33959, + "name": "batchSize", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33928, + "src": "6945:9:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + ], + "id": 33955, + "name": "calculateIdentityDeletionInputHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34134, + "src": "6868:34:43", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_bytes_calldata_ptr_$_t_uint256_$_t_uint256_$_t_uint32_$returns$_t_bytes32_$", + "typeString": "function (bytes calldata,uint256,uint256,uint32) view returns (bytes32)" + } + }, + "id": 33960, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "6868:87:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6836:119:43" + }, + { + "assignments": [ + 33963 + ], + "declarations": [ + { + "constant": false, + "id": 33963, + "mutability": "mutable", + "name": "reducedElement", + "nameLocation": "7234:14:43", + "nodeType": "VariableDeclaration", + "scope": 34061, + "src": "7226:22:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33962, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7226:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 33970, + "initialValue": { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 33969, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "arguments": [ + { + "id": 33966, + "name": "inputHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33954, + "src": "7259:9:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "id": 33965, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "7251:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 33964, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7251:7:43", + "typeDescriptions": {} + } + }, + "id": 33967, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7251:18:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "%", + "rightExpression": { + "id": 33968, + "name": "SNARK_SCALAR_FIELD", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32776, + "src": "7272:18:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7251:39:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7226:64:43" + }, + { + "assignments": [ + 33973 + ], + "declarations": [ + { + "constant": false, + "id": 33973, + "mutability": "mutable", + "name": "deletionVerifier", + "nameLocation": "7388:16:43", + "nodeType": "VariableDeclaration", + "scope": 34061, + "src": "7374:30:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + }, + "typeName": { + "id": 33972, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 33971, + "name": "ITreeVerifier", + "nameLocations": [ + "7374:13:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34478, + "src": "7374:13:43" + }, + "referencedDeclaration": 34478, + "src": "7374:13:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + } + }, + "visibility": "internal" + } + ], + "id": 33978, + "initialValue": { + "arguments": [ + { + "id": 33976, + "name": "batchSize", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33928, + "src": "7445:9:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + ], + "expression": { + "id": 33974, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "7407:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "id": 33975, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "7430:14:43", + "memberName": "getVerifierFor", + "nodeType": "MemberAccess", + "referencedDeclaration": 34297, + "src": "7407:37:43", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_uint256_$returns$_t_contract$_ITreeVerifier_$34478_$", + "typeString": "function (uint256) view external returns (contract ITreeVerifier)" + } + }, + "id": 33977, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7407:48:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7374:81:43" + }, + { + "clauses": [ + { + "block": { + "id": 34044, + "nodeType": "Block", + "src": "7813:634:43", + "statements": [ + { + "condition": { + "id": 34017, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "7901:15:43", + "subExpression": { + "id": 34016, + "name": "verifierResult", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34014, + "src": "7902:14:43", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 34022, + "nodeType": "IfStatement", + "src": "7897:85:43", + "trueBody": { + "id": 34021, + "nodeType": "Block", + "src": "7918:64:43", + "statements": [ + { + "errorCall": { + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 34018, + "name": "ProofValidationFailure", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32861, + "src": "7943:22:43", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 34019, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7943:24:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34020, + "nodeType": "RevertStatement", + "src": "7936:31:43" + } + ] + } + }, + { + "expression": { + "id": 34025, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 34023, + "name": "_latestRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32764, + "src": "8150:11:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 34024, + "name": "postRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33934, + "src": "8164:8:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "8150:22:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 34026, + "nodeType": "ExpressionStatement", + "src": "8150:22:43" + }, + { + "expression": { + "id": 34035, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "baseExpression": { + "id": 34027, + "name": "rootHistory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32769, + "src": "8318:11:43", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint128_$", + "typeString": "mapping(uint256 => uint128)" + } + }, + "id": 34029, + "indexExpression": { + "id": 34028, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "8330:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "8318:20:43", + "typeDescriptions": { + "typeIdentifier": "t_uint128", + "typeString": "uint128" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "arguments": [ + { + "expression": { + "id": 34032, + "name": "block", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -4, + "src": "8349:5:43", + "typeDescriptions": { + "typeIdentifier": "t_magic_block", + "typeString": "block" + } + }, + "id": 34033, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "8355:9:43", + "memberName": "timestamp", + "nodeType": "MemberAccess", + "src": "8349:15:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 34031, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8341:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint128_$", + "typeString": "type(uint128)" + }, + "typeName": { + "id": 34030, + "name": "uint128", + "nodeType": "ElementaryTypeName", + "src": "8341:7:43", + "typeDescriptions": {} + } + }, + "id": 34034, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8341:24:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint128", + "typeString": "uint128" + } + }, + "src": "8318:47:43", + "typeDescriptions": { + "typeIdentifier": "t_uint128", + "typeString": "uint128" + } + }, + "id": 34036, + "nodeType": "ExpressionStatement", + "src": "8318:47:43" + }, + { + "eventCall": { + "arguments": [ + { + "id": 34038, + "name": "preRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33932, + "src": "8397:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "expression": { + "id": 34039, + "name": "TreeChange", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32819, + "src": "8406:10:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_TreeChange_$32819_$", + "typeString": "type(enum WorldIDIdentityManagerImplV1.TreeChange)" + } + }, + "id": 34040, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "8417:8:43", + "memberName": "Deletion", + "nodeType": "MemberAccess", + "referencedDeclaration": 32817, + "src": "8406:19:43", + "typeDescriptions": { + "typeIdentifier": "t_enum$_TreeChange_$32819", + "typeString": "enum WorldIDIdentityManagerImplV1.TreeChange" + } + }, + { + "id": 34041, + "name": "postRoot", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33934, + "src": "8427:8:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_enum$_TreeChange_$32819", + "typeString": "enum WorldIDIdentityManagerImplV1.TreeChange" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 34037, + "name": "TreeChanged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32895, + "src": "8385:11:43", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_enum$_TreeChange_$32819_$_t_uint256_$returns$__$", + "typeString": "function (uint256,enum WorldIDIdentityManagerImplV1.TreeChange,uint256)" + } + }, + "id": 34042, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8385:51:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34043, + "nodeType": "EmitStatement", + "src": "8380:56:43" + } + ] + }, + "errorName": "", + "id": 34045, + "nodeType": "TryCatchClause", + "parameters": { + "id": 34015, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34014, + "mutability": "mutable", + "name": "verifierResult", + "nameLocation": "7797:14:43", + "nodeType": "VariableDeclaration", + "scope": 34045, + "src": "7792:19:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 34013, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "7792:4:43", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "src": "7791:21:43" + }, + "src": "7783:664:43" + }, + { + "block": { + "id": 34053, + "nodeType": "Block", + "src": "8485:100:43", + "statements": [ + { + "documentation": "This is not the revert we're looking for.", + "expression": { + "arguments": [ + { + "id": 34050, + "name": "errString", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34047, + "src": "8564:9:43", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 34049, + "name": "revert", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -19, + -19 + ], + "referencedDeclaration": -19, + "src": "8557:6:43", + "typeDescriptions": { + "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", + "typeString": "function (string memory) pure" + } + }, + "id": 34051, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8557:17:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34052, + "nodeType": "ExpressionStatement", + "src": "8557:17:43" + } + ] + }, + "errorName": "Error", + "id": 34054, + "nodeType": "TryCatchClause", + "parameters": { + "id": 34048, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34047, + "mutability": "mutable", + "name": "errString", + "nameLocation": "8474:9:43", + "nodeType": "VariableDeclaration", + "scope": 34054, + "src": "8460:23:43", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 34046, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "8460:6:43", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "8459:25:43" + }, + "src": "8448:137:43" + }, + { + "block": { + "id": 34058, + "nodeType": "Block", + "src": "8592:220:43", + "statements": [ + { + "errorCall": { + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 34055, + "name": "ProofValidationFailure", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32861, + "src": "8777:22:43", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 34056, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "8777:24:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34057, + "nodeType": "RevertStatement", + "src": "8770:31:43" + } + ] + }, + "errorName": "", + "id": 34059, + "nodeType": "TryCatchClause", + "src": "8586:226:43" + } + ], + "externalCall": { + "arguments": [ + { + "components": [ + { + "baseExpression": { + "id": 33981, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7567:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33983, + "indexExpression": { + "hexValue": "30", + "id": 33982, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7581:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7567:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 33984, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7585:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33986, + "indexExpression": { + "hexValue": "31", + "id": 33985, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7599:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7585:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 33987, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7566:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + }, + { + "components": [ + { + "components": [ + { + "baseExpression": { + "id": 33988, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7618:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33990, + "indexExpression": { + "hexValue": "32", + "id": 33989, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7632:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7618:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 33991, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7636:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33993, + "indexExpression": { + "hexValue": "33", + "id": 33992, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7650:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + }, + "value": "3" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7636:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 33994, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7617:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + }, + { + "components": [ + { + "baseExpression": { + "id": 33995, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7656:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 33997, + "indexExpression": { + "hexValue": "34", + "id": 33996, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7670:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_4_by_1", + "typeString": "int_const 4" + }, + "value": "4" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7656:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 33998, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7674:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 34000, + "indexExpression": { + "hexValue": "35", + "id": 33999, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7688:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_5_by_1", + "typeString": "int_const 5" + }, + "value": "5" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7674:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 34001, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7655:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + } + ], + "id": 34002, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7616:76:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", + "typeString": "uint256[2] memory[2] memory" + } + }, + { + "components": [ + { + "baseExpression": { + "id": 34003, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7707:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 34005, + "indexExpression": { + "hexValue": "36", + "id": 34004, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7721:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_6_by_1", + "typeString": "int_const 6" + }, + "value": "6" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7707:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "baseExpression": { + "id": 34006, + "name": "deletionProof", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33926, + "src": "7725:13:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8] calldata" + } + }, + "id": 34008, + "indexExpression": { + "hexValue": "37", + "id": 34007, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7739:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_7_by_1", + "typeString": "int_const 7" + }, + "value": "7" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7725:16:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 34009, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7706:36:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + } + }, + { + "components": [ + { + "id": 34010, + "name": "reducedElement", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33963, + "src": "7757:14:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 34011, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "7756:16:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", + "typeString": "uint256[1] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + }, + { + "typeIdentifier": "t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr", + "typeString": "uint256[2] memory[2] memory" + }, + { + "typeIdentifier": "t_array$_t_uint256_$2_memory_ptr", + "typeString": "uint256[2] memory" + }, + { + "typeIdentifier": "t_array$_t_uint256_$1_memory_ptr", + "typeString": "uint256[1] memory" + } + ], + "expression": { + "id": 33979, + "name": "deletionVerifier", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33973, + "src": "7524:16:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITreeVerifier_$34478", + "typeString": "contract ITreeVerifier" + } + }, + "id": 33980, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "7541:11:43", + "memberName": "verifyProof", + "nodeType": "MemberAccess", + "referencedDeclaration": 34477, + "src": "7524:28:43", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_array$_t_uint256_$2_memory_ptr_$2_memory_ptr_$_t_array$_t_uint256_$2_memory_ptr_$_t_array$_t_uint256_$1_memory_ptr_$returns$_t_bool_$", + "typeString": "function (uint256[2] memory,uint256[2] memory[2] memory,uint256[2] memory,uint256[1] memory) external returns (bool)" + } + }, + "id": 34012, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "7524:258:43", + "tryCall": true, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 34060, + "nodeType": "TryStatement", + "src": "7520:1292:43" + } + ] + }, + "documentation": { + "id": 33922, + "nodeType": "StructuredDocumentation", + "src": "4175:2200:43", + "text": "@notice Deletes identities from the WorldID system.\n @dev Can only be called by the owner.\n @dev Deletion is performed off-chain and verified on-chain via the `deletionProof`.\n This saves gas and time over deleting identities one at a time.\n @param deletionProof The proof that given the conditions (`preRoot` and `packedDeletionIndices`),\n deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y`\n coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`,\n and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x`\n and `y` coordinates for `krs`.\n @param batchSize The number of identities that are to be deleted in the current batch.\n @param packedDeletionIndices The indices of the identities that were deleted from the tree.\n @param preRoot The value for the root of the tree before the `identityCommitments` have been\n inserted. Must be an element of the field `Kr`.\n @param postRoot The root obtained after deleting all of `identityCommitments` into the tree\n described by `preRoot`. Must be an element of the field `Kr`.\n @custom:reverts Unauthorized If the message sender is not authorised to add identities.\n @custom:reverts InvalidCommitment If one or more of the provided commitments is invalid.\n @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root.\n @custom:reverts ProofValidationFailure If `deletionProof` cannot be verified using the\n provided inputs.\n @custom:reverts UnreducedElement If any of the `preRoot`, `postRoot` and\n `identityCommitments` is not an element of the field `Kr`. It describes the\n type and value of the unreduced element.\n @custom:reverts VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known\n verifier.\n @custom:reverts VerifierLookupTable.BatchTooLarge If the batch size exceeds the maximum\n batch size." + }, + "functionSelector": "23cfdba5", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 33937, + "kind": "modifierInvocation", + "modifierName": { + "id": 33936, + "name": "onlyProxy", + "nameLocations": [ + "6593:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "6593:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "6593:9:43" + }, + { + "id": 33939, + "kind": "modifierInvocation", + "modifierName": { + "id": 33938, + "name": "onlyInitialized", + "nameLocations": [ + "6603:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "6603:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "6603:15:43" + }, + { + "id": 33941, + "kind": "modifierInvocation", + "modifierName": { + "id": 33940, + "name": "onlyIdentityOperator", + "nameLocations": [ + "6619:20:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 33895, + "src": "6619:20:43" + }, + "nodeType": "ModifierInvocation", + "src": "6619:20:43" + } + ], + "name": "deleteIdentities", + "nameLocation": "6389:16:43", + "parameters": { + "id": 33935, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 33926, + "mutability": "mutable", + "name": "deletionProof", + "nameLocation": "6435:13:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6415:33:43", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_calldata_ptr", + "typeString": "uint256[8]" + }, + "typeName": { + "baseType": { + "id": 33923, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6415:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 33925, + "length": { + "hexValue": "38", + "id": 33924, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6423:1:43", + "typeDescriptions": { + "typeIdentifier": "t_rational_8_by_1", + "typeString": "int_const 8" + }, + "value": "8" + }, + "nodeType": "ArrayTypeName", + "src": "6415:10:43", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$8_storage_ptr", + "typeString": "uint256[8]" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33928, + "mutability": "mutable", + "name": "batchSize", + "nameLocation": "6465:9:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6458:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + }, + "typeName": { + "id": 33927, + "name": "uint32", + "nodeType": "ElementaryTypeName", + "src": "6458:6:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33930, + "mutability": "mutable", + "name": "packedDeletionIndices", + "nameLocation": "6499:21:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6484:36:43", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 33929, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "6484:5:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33932, + "mutability": "mutable", + "name": "preRoot", + "nameLocation": "6538:7:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6530:15:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33931, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6530:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 33934, + "mutability": "mutable", + "name": "postRoot", + "nameLocation": "6563:8:43", + "nodeType": "VariableDeclaration", + "scope": 34062, + "src": "6555:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33933, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6555:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "6405:172:43" + }, + "returnParameters": { + "id": 33942, + "nodeType": "ParameterList", + "parameters": [], + "src": "6640:0:43" + }, + "scope": 34135, + "stateMutability": "nonpayable", + "virtual": true, + "visibility": "public" + }, + { + "id": 34078, + "nodeType": "FunctionDefinition", + "src": "9156:228:43", + "nodes": [], + "body": { + "id": 34077, + "nodeType": "Block", + "src": "9329:55:43", + "nodes": [], + "statements": [ + { + "expression": { + "arguments": [ + { + "id": 34074, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "9354:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + ], + "id": 34073, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "9346:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 34072, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9346:7:43", + "typeDescriptions": {} + } + }, + "id": 34075, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "9346:31:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 34071, + "id": 34076, + "nodeType": "Return", + "src": "9339:38:43" + } + ] + }, + "documentation": { + "id": 34063, + "nodeType": "StructuredDocumentation", + "src": "8824:327:43", + "text": "@notice Gets the address for the lookup table of merkle tree verifiers used for batch identity\n deletions.\n @dev The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch.\n @return addr The address of the contract being used as the verifier lookup table." + }, + "functionSelector": "3e8919b6", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 34066, + "kind": "modifierInvocation", + "modifierName": { + "id": 34065, + "name": "onlyProxy", + "nameLocations": [ + "9265:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "9265:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "9265:9:43" + }, + { + "id": 34068, + "kind": "modifierInvocation", + "modifierName": { + "id": 34067, + "name": "onlyInitialized", + "nameLocations": [ + "9283:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "9283:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "9283:15:43" + } + ], + "name": "getDeleteIdentitiesVerifierLookupTableAddress", + "nameLocation": "9165:45:43", + "parameters": { + "id": 34064, + "nodeType": "ParameterList", + "parameters": [], + "src": "9210:2:43" + }, + "returnParameters": { + "id": 34071, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34070, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 34078, + "src": "9316:7:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 34069, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9316:7:43", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "9315:9:43" + }, + "scope": 34135, + "stateMutability": "view", + "virtual": true, + "visibility": "public" + }, + { + "id": 34114, + "nodeType": "FunctionDefinition", + "src": "9704:418:43", + "nodes": [], + "body": { + "id": 34113, + "nodeType": "Block", + "src": "9877:245:43", + "nodes": [], + "statements": [ + { + "assignments": [ + 34093 + ], + "declarations": [ + { + "constant": false, + "id": 34093, + "mutability": "mutable", + "name": "oldTable", + "nameLocation": "9907:8:43", + "nodeType": "VariableDeclaration", + "scope": 34113, + "src": "9887:28:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 34092, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 34091, + "name": "VerifierLookupTable", + "nameLocations": [ + "9887:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "9887:19:43" + }, + "referencedDeclaration": 34425, + "src": "9887:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + } + ], + "id": 34095, + "initialValue": { + "id": 34094, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "9918:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "9887:53:43" + }, + { + "expression": { + "id": 34098, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 34096, + "name": "batchDeletionVerifiers", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33906, + "src": "9950:22:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 34097, + "name": "newTable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34082, + "src": "9975:8:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "src": "9950:33:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "id": 34099, + "nodeType": "ExpressionStatement", + "src": "9950:33:43" + }, + { + "eventCall": { + "arguments": [ + { + "expression": { + "id": 34101, + "name": "Dependency", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32826, + "src": "10029:10:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_Dependency_$32826_$", + "typeString": "type(enum WorldIDIdentityManagerImplV1.Dependency)" + } + }, + "id": 34102, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "10040:27:43", + "memberName": "DeletionVerifierLookupTable", + "nodeType": "MemberAccess", + "referencedDeclaration": 32823, + "src": "10029:38:43", + "typeDescriptions": { + "typeIdentifier": "t_enum$_Dependency_$32826", + "typeString": "enum WorldIDIdentityManagerImplV1.Dependency" + } + }, + { + "arguments": [ + { + "id": 34105, + "name": "oldTable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34093, + "src": "10077:8:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + ], + "id": 34104, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "10069:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 34103, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10069:7:43", + "typeDescriptions": {} + } + }, + "id": 34106, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "10069:17:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "arguments": [ + { + "id": 34109, + "name": "newTable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34082, + "src": "10096:8:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + ], + "id": 34108, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "10088:7:43", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 34107, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10088:7:43", + "typeDescriptions": {} + } + }, + "id": 34110, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "10088:17:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_enum$_Dependency_$32826", + "typeString": "enum WorldIDIdentityManagerImplV1.Dependency" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 34100, + "name": "DependencyUpdated", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32905, + "src": "9998:17:43", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_enum$_Dependency_$32826_$_t_address_$_t_address_$returns$__$", + "typeString": "function (enum WorldIDIdentityManagerImplV1.Dependency,address,address)" + } + }, + "id": 34111, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "9998:117:43", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 34112, + "nodeType": "EmitStatement", + "src": "9993:122:43" + } + ] + }, + "documentation": { + "id": 34079, + "nodeType": "StructuredDocumentation", + "src": "9390:309:43", + "text": "@notice Sets the address for the lookup table of merkle tree verifiers used for identity\n deletions.\n @dev Only the owner of the contract can call this function.\n @param newTable The new verifier lookup table to be used for verifying identity\n deletions." + }, + "functionSelector": "aa4a729e", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 34085, + "kind": "modifierInvocation", + "modifierName": { + "id": 34084, + "name": "onlyProxy", + "nameLocations": [ + "9821:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "9821:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "9821:9:43" + }, + { + "id": 34087, + "kind": "modifierInvocation", + "modifierName": { + "id": 34086, + "name": "onlyInitialized", + "nameLocations": [ + "9839:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "9839:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "9839:15:43" + }, + { + "id": 34089, + "kind": "modifierInvocation", + "modifierName": { + "id": 34088, + "name": "onlyOwner", + "nameLocations": [ + "9863:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29157, + "src": "9863:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "9863:9:43" + } + ], + "name": "setDeleteIdentitiesVerifierLookupTable", + "nameLocation": "9713:38:43", + "parameters": { + "id": 34083, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34082, + "mutability": "mutable", + "name": "newTable", + "nameLocation": "9772:8:43", + "nodeType": "VariableDeclaration", + "scope": 34114, + "src": "9752:28:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + }, + "typeName": { + "id": 34081, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 34080, + "name": "VerifierLookupTable", + "nameLocations": [ + "9752:19:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 34425, + "src": "9752:19:43" + }, + "referencedDeclaration": 34425, + "src": "9752:19:43", + "typeDescriptions": { + "typeIdentifier": "t_contract$_VerifierLookupTable_$34425", + "typeString": "contract VerifierLookupTable" + } + }, + "visibility": "internal" + } + ], + "src": "9751:30:43" + }, + "returnParameters": { + "id": 34090, + "nodeType": "ParameterList", + "parameters": [], + "src": "9877:0:43" + }, + "scope": 34135, + "stateMutability": "nonpayable", + "virtual": true, + "visibility": "public" + }, + { + "id": 34134, + "nodeType": "FunctionDefinition", + "src": "11363:685:43", + "nodes": [], + "body": { + "id": 34133, + "nodeType": "Block", + "src": "11605:443:43", + "nodes": [], + "statements": [ + { + "AST": { + "nativeSrc": "11624:418:43", + "nodeType": "YulBlock", + "src": "11624:418:43", + "statements": [ + { + "nativeSrc": "11638:30:43", + "nodeType": "YulVariableDeclaration", + "src": "11638:30:43", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "11663:4:43", + "nodeType": "YulLiteral", + "src": "11663:4:43", + "type": "", + "value": "0x40" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "11657:5:43", + "nodeType": "YulIdentifier", + "src": "11657:5:43" + }, + "nativeSrc": "11657:11:43", + "nodeType": "YulFunctionCall", + "src": "11657:11:43" + }, + "variables": [ + { + "name": "startOffset", + "nativeSrc": "11642:11:43", + "nodeType": "YulTypedName", + "src": "11642:11:43", + "type": "" + } + ] + }, + { + "nativeSrc": "11681:40:43", + "nodeType": "YulVariableDeclaration", + "src": "11681:40:43", + "value": { + "arguments": [ + { + "name": "batchSize", + "nativeSrc": "11708:9:43", + "nodeType": "YulIdentifier", + "src": "11708:9:43" + }, + { + "kind": "number", + "nativeSrc": "11719:1:43", + "nodeType": "YulLiteral", + "src": "11719:1:43", + "type": "", + "value": "4" + } + ], + "functionName": { + "name": "mul", + "nativeSrc": "11704:3:43", + "nodeType": "YulIdentifier", + "src": "11704:3:43" + }, + "nativeSrc": "11704:17:43", + "nodeType": "YulFunctionCall", + "src": "11704:17:43" + }, + "variables": [ + { + "name": "indicesByteSize", + "nativeSrc": "11685:15:43", + "nodeType": "YulTypedName", + "src": "11685:15:43", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "startOffset", + "nativeSrc": "11747:11:43", + "nodeType": "YulIdentifier", + "src": "11747:11:43" + }, + { + "name": "packedDeletionIndices.offset", + "nativeSrc": "11760:28:43", + "nodeType": "YulIdentifier", + "src": "11760:28:43" + }, + { + "name": "indicesByteSize", + "nativeSrc": "11790:15:43", + "nodeType": "YulIdentifier", + "src": "11790:15:43" + } + ], + "functionName": { + "name": "calldatacopy", + "nativeSrc": "11734:12:43", + "nodeType": "YulIdentifier", + "src": "11734:12:43" + }, + "nativeSrc": "11734:72:43", + "nodeType": "YulFunctionCall", + "src": "11734:72:43" + }, + "nativeSrc": "11734:72:43", + "nodeType": "YulExpressionStatement", + "src": "11734:72:43" + }, + { + "nativeSrc": "11819:52:43", + "nodeType": "YulVariableDeclaration", + "src": "11819:52:43", + "value": { + "arguments": [ + { + "name": "startOffset", + "nativeSrc": "11842:11:43", + "nodeType": "YulIdentifier", + "src": "11842:11:43" + }, + { + "name": "indicesByteSize", + "nativeSrc": "11855:15:43", + "nodeType": "YulIdentifier", + "src": "11855:15:43" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "11838:3:43", + "nodeType": "YulIdentifier", + "src": "11838:3:43" + }, + "nativeSrc": "11838:33:43", + "nodeType": "YulFunctionCall", + "src": "11838:33:43" + }, + "variables": [ + { + "name": "rootsOffset", + "nativeSrc": "11823:11:43", + "nodeType": "YulTypedName", + "src": "11823:11:43", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "rootsOffset", + "nativeSrc": "11891:11:43", + "nodeType": "YulIdentifier", + "src": "11891:11:43" + }, + { + "name": "preRoot", + "nativeSrc": "11904:7:43", + "nodeType": "YulIdentifier", + "src": "11904:7:43" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "11884:6:43", + "nodeType": "YulIdentifier", + "src": "11884:6:43" + }, + "nativeSrc": "11884:28:43", + "nodeType": "YulFunctionCall", + "src": "11884:28:43" + }, + "nativeSrc": "11884:28:43", + "nodeType": "YulExpressionStatement", + "src": "11884:28:43" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "rootsOffset", + "nativeSrc": "11936:11:43", + "nodeType": "YulIdentifier", + "src": "11936:11:43" + }, + { + "kind": "number", + "nativeSrc": "11949:2:43", + "nodeType": "YulLiteral", + "src": "11949:2:43", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "11932:3:43", + "nodeType": "YulIdentifier", + "src": "11932:3:43" + }, + "nativeSrc": "11932:20:43", + "nodeType": "YulFunctionCall", + "src": "11932:20:43" + }, + { + "name": "postRoot", + "nativeSrc": "11954:8:43", + "nodeType": "YulIdentifier", + "src": "11954:8:43" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "11925:6:43", + "nodeType": "YulIdentifier", + "src": "11925:6:43" + }, + "nativeSrc": "11925:38:43", + "nodeType": "YulFunctionCall", + "src": "11925:38:43" + }, + "nativeSrc": "11925:38:43", + "nodeType": "YulExpressionStatement", + "src": "11925:38:43" + }, + { + "nativeSrc": "11976:56:43", + "nodeType": "YulAssignment", + "src": "11976:56:43", + "value": { + "arguments": [ + { + "name": "startOffset", + "nativeSrc": "11994:11:43", + "nodeType": "YulIdentifier", + "src": "11994:11:43" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "12011:2:43", + "nodeType": "YulLiteral", + "src": "12011:2:43", + "type": "", + "value": "64" + }, + { + "name": "indicesByteSize", + "nativeSrc": "12015:15:43", + "nodeType": "YulIdentifier", + "src": "12015:15:43" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "12007:3:43", + "nodeType": "YulIdentifier", + "src": "12007:3:43" + }, + "nativeSrc": "12007:24:43", + "nodeType": "YulFunctionCall", + "src": "12007:24:43" + } + ], + "functionName": { + "name": "keccak256", + "nativeSrc": "11984:9:43", + "nodeType": "YulIdentifier", + "src": "11984:9:43" + }, + "nativeSrc": "11984:48:43", + "nodeType": "YulFunctionCall", + "src": "11984:48:43" + }, + "variableNames": [ + { + "name": "hash", + "nativeSrc": "11976:4:43", + "nodeType": "YulIdentifier", + "src": "11976:4:43" + } + ] + } + ] + }, + "evmVersion": "paris", + "externalReferences": [ + { + "declaration": 34123, + "isOffset": false, + "isSlot": false, + "src": "11708:9:43", + "valueSize": 1 + }, + { + "declaration": 34130, + "isOffset": false, + "isSlot": false, + "src": "11976:4:43", + "valueSize": 1 + }, + { + "declaration": 34117, + "isOffset": true, + "isSlot": false, + "src": "11760:28:43", + "suffix": "offset", + "valueSize": 1 + }, + { + "declaration": 34121, + "isOffset": false, + "isSlot": false, + "src": "11954:8:43", + "valueSize": 1 + }, + { + "declaration": 34119, + "isOffset": false, + "isSlot": false, + "src": "11904:7:43", + "valueSize": 1 + } + ], + "id": 34132, + "nodeType": "InlineAssembly", + "src": "11615:427:43" + } + ] + }, + "documentation": { + "id": 34115, + "nodeType": "StructuredDocumentation", + "src": "10381:977:43", + "text": "@notice Calculates the input hash for the identity deletion verifier.\n @dev Implements the computation described below.\n @param packedDeletionIndices The indices of the identities that were deleted from the tree.\n @param preRoot The root value of the tree before these insertions were made.\n @param postRoot The root value of the tree after these insertions were made.\n @param batchSize The number of identities that were deleted in this batch\n @return hash The input hash calculated as described below.\n @dev the deletion indices are packed into bytes calldata where each deletion index is 32 bits\n wide. The indices are encoded using abi.encodePacked for testing.\n We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows:\n packedDeletionIndices || PreRoot || PostRoot\n 32 bits * batchSize || 256 || 256" + }, + "functionSelector": "31e4e992", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "id": 34126, + "kind": "modifierInvocation", + "modifierName": { + "id": 34125, + "name": "onlyProxy", + "nameLocations": [ + "11556:9:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 29855, + "src": "11556:9:43" + }, + "nodeType": "ModifierInvocation", + "src": "11556:9:43" + }, + { + "id": 34128, + "kind": "modifierInvocation", + "modifierName": { + "id": 34127, + "name": "onlyInitialized", + "nameLocations": [ + "11566:15:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 47873, + "src": "11566:15:43" + }, + "nodeType": "ModifierInvocation", + "src": "11566:15:43" + } + ], + "name": "calculateIdentityDeletionInputHash", + "nameLocation": "11372:34:43", + "parameters": { + "id": 34124, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34117, + "mutability": "mutable", + "name": "packedDeletionIndices", + "nameLocation": "11431:21:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11416:36:43", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 34116, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "11416:5:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34119, + "mutability": "mutable", + "name": "preRoot", + "nameLocation": "11470:7:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11462:15:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 34118, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "11462:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34121, + "mutability": "mutable", + "name": "postRoot", + "nameLocation": "11495:8:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11487:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 34120, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "11487:7:43", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34123, + "mutability": "mutable", + "name": "batchSize", + "nameLocation": "11520:9:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11513:16:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + }, + "typeName": { + "id": 34122, + "name": "uint32", + "nodeType": "ElementaryTypeName", + "src": "11513:6:43", + "typeDescriptions": { + "typeIdentifier": "t_uint32", + "typeString": "uint32" + } + }, + "visibility": "internal" + } + ], + "src": "11406:129:43" + }, + "returnParameters": { + "id": 34131, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 34130, + "mutability": "mutable", + "name": "hash", + "nameLocation": "11599:4:43", + "nodeType": "VariableDeclaration", + "scope": 34134, + "src": "11591:12:43", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 34129, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "11591:7:43", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "src": "11590:14:43" + }, + "scope": 34135, + "stateMutability": "view", + "virtual": true, + "visibility": "public" + } + ], + "abstract": false, + "baseContracts": [ + { + "baseName": { + "id": 33901, + "name": "WorldIDIdentityManagerImplV1", + "nameLocations": [ + "484:28:43" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 33896, + "src": "484:28:43" + }, + "id": 33902, + "nodeType": "InheritanceSpecifier", + "src": "484:28:43" + } + ], + "canonicalName": "WorldIDIdentityManagerImplV2", + "contractDependencies": [], + "contractKind": "contract", + "documentation": { + "id": 33900, + "nodeType": "StructuredDocumentation", + "src": "72:371:43", + "text": "@title WorldID Identity Manager Implementation Version 2\n @author Worldcoin\n @notice An implementation of a batch-based identity manager for the WorldID protocol.\n @dev The manager is based on the principle of verifying externally-created Zero Knowledge Proofs\n to perform the insertions.\n @dev This is the implementation delegated to by a proxy." + }, + "fullyImplemented": true, + "linearizedBaseContracts": [ + 34135, + 33896, + 34502, + 34435, + 34190, + 47879, + 29937, + 29622, + 29253, + 29111, + 29243, + 30263, + 29801 + ], + "name": "WorldIDIdentityManagerImplV2", + "nameLocation": "452:28:43", + "scope": 34136, + "usedErrors": [ + 32848, + 32853, + 32858, + 32861, + 32868, + 32871, + 32874, + 32877, + 32882, + 32885, + 34166, + 34431, + 34434, + 47850 + ], + "usedEvents": [ + 29037, + 29128, + 29287, + 29431, + 29496, + 29647, + 32895, + 32905, + 32910, + 32917, + 32924, + 32931 + ] + } + ] + }, + "id": 43 +} \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index f276a277..b07e8a48 100644 --- a/src/app.rs +++ b/src/app.rs @@ -326,7 +326,7 @@ impl App { } self.database - .insert_new_identity(commitment, DateTime::from(Utc::now())) + .insert_new_identity(commitment, Utc::now()) .await?; Ok(()) @@ -349,10 +349,14 @@ impl App { return Err(ServerError::NoProversOnIdDeletion); } + if !self.database.identity_exists(*commitment).await? { + return Err(ServerError::IdentityCommitmentNotFound); + } + // Get the leaf index for the id commitment let leaf_index = self .database - .get_identity_leaf_index(&commitment) + .get_identity_leaf_index(commitment) .await? .ok_or(ServerError::IdentityCommitmentNotFound)? .leaf_index; @@ -380,7 +384,7 @@ impl App { // If the id has not been deleted, insert into the deletions table self.database - .insert_new_deletion(leaf_index, &commitment) + .insert_new_deletion(leaf_index, commitment) .await?; Ok(()) @@ -408,10 +412,10 @@ impl App { } // Delete the existing id and insert the commitments into the recovery table - self.delete_identity(&existing_commitment).await?; + self.delete_identity(existing_commitment).await?; self.database - .insert_new_recovery(&existing_commitment, &new_commitment) + .insert_new_recovery(existing_commitment, new_commitment) .await?; Ok(()) @@ -526,7 +530,11 @@ impl App { .await? .ok_or(ServerError::IdentityCommitmentNotFound)?; - let proof = self.tree_state.get_proof_for(&item); + let (leaf, proof) = self.tree_state.get_proof_for(&item); + + if leaf != *commitment { + return Err(ServerError::InvalidCommitment); + } Ok(InclusionProofResponse(proof)) } diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index 8a75934d..0353373b 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -8,7 +8,7 @@ abigen!( struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } event TreeChanged(uint256 indexed preRoot, uint8 indexed kind, uint256 indexed postRoot) function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual - function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, bytes calldata deletionIndices, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint32 batchSize, bytes calldata packedDeletionIndices, uint256 preRoot, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 99285846..03cc0430 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -7,7 +7,6 @@ use std::sync::Arc; use anyhow::anyhow; use clap::Parser; -use ethers::abi::ethabi::Bytes; use ethers::providers::Middleware; use ethers::types::{Address, U256}; use semaphore::Field; @@ -237,7 +236,7 @@ impl IdentityManager { pub async fn prepare_deletion_proof( prover: ReadOnlyProver<'_, Prover>, pre_root: U256, - deletion_indices: &[u32], + packed_deletion_indices: Vec, identity_commitments: Vec, post_root: U256, ) -> anyhow::Result { @@ -248,7 +247,12 @@ impl IdentityManager { ); let proof_data: Proof = prover - .generate_deletion_proof(pre_root, post_root, deletion_indices, identity_commitments) + .generate_deletion_proof( + pre_root, + post_root, + packed_deletion_indices, + identity_commitments, + ) .await?; Ok(proof_data) @@ -296,26 +300,20 @@ impl IdentityManager { pub async fn delete_identities( &self, deletion_proof: Proof, + batch_size: u32, + packed_deletion_indices: Vec, pre_root: U256, - deletion_indices: Vec, post_root: U256, ) -> anyhow::Result { let proof_points_array: [U256; 8] = deletion_proof.into(); - // We want to send the transaction through our ethereum provider rather than - // directly now. To that end, we create it, and then send it later, waiting for - // it to complete. - let deletion_indices = deletion_indices - .iter() - .flat_map(|&idx| idx.to_be_bytes().to_vec()) - .collect::>(); - let register_identities_transaction = self .abi .delete_identities( proof_points_array, + batch_size, + packed_deletion_indices.into(), pre_root, - deletion_indices.into(), post_root, ) .tx; @@ -329,6 +327,7 @@ impl IdentityManager { #[instrument(level = "debug", skip(self))] pub async fn mine_identities(&self, transaction_id: TransactionId) -> anyhow::Result { let result = self.ethereum.mine_transaction(transaction_id).await?; + Ok(result) } diff --git a/src/database/mod.rs b/src/database/mod.rs index 97e3442e..738190d5 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -19,7 +19,7 @@ use self::types::{DeletionEntry, LatestDeletionEntry, RecoveryEntry}; use crate::identity_tree::{Hash, RootItem, Status, TreeItem, TreeUpdate}; pub mod types; -use crate::prover::{self, ProverConfiguration, ProverType, Provers}; +use crate::prover::{ProverConfiguration, ProverType, Provers}; use crate::secret::SecretUrl; // Statically link in migration files @@ -287,6 +287,7 @@ impl Database { SELECT leaf_index, status FROM identities WHERE commitment = $1 + ORDER BY id DESC LIMIT 1; "#, ) @@ -407,12 +408,7 @@ impl Database { let url = row.get::(1); let timeout_s = row.get::(2) as u64; let prover_type = row.get::(3); - ProverConfiguration { - url, - batch_size, - timeout_s, - prover_type, - } + ProverConfiguration { url, timeout_s, batch_size, prover_type } }) .collect::()) } @@ -532,7 +528,7 @@ impl Database { }) } else { Ok(LatestDeletionEntry { - timestamp: DateTime::from(Utc::now()), + timestamp: Utc::now(), }) } } @@ -545,11 +541,11 @@ impl Database { r#" INSERT INTO latest_deletion_root (Lock, deletion_timestamp) VALUES ('X', $1) - ON CONFLICT (Lock) + ON CONFLICT (Lock) DO UPDATE SET deletion_timestamp = EXCLUDED.deletion_timestamp; "#, ) - .bind(&deletion_timestamp); + .bind(deletion_timestamp); self.pool.execute(query).await?; Ok(()) @@ -631,7 +627,7 @@ impl Database { let mut query = sqlx::query(&query); - for commitment in commitments.iter() { + for commitment in &commitments { query = query.bind(commitment); } @@ -775,7 +771,7 @@ mod test { use ruint::Uint; use semaphore::Field; use sqlx::types::chrono::DateTime; - use sqlx::{PgPool, Row}; + use sqlx::{Row}; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; @@ -852,7 +848,7 @@ mod test { .expect("cant convert to u256") .into(); - let eligibility_timestamp = DateTime::from(Utc::now()); + let eligibility_timestamp = Utc::now(); let hash = db .insert_new_identity(commit_hash, eligibility_timestamp) @@ -878,6 +874,28 @@ mod test { Ok(()) } + #[tokio::test] + async fn insert_and_delete_identity() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + + let zero: Hash = U256::zero().into(); + let zero_root: Hash = U256::from_dec_str("6789")?.into(); + let root: Hash = U256::from_dec_str("54321")?.into(); + let commitment: Hash = U256::from_dec_str("12345")?.into(); + + db.insert_pending_identity(0, &commitment, &root).await?; + db.insert_pending_identity(0, &zero, &zero_root).await?; + + let leaf_index = db + .get_identity_leaf_index(&commitment) + .await? + .context("Missing identity")?; + + assert_eq!(leaf_index.leaf_index, 0); + + Ok(()) + } + fn mock_provers() -> HashSet { let mut provers = HashSet::new(); @@ -1005,13 +1023,13 @@ mod test { async fn test_get_eligible_unprocessed_commitments() -> anyhow::Result<()> { let (db, _db_container) = setup_db().await?; let commitment_0: Uint<256, 4> = Uint::from(1); - let eligibility_timestamp_0 = DateTime::from(Utc::now()); + let eligibility_timestamp_0 = Utc::now(); db.insert_new_identity(commitment_0, eligibility_timestamp_0) .await?; let commitment_1: Uint<256, 4> = Uint::from(2); - let eligibility_timestamp_1 = DateTime::from(Utc::now()) + let eligibility_timestamp_1 = Utc::now() .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); @@ -1036,13 +1054,13 @@ mod test { // Insert new identity with a valid eligibility timestamp let commitment_0: Uint<256, 4> = Uint::from(1); - let eligibility_timestamp_0 = DateTime::from(Utc::now()); + let eligibility_timestamp_0 = Utc::now(); db.insert_new_identity(commitment_0, eligibility_timestamp_0) .await?; // Insert new identity with eligibility timestamp in the future let commitment_1: Uint<256, 4> = Uint::from(2); - let eligibility_timestamp_1 = DateTime::from(Utc::now()) + let eligibility_timestamp_1 = Utc::now() .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); db.insert_new_identity(commitment_1, eligibility_timestamp_1) @@ -1057,11 +1075,6 @@ mod test { unprocessed_commitments[0].eligibility_timestamp, eligibility_timestamp_0 ); - assert_eq!(unprocessed_commitments[1].commitment, commitment_1); - assert_eq!( - unprocessed_commitments[1].eligibility_timestamp, - eligibility_timestamp_1 - ); Ok(()) } @@ -1090,7 +1103,7 @@ mod test { .into(); // Set eligibility to Utc::now() day and check db entries - let eligibility_timestamp = DateTime::from(Utc::now()); + let eligibility_timestamp = Utc::now(); db.insert_new_identity(commit_hash, eligibility_timestamp) .await?; @@ -1101,7 +1114,7 @@ mod test { assert_eq!(eligible_commitments.len(), 1); // Set eligibility to Utc::now() + 7 days and check db entries - let eligibility_timestamp = DateTime::from(Utc::now()) + let eligibility_timestamp = Utc::now() .checked_add_days(Days::new(7)) .expect("Could not create eligibility timestamp"); @@ -1516,7 +1529,7 @@ mod test { assert!(!db.identity_exists(identities[0]).await?); // When there's only unprocessed identity - let eligibility_timestamp = DateTime::from(Utc::now()); + let eligibility_timestamp = Utc::now(); db.insert_new_identity(identities[0], eligibility_timestamp) .await diff --git a/src/identity_tree.rs b/src/identity_tree.rs index b6c7629a..fc99df00 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -185,7 +185,7 @@ where /// Gets the leaf value at a given index. fn get_leaf(&self, leaf: usize) -> Hash { - self.get_leaf(leaf) + self.tree.get_leaf(leaf) } /// Gets the proof of the given leaf index element @@ -267,7 +267,9 @@ impl BasicTreeOps for TreeVersionData { take_mut::take(&mut self.tree, |tree| { tree.update_with_mutation(leaf_index, &element) }); - self.next_leaf = leaf_index + 1; + if element != Hash::ZERO { + self.next_leaf = leaf_index + 1; + } self.metadata.count_since_last_flatten += 1; } @@ -319,7 +321,9 @@ impl BasicTreeOps for TreeVersionData { self.tree = updated_tree.clone(); - self.next_leaf = leaf_index + 1; + if element != Hash::ZERO { + self.next_leaf = leaf_index + 1; + } self.metadata.diff.push(AppliedTreeUpdate { update: TreeUpdate { leaf_index, @@ -336,7 +340,10 @@ impl BasicTreeOps for TreeVersionData { if let Some(last) = last { self.tree = last.result.clone(); - self.next_leaf = last.update.leaf_index + 1; + + if last.update.element != Hash::ZERO { + self.next_leaf = last.update.leaf_index + 1; + } } } @@ -422,6 +429,8 @@ pub trait TreeVersionReadOps { fn get_root(&self) -> Hash; /// Returns the next free leaf. fn next_leaf(&self) -> usize; + /// Returns the given leaf value, the root of the tree and the proof + fn get_leaf_and_proof(&self, leaf: usize) -> (Hash, Hash, Proof); /// Returns the merkle proof and element at the given leaf. fn get_proof(&self, leaf: usize) -> (Hash, Proof); /// Gets the leaf value at a given index. @@ -440,6 +449,15 @@ where self.get_data().next_leaf } + fn get_leaf_and_proof(&self, leaf: usize) -> (Hash, Hash, Proof) { + let tree = self.get_data(); + + let (root, proof) = tree.get_proof(leaf); + let leaf = tree.get_leaf(leaf); + + (leaf, root, proof) + } + fn get_proof(&self, leaf: usize) -> (Hash, Proof) { let tree = self.get_data(); tree.get_proof(leaf) @@ -481,6 +499,7 @@ impl TreeVersion { /// Deletes many identities from the tree, returns a list with the root /// and proof of inclusion + #[must_use] pub fn delete_many(&self, leaf_indices: &[usize]) -> Vec<(Hash, Proof)> { let mut data = self.get_data(); @@ -563,21 +582,23 @@ impl TreeState { } #[must_use] - pub fn get_proof_for(&self, item: &TreeItem) -> InclusionProof { - let (root, proof) = match item.status { + pub fn get_proof_for(&self, item: &TreeItem) -> (Field, InclusionProof) { + let (leaf, root, proof) = match item.status { Status::Pending | Status::New | Status::Failed => { - self.latest.get_proof(item.leaf_index) + self.latest.get_leaf_and_proof(item.leaf_index) } - Status::Processed => self.processed.get_proof(item.leaf_index), - Status::Mined => self.mined.get_proof(item.leaf_index), + Status::Processed => self.processed.get_leaf_and_proof(item.leaf_index), + Status::Mined => self.mined.get_leaf_and_proof(item.leaf_index), }; - InclusionProof { + let proof = InclusionProof { status: item.status, root: Some(root), proof: Some(proof), message: None, - } + }; + + (leaf, proof) } } @@ -706,18 +727,13 @@ impl DerivedTreeBuilder

{ #[cfg(test)] mod tests { - use semaphore::lazy_merkle_tree::{Canonical, LazyMerkleTree}; - use semaphore::poseidon_tree::PoseidonHash; - use super::{ - AppliedTreeUpdate, CanonicalTreeBuilder, DerivedTreeBuilder, Hash, PoseidonTree, - TreeVersion, TreeWithNextVersion, - }; + use super::{CanonicalTreeBuilder, Hash, TreeWithNextVersion}; #[test] fn test_peek_next_updates() { let (canonical_tree, processed_builder) = - CanonicalTreeBuilder::new(10, 10, 0, Hash::ZERO, &vec![]).seal(); + CanonicalTreeBuilder::new(10, 10, 0, Hash::ZERO, &[]).seal(); let processed_tree = processed_builder.seal(); let insertion_updates = processed_tree.append_many(&vec![ Hash::from(1), @@ -729,7 +745,7 @@ mod tests { Hash::from(7), ]); - let _deletion_updates = processed_tree.delete_many(&vec![0, 1, 2]); + let _deletion_updates = processed_tree.delete_many(&[0, 1, 2]); let next_updates = canonical_tree.peek_next_updates(10); assert_eq!(next_updates.len(), 7); @@ -741,7 +757,7 @@ mod tests { .0, ); - let _ = processed_tree.append_many(&vec![ + let _ = processed_tree.append_many(&[ Hash::from(5), Hash::from(6), Hash::from(7), diff --git a/src/prover/map.rs b/src/prover/map.rs index 8712b90c..29263374 100644 --- a/src/prover/map.rs +++ b/src/prover/map.rs @@ -1,5 +1,5 @@ use std::collections::BTreeMap; -use std::hash::{Hash, Hasher}; + use tokio::sync::{RwLock, RwLockReadGuard}; diff --git a/src/prover/mod.rs b/src/prover/mod.rs index f1ab1b9c..e0c1b45a 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -12,7 +12,7 @@ pub mod map; pub mod proof; use std::collections::HashSet; -use std::default; + use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; use std::mem::size_of; @@ -250,7 +250,7 @@ impl Prover { &self, pre_root: U256, post_root: U256, - deletion_indices: &[u32], + packed_deletion_indices: Vec, identities: Vec, ) -> anyhow::Result { if identities.len() != self.batch_size { @@ -267,13 +267,13 @@ impl Prover { .unzip(); let input_hash = - compute_deletion_proof_input_hash(pre_root, post_root, &identity_commitments); + compute_deletion_proof_input_hash(packed_deletion_indices.clone(), pre_root, post_root); let proof_input = DeletionProofInput { input_hash, pre_root, post_root, - deletion_indices: deletion_indices.to_vec(), + packed_deletion_indices, identity_commitments, merkle_proofs, }; @@ -354,26 +354,29 @@ pub fn compute_insertion_proof_input_hash( } // TODO: check this and update docs + pub fn compute_deletion_proof_input_hash( + packed_deletion_indices: Vec, pre_root: U256, post_root: U256, - identity_commitments: &[U256], ) -> U256 { - let mut pre_root_bytes: [u8; size_of::()] = Default::default(); - pre_root.to_big_endian(pre_root_bytes.as_mut_slice()); - let mut post_root_bytes: [u8; size_of::()] = Default::default(); - post_root.to_big_endian(post_root_bytes.as_mut_slice()); + // Convert pre_root and post_root to bytes + let mut pre_root_bytes = vec![0u8; 32]; + pre_root.to_big_endian(&mut pre_root_bytes); - let mut bytes: Vec = vec![]; - bytes.extend(pre_root_bytes.iter()); - bytes.extend(post_root_bytes.iter()); + let mut post_root_bytes = vec![0u8; 32]; + post_root.to_big_endian(&mut post_root_bytes); - for commitment in identity_commitments.iter() { - let mut commitment_bytes: [u8; size_of::()] = Default::default(); - commitment.to_big_endian(commitment_bytes.as_mut_slice()); - bytes.extend(commitment_bytes.iter()); - } + let mut bytes = vec![]; + + // Append packed_deletion_indices + bytes.extend_from_slice(&packed_deletion_indices); + + // Append pre_root and post_root bytes + bytes.extend_from_slice(&pre_root_bytes); + bytes.extend_from_slice(&post_root_bytes); + // Compute and return the Keccak-256 hash keccak256(bytes).into() } @@ -408,12 +411,12 @@ struct InsertionProofInput { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct DeletionProofInput { - input_hash: U256, - pre_root: U256, - post_root: U256, - deletion_indices: Vec, - identity_commitments: Vec, - merkle_proofs: Vec>, + input_hash: U256, + pre_root: U256, + post_root: U256, + packed_deletion_indices: Vec, + identity_commitments: Vec, + merkle_proofs: Vec>, } #[cfg(test)] diff --git a/src/server/mod.rs b/src/server/mod.rs index dc5aed14..34266b67 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -109,9 +109,9 @@ pub struct DeletionRequest { #[serde(deny_unknown_fields)] pub struct RecoveryRequest { /// The leaf index of the identity commitment to delete. - prev_identity_commitment: Hash, + previous_identity_commitment: Hash, /// The new identity commitment to insert. - new_identity_commitment: Hash, + new_identity_commitment: Hash, } pub trait ToResponseCode { @@ -191,8 +191,11 @@ async fn recover_identity( State(app): State>, Json(req): Json, ) -> Result<(), Error> { - app.recover_identity(&req.prev_identity_commitment, &req.new_identity_commitment) - .await?; + app.recover_identity( + &req.previous_identity_commitment, + &req.new_identity_commitment, + ) + .await?; Ok(()) } diff --git a/src/task_monitor.rs b/src/task_monitor.rs index d532eaa6..85b47ebf 100644 --- a/src/task_monitor.rs +++ b/src/task_monitor.rs @@ -18,7 +18,7 @@ use self::tasks::process_identities::ProcessIdentities; use crate::contracts::SharedIdentityManager; use crate::database::Database; use crate::ethereum::write::TransactionId; -use crate::identity_tree::{Hash, TreeState}; +use crate::identity_tree::TreeState; use crate::utils::async_queue::AsyncQueue; pub mod tasks; @@ -134,12 +134,13 @@ impl RunningInstance { pub struct Options { /// The maximum number of seconds the sequencer will wait before sending a /// batch of identities to the chain, even if the batch is not full. + // TODO: do we want to change this to batch_insertion_timeout_secs #[clap(long, env, default_value = "180")] pub batch_timeout_seconds: u64, /// TODO: #[clap(long, env, default_value = "3600")] - pub deletion_time_interval: i64, + pub batch_deletion_timeout_seconds: i64, /// TODO: #[clap(long, env, default_value = "100")] @@ -184,12 +185,12 @@ pub struct TaskMonitor { pending_identities_capacity: usize, // Finalization params - scanning_window_size: u64, - time_between_scans: Duration, + scanning_window_size: u64, + time_between_scans: Duration, // TODO: docs - deletion_time_interval: i64, + batch_deletion_timeout_seconds: i64, // TODO: docs - min_batch_deletion_size: usize, + min_batch_deletion_size: usize, } impl TaskMonitor { @@ -204,7 +205,7 @@ impl TaskMonitor { pending_identities_capacity, scanning_window_size, time_between_scans_seconds, - deletion_time_interval, + batch_deletion_timeout_seconds, min_batch_deletion_size, insert_identities_capacity, } = *options; @@ -218,7 +219,7 @@ impl TaskMonitor { pending_identities_capacity, scanning_window_size, time_between_scans: Duration::from_secs(time_between_scans_seconds), - deletion_time_interval: options.deletion_time_interval, + batch_deletion_timeout_seconds: options.batch_deletion_timeout_seconds, min_batch_deletion_size: options.min_batch_deletion_size, } } @@ -314,7 +315,7 @@ impl TaskMonitor { let delete_identities = DeleteIdentities::new( self.database.clone(), self.tree_state.get_latest_tree(), - self.deletion_time_interval, + self.batch_deletion_timeout_seconds, self.min_batch_deletion_size, wake_up_notify, ); diff --git a/src/task_monitor/tasks/delete_identities.rs b/src/task_monitor/tasks/delete_identities.rs index 79487cf9..0af44c78 100644 --- a/src/task_monitor/tasks/delete_identities.rs +++ b/src/task_monitor/tasks/delete_identities.rs @@ -2,11 +2,11 @@ use std::collections::HashSet; use std::sync::Arc; use anyhow::Result as AnyhowResult; -use chrono::{DateTime, Utc}; +use chrono::{Utc}; use tokio::sync::Notify; use tracing::info; -use crate::contracts::SharedIdentityManager; + use crate::database::types::DeletionEntry; use crate::database::Database; use crate::identity_tree::{Hash, Latest, TreeVersion}; @@ -63,11 +63,14 @@ async fn delete_identities( let deletions = database.get_deletions().await?; if deletions.is_empty() { // Sleep for one hour - tokio::time::sleep(tokio::time::Duration::from_secs(3600)).await; + // TODO: should we make this dynamic? This causes an issue with tests so its set + // to 1 sec atm + tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; continue; } let last_deletion_timestamp = database.get_latest_deletion().await?.timestamp; + // If the minimum deletions batch size is reached or the deletion time interval // has elapsed, run a batch of deletions if deletions.len() >= min_deletion_batch_size @@ -76,7 +79,6 @@ async fn delete_identities( // Dedup deletion entries let deletions = deletions .into_iter() - .map(|f| f) .collect::>(); let (leaf_indices, previous_commitments): (Vec, Vec) = deletions diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs index 264f305d..914aed1f 100644 --- a/src/task_monitor/tasks/mine_identities.rs +++ b/src/task_monitor/tasks/mine_identities.rs @@ -2,18 +2,18 @@ use std::collections::HashMap; use std::sync::Arc; use anyhow::{Context, Result as AnyhowResult}; -use chrono::{DateTime, Days, Utc}; +use chrono::{DateTime, Utc}; use ethers::types::U256; use tracing::{info, instrument}; -use crate::contracts::abi::WorldId; + use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; use crate::identity_tree::{Hash, Intermediate, TreeVersion, TreeWithNextVersion}; use crate::task_monitor::{ PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, }; -use crate::utils::async_queue::{AsyncPopGuard, AsyncQueue}; +use crate::utils::async_queue::{AsyncQueue}; pub struct MineIdentities { database: Arc, diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 0f8fad56..575ebe9f 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -1,15 +1,13 @@ -use std::collections::HashMap; use std::sync::Arc; use std::time::{Duration, SystemTime}; use anyhow::{Context, Result as AnyhowResult}; -use chrono::{Days, Utc}; use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{register_histogram, Histogram}; use ruint::Uint; use semaphore::merkle_tree::Proof; -use semaphore::poseidon_tree::{Branch, PoseidonHash}; +use semaphore::poseidon_tree::Branch; use tokio::sync::Notify; use tokio::{select, time}; use tracing::{debug, error, info, instrument, warn}; @@ -20,7 +18,6 @@ use crate::identity_tree::{ AppliedTreeUpdate, Hash, Intermediate, TreeVersion, TreeVersionReadOps, TreeWithNextVersion, }; use crate::prover::identity::Identity; -use crate::prover::map::ReadOnlyInsertionProver; use crate::prover::{Prover, ReadOnlyProver}; use crate::task_monitor::{ PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, @@ -228,7 +225,7 @@ async fn commit_identities( identity_manager, batching_tree, pending_batch_submissions_queue, - &updates, + updates, prover, ) .await?; @@ -248,7 +245,7 @@ async fn commit_identities( identity_manager, batching_tree, pending_batch_submissions_queue, - &updates, + updates, prover, ) .await?; @@ -466,10 +463,19 @@ pub async fn delete_identities( // Grab the initial conditions before the updates are applied to the tree. let pre_root: U256 = batching_tree.get_root().into(); - let mut commitments: Vec = updates + + let mut deletion_indices = updates .iter() - .map(|update| update.update.element.into()) - .collect(); + .map(|f| f.update.leaf_index as u32) + .collect::>(); + + // TODO: note that using `batching_tree.get_leaf()` locks the tree every time + // to speed this up we could write a new function that takes an input array, + // locks it once and gets all the commitments + let mut commitments = deletion_indices + .iter() + .map(|i| batching_tree.get_leaf(*i as usize).into()) + .collect::>(); let latest_tree_from_updates = updates .last() @@ -501,16 +507,11 @@ pub async fn delete_identities( let batch_size = prover.batch_size(); - let mut deletion_indices = updates - .iter() - .map(|f| f.update.leaf_index as u32) - .collect::>(); - // The verifier and prover can only work with a given batch size, so we need to // ensure that our batches match that size. We do this by padding deletion // indices with tree.depth() ^ 2. The deletion prover will skip the proof for // any deletion with an index greater than the max tree depth - let pad_index = latest_tree_from_updates.depth().pow(2) as u32; + let pad_index = 2_u32.pow(latest_tree_from_updates.depth() as u32); if commitment_count != batch_size { let padding = batch_size - commitment_count; @@ -534,6 +535,8 @@ pub async fn delete_identities( // With the updates applied we can grab the value of the tree's new root and // build our identities for sending to the identity manager. let post_root: U256 = latest_tree_from_updates.root().into(); + + // Get the previous identity let identity_commitments: Vec = commitments .iter() .zip(merkle_proofs) @@ -552,11 +555,16 @@ pub async fn delete_identities( identity_manager.validate_merkle_proofs(&identity_commitments)?; + let mut packed_deletion_indices = vec![]; + for &index in &deletion_indices { + packed_deletion_indices.extend_from_slice(&index.to_be_bytes()); + } + // We prepare the proof before reserving a slot in the pending identities let proof = IdentityManager::prepare_deletion_proof( prover, pre_root, - &deletion_indices, + packed_deletion_indices.clone(), identity_commitments, post_root, ) @@ -575,7 +583,13 @@ pub async fn delete_identities( // With all the data prepared we can submit the identities to the on-chain // identity manager and wait for that transaction to be mined. let transaction_id = identity_manager - .delete_identities(proof, pre_root, deletion_indices, post_root) + .delete_identities( + proof, + batch_size as u32, + packed_deletion_indices, + pre_root, + post_root, + ) .await .map_err(|e| { error!(?e, "Failed to insert identity to contract."); diff --git a/tests/common/abi.rs b/tests/common/abi.rs index 2f43f7fc..f857132e 100644 --- a/tests/common/abi.rs +++ b/tests/common/abi.rs @@ -18,7 +18,9 @@ abigen!( error NoSuchVerifier() error MismatchedInputLengths() constructor(address _logic, bytes memory data) payable - function initialize(uint8 treeDepth, uint256 initialRoot, address _batchInsertionVerifiers, address _batchUpdateVerifiers, address _semaphoreVerifier, bool _enableStateBridge, address stateBridge) public virtual + function initialize(uint8 treeDepth, uint256 initialRoot, address _batchInsertionVerifiers, address _batchUpdateVerifiers, address _semaphoreVerifier) public virtual + function initializeV2(address _batchDeletionVerifiers) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint256 preRoot, bytes calldata deletionIndices, uint256 postRoot) public virtual function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual function updateIdentities(uint256[8] calldata updateProof, uint256 preRoot, uint32[] calldata leafIndices, uint256[] calldata oldIdentities, uint256[] calldata newIdentities, uint256 postRoot) public virtual function calculateIdentityRegistrationInputHash(uint32 startIndex, uint256 preRoot, uint256 postRoot, uint256[] identityCommitments) public view virtual returns (bytes32 hash) diff --git a/tests/common/chain_mock.rs b/tests/common/chain_mock.rs index 9c7ff0ed..2f6ddd97 100644 --- a/tests/common/chain_mock.rs +++ b/tests/common/chain_mock.rs @@ -29,7 +29,8 @@ pub struct MockChain { #[instrument(skip_all)] pub async fn spawn_mock_chain( initial_root: U256, - batch_sizes: &[usize], + insertion_batch_sizes: &[usize], + deletion_batch_sizes: &[usize], tree_depth: u8, ) -> anyhow::Result { let chain = Anvil::new().block_time(2u64).spawn(); @@ -95,16 +96,6 @@ pub async fn spawn_mock_chain( .send() .await?; - // The rest of the contracts can be deployed to the mock chain normally. - let mock_state_bridge_factory = - load_and_build_contract("./sol/SimpleStateBridge.json", client.clone())?; - - let mock_state_bridge = mock_state_bridge_factory - .deploy(())? - .confirmations(0usize) - .send() - .await?; - let mock_verifier_factory = load_and_build_contract("./sol/SequencerVerifier.json", client.clone())?; @@ -126,32 +117,34 @@ pub async fn spawn_mock_chain( let verifier_lookup_table_factory = load_and_build_contract("./sol/VerifierLookupTable.json", client.clone())?; - let first_batch_size = batch_sizes[0]; + let first_insertion_batch_size = insertion_batch_sizes.first().copied().unwrap_or(1); + let first_deletion_batch_size = deletion_batch_sizes.first().copied().unwrap_or(1); let insert_verifiers = verifier_lookup_table_factory .clone() - .deploy((first_batch_size as u64, mock_verifier.address()))? + .deploy((first_insertion_batch_size as u64, mock_verifier.address()))? .confirmations(0usize) .send() .await?; let update_verifiers = verifier_lookup_table_factory - .deploy((first_batch_size as u64, unimplemented_verifier.address()))? + .clone() + .deploy(( + first_insertion_batch_size as u64, + unimplemented_verifier.address(), + ))? .confirmations(0usize) .send() .await?; - let identity_manager_impl_factory = - load_and_build_contract("./sol/WorldIDIdentityManagerImplV1.json", client.clone())?; - - let identity_manager_impl = identity_manager_impl_factory - .deploy(())? + let delete_verifiers = verifier_lookup_table_factory + .deploy((first_deletion_batch_size as u64, mock_verifier.address()))? .confirmations(0usize) .send() .await?; - for batch_size in &batch_sizes[1..] { - let batch_size = *batch_size as u64; + for batch_size in insertion_batch_sizes.iter().skip(1).copied() { + let batch_size = batch_size as u64; info!("Adding verifier for batch size {}", batch_size); insert_verifiers @@ -161,10 +154,29 @@ pub async fn spawn_mock_chain( .await?; } + for batch_size in deletion_batch_sizes.iter().skip(1).copied() { + let batch_size = batch_size as u64; + + info!("Adding verifier for batch size {}", batch_size); + delete_verifiers + .method::<_, ()>("addVerifier", (batch_size, mock_verifier.address()))? + .send() + .await? + .await?; + } + + let identity_manager_impl_factory = + load_and_build_contract("./sol/WorldIDIdentityManagerImplV2.json", client.clone())?; + + let identity_manager_impl = identity_manager_impl_factory + .deploy(())? + .confirmations(0usize) + .send() + .await?; + let identity_manager_factory = load_and_build_contract("./sol/WorldIDIdentityManager.json", client.clone())?; - let state_bridge_address = mock_state_bridge.address(); - let enable_state_bridge = true; + let identity_manager_impl_address = identity_manager_impl.address(); let init_call_data = ContractAbi::InitializeCall { @@ -173,8 +185,6 @@ pub async fn spawn_mock_chain( batch_insertion_verifiers: insert_verifiers.address(), batch_update_verifiers: update_verifiers.address(), semaphore_verifier: semaphore_verifier.address(), - enable_state_bridge, - state_bridge: state_bridge_address, }; let init_call_encoded: Bytes = Bytes::from(init_call_data.encode()); @@ -190,6 +200,12 @@ pub async fn spawn_mock_chain( client.clone(), ); + identity_manager + .method::<_, ()>("initializeV2", delete_verifiers.address())? + .send() + .await? + .await?; + Ok(MockChain { anvil: chain, private_key, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 7752d835..a530a014 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -48,18 +48,21 @@ pub mod prelude { pub use super::prover_mock::ProverService; pub use super::{ abi as ContractAbi, generate_reference_proof_json, generate_test_identities, - init_tracing_subscriber, spawn_app, spawn_deps, spawn_mock_prover, test_inclusion_proof, - test_insert_identity, test_verify_proof, test_verify_proof_on_chain, + init_tracing_subscriber, spawn_app, spawn_deps, spawn_mock_deletion_prover, + spawn_mock_insertion_prover, test_inclusion_proof, test_insert_identity, test_verify_proof, + test_verify_proof_on_chain, }; } use std::collections::HashMap; use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener}; +use std::str::FromStr; use std::sync::Arc; use futures::stream::FuturesUnordered; use futures::StreamExt; use hyper::StatusCode; +use signup_sequencer::identity_tree::Status; use self::chain_mock::{spawn_mock_chain, MockChain, SpecialisedContract}; use self::prelude::*; @@ -271,6 +274,134 @@ pub async fn test_inclusion_proof( } } +#[instrument(skip_all)] +pub async fn test_inclusion_status( + uri: &str, + client: &Client, + leaf: &Hash, + expected_status: Status, +) { + for _i in 1..21 { + let body = construct_inclusion_proof_body(leaf); + info!(?uri, "Contacting"); + let req = Request::builder() + .method("POST") + .uri(uri.to_owned() + "/inclusionProof") + .header("Content-Type", "application/json") + .body(body) + .expect("Failed to create inclusion proof hyper::Body"); + + let mut response = client + .request(req) + .await + .expect("Failed to execute request."); + + let bytes = hyper::body::to_bytes(response.body_mut()) + .await + .expect("Failed to convert response body to bytes"); + let result = String::from_utf8(bytes.into_iter().collect()) + .expect("Could not parse response bytes to utf-8"); + let result_json = serde_json::from_str::(&result) + .expect("Failed to parse response as json"); + let status = result_json["status"] + .as_str() + .expect("Failed to get status"); + + assert_eq!( + expected_status, + Status::from_str(status).expect("Could not convert str to Status") + ); + } +} + +#[instrument(skip_all)] +pub async fn test_delete_identity( + uri: &str, + client: &Client, + ref_tree: &mut PoseidonTree, + test_leaves: &[Field], + leaf_index: usize, + expect_failure: bool, +) -> (merkle_tree::Proof, Field) { + let body = construct_delete_identity_body(&test_leaves[leaf_index]); + + let req = Request::builder() + .method("POST") + .uri(uri.to_owned() + "/deleteIdentity") + .header("Content-Type", "application/json") + .body(body) + .expect("Failed to create insert identity hyper::Body"); + + let mut response = client + .request(req) + .await + .expect("Failed to execute request."); + let bytes = hyper::body::to_bytes(response.body_mut()) + .await + .expect("Failed to convert response body to bytes"); + + if expect_failure { + assert!(!response.status().is_success()); + } else { + assert!(response.status().is_success()); + assert!(bytes.is_empty()); + } + + ref_tree.set(leaf_index, Hash::ZERO); + (ref_tree.proof(leaf_index).unwrap(), ref_tree.root()) +} + +#[instrument(skip_all)] +pub async fn test_recover_identity( + uri: &str, + client: &Client, + ref_tree: &mut PoseidonTree, + test_leaves: &[Field], + previous_leaf_index: usize, + new_leaf: Field, + new_leaf_index: usize, + expect_failure: bool, +) -> (merkle_tree::Proof, Field) { + let previous_leaf = test_leaves[previous_leaf_index]; + + let body = construct_recover_identity_body(&previous_leaf, &new_leaf); + + let req = Request::builder() + .method("POST") + .uri(uri.to_owned() + "/recoverIdentity") + .header("Content-Type", "application/json") + .body(body) + .expect("Failed to create insert identity hyper::Body"); + + let mut response = client + .request(req) + .await + .expect("Failed to execute request."); + + let bytes = hyper::body::to_bytes(response.body_mut()) + .await + .expect("Failed to convert response body to bytes"); + + if expect_failure { + assert!(!response.status().is_success()); + } else { + assert!(response.status().is_success()); + assert!(bytes.is_empty()); + } + + // TODO: Note that recovery order is non-deterministic and therefore we cannot + // easily keep the ref_tree in sync with the sequencer's version of the + // tree. In the future, we could consider tracking updates to the tree in a + // different way like listening to event emission. + ref_tree.set(previous_leaf_index, Hash::ZERO); + // Continuing on the note above, while the replacement identity is be + // inserted as a new identity, it is not deterministic and if there are multiple + // recovery requests, it is possible that the sequencer tree is ordered in a + // different way than the ref_tree + ref_tree.set(new_leaf_index, new_leaf); + (ref_tree.proof(new_leaf_index).unwrap(), ref_tree.root()) +} + #[instrument(skip_all)] pub async fn test_add_batch_size( uri: impl Into, @@ -382,6 +513,28 @@ fn construct_inclusion_proof_body(identity_commitment: &Hash) -> Body { ) } +fn construct_delete_identity_body(identity_commitment: &Hash) -> Body { + Body::from( + json!({ + "identityCommitment": identity_commitment, + }) + .to_string(), + ) +} + +fn construct_recover_identity_body( + prev_identity_commitment: &Hash, + new_identity_commitment: &Hash, +) -> Body { + Body::from( + json!({ + "previousIdentityCommitment":prev_identity_commitment , + "newIdentityCommitment": new_identity_commitment, + }) + .to_string(), + ) +} + fn construct_insert_identity_body(identity_commitment: &Field) -> Body { Body::from( json!({ @@ -446,38 +599,72 @@ struct CompiledContract { pub async fn spawn_deps( initial_root: U256, - batch_sizes: &[usize], + insertion_batch_sizes: &[usize], + deletion_batch_sizes: &[usize], tree_depth: u8, ) -> anyhow::Result<( MockChain, DockerContainerGuard, HashMap, + HashMap, micro_oz::ServerHandle, )> { - let chain = spawn_mock_chain(initial_root, batch_sizes, tree_depth); + let chain = spawn_mock_chain( + initial_root, + insertion_batch_sizes, + deletion_batch_sizes, + tree_depth, + ); + let db_container = spawn_db(); - let prover_futures = FuturesUnordered::new(); - for batch_size in batch_sizes { - prover_futures.push(spawn_mock_prover(*batch_size)); + let insertion_prover_futures = FuturesUnordered::new(); + for batch_size in insertion_batch_sizes { + insertion_prover_futures.push(spawn_mock_insertion_prover(*batch_size, tree_depth)); + } + + let deletion_prover_futures = FuturesUnordered::new(); + for batch_size in deletion_batch_sizes { + deletion_prover_futures.push(spawn_mock_deletion_prover(*batch_size, tree_depth)); } - let (chain, db_container, provers) = - tokio::join!(chain, db_container, prover_futures.collect::>()); + let (chain, db_container, insertion_provers, deletion_provers) = tokio::join!( + chain, + db_container, + insertion_prover_futures.collect::>(), + deletion_prover_futures.collect::>() + ); let chain = chain?; let signing_key = SigningKey::from_bytes(chain.private_key.as_bytes())?; let micro_oz = micro_oz::spawn(chain.anvil.endpoint(), signing_key).await?; - let provers = provers.into_iter().collect::, _>>()?; + let insertion_provers = insertion_provers + .into_iter() + .collect::, _>>()?; - let prover_map = provers + let insertion_prover_map = insertion_provers .into_iter() .map(|prover| (prover.batch_size(), prover)) - .collect(); + .collect::>(); + + let deletion_provers = deletion_provers + .into_iter() + .collect::, _>>()?; - Ok((chain, db_container?, prover_map, micro_oz)) + let deletion_prover_map = deletion_provers + .into_iter() + .map(|prover| (prover.batch_size(), prover)) + .collect::>(); + + Ok(( + chain, + db_container?, + insertion_prover_map, + deletion_prover_map, + micro_oz, + )) } async fn spawn_db() -> anyhow::Result { @@ -486,9 +673,24 @@ async fn spawn_db() -> anyhow::Result { Ok(db_container) } -pub async fn spawn_mock_prover(batch_size: usize) -> anyhow::Result { +pub async fn spawn_mock_insertion_prover( + batch_size: usize, + tree_depth: u8, +) -> anyhow::Result { + let mock_prover_service = + prover_mock::ProverService::new(batch_size, tree_depth, prover_mock::ProverType::Insertion) + .await?; + + Ok(mock_prover_service) +} + +pub async fn spawn_mock_deletion_prover( + batch_size: usize, + tree_depth: u8, +) -> anyhow::Result { let mock_prover_service = - prover_mock::ProverService::new(batch_size, prover_mock::ProverType::Insertion).await?; + prover_mock::ProverService::new(batch_size, tree_depth, prover_mock::ProverType::Deletion) + .await?; Ok(mock_prover_service) } diff --git a/tests/common/prover_mock.rs b/tests/common/prover_mock.rs index f7ab189e..6aaa4fb8 100644 --- a/tests/common/prover_mock.rs +++ b/tests/common/prover_mock.rs @@ -36,7 +36,7 @@ impl Display for ProverError { /// The input to the prover. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -struct ProofInput { +struct InsertionProofInput { input_hash: U256, start_index: u32, pre_root: U256, @@ -45,6 +45,22 @@ struct ProofInput { merkle_proofs: Vec>, } +// TODO: ideally we just import the InsertionProofInput and DeletionProofInput +// from the signup sequencer so that we can know e2e breaks when any interface +// changes occur + +/// The input to the prover. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct DeletionProofInput { + input_hash: U256, + pre_root: U256, + post_root: U256, + packed_deletion_indices: Vec, + identity_commitments: Vec, + merkle_proofs: Vec>, +} + /// The proof response from the prover. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Proof { @@ -119,6 +135,7 @@ impl std::fmt::Display for ProverType { struct Prover { is_available: bool, + tree_depth: u8, } impl ProverService { @@ -128,17 +145,41 @@ impl ProverService { /// It provides only a single endpoint for now, `/prove` in order to match /// the full service (`semaphore-mtb`). This can be extended in the future /// if needed. - pub async fn new(batch_size: usize, prover_type: ProverType) -> anyhow::Result { + pub async fn new( + batch_size: usize, + tree_depth: u8, + prover_type: ProverType, + ) -> anyhow::Result { async fn prove( - State(state): State>>, - Json(input): Json, + state: State>>, + Json(input): Json, ) -> Result, StatusCode> { let state = state.lock().await; - state.prove(input).map(Json) + // Attempt to deserialize into InsertionProofInput + if let Ok(deserialized_insertion_input) = + serde_json::from_value::(input.clone()) + { + return state + .prove_insertion(deserialized_insertion_input) + .map(Json); + } + + // If the above fails, attempt to deserialize into DeletionProofInput + if let Ok(deserialized_deletion_input) = + serde_json::from_value::(input) + { + return state.prove_deletion(deserialized_deletion_input).map(Json); + } + + // If both fail, return an error + Err(StatusCode::BAD_REQUEST) } - let inner = Arc::new(Mutex::new(Prover { is_available: true })); + let inner = Arc::new(Mutex::new(Prover { + is_available: true, + tree_depth, + })); let state = inner.clone(); let app = Router::new().route("/prove", post(prove)).with_state(state); @@ -217,7 +258,7 @@ impl ProverService { } impl Prover { - fn prove(&self, input: ProofInput) -> Result { + fn prove_insertion(&self, input: InsertionProofInput) -> Result { if !self.is_available { return Err(StatusCode::SERVICE_UNAVAILABLE); } @@ -271,6 +312,66 @@ impl Prover { ])) } + fn prove_deletion(&self, input: DeletionProofInput) -> Result { + if !self.is_available { + return Err(StatusCode::SERVICE_UNAVAILABLE); + } + + // Calculate the input hash based on the prover parameters. + let input_hash = Self::compute_deletion_proof_input_hash( + input.packed_deletion_indices.clone(), + input.pre_root, + input.post_root, + ); + + // If the hashes aren't the same something's wrong so we return an error. + if input_hash != input.input_hash { + return Ok(ProveResponse::failure("42", "Input hash mismatch.")); + } + + // Next we verify the merkle proofs. + let empty_leaf = U256::zero(); + let mut last_root = input.pre_root; + + let mut deletion_indices = vec![]; + + for bytes in input.packed_deletion_indices.chunks(4) { + let mut val: [u8; 4] = Default::default(); + val.copy_from_slice(bytes); + deletion_indices.push(u32::from_be_bytes(val)); + } + + for (leaf_index, merkle_proof) in deletion_indices.iter().zip(input.merkle_proofs) { + if *leaf_index == 2u32.pow(self.tree_depth as u32) { + continue; + } + + let proof = + Self::reconstruct_proof_with_directions(*leaf_index as usize, &merkle_proof); + + last_root = proof.root(empty_leaf.into()).into(); + } + + // If the final root doesn't match the post root something's broken so we error. + if last_root != input.post_root { + return Ok(ProveResponse::failure( + "43", + "Merkle proof verification failure.", + )); + } + + Ok(ProveResponse::success([ + "0x2".into(), + input_hash, + "0x2413396a2af3add6fbe8137cfe7657917e31a5cdab0b7d1d645bd5eeb47ba601".into(), + "0x1ad029539528b32ba70964ce43dbf9bba2501cdb3aaa04e4d58982e2f6c34752".into(), + "0x5bb975296032b135458bd49f92d5e9d363367804440d4692708de92e887cf17".into(), + "0x14932600f53a1ceb11d79a7bdd9688a2f8d1919176f257f132587b2b3274c41e".into(), + "0x13d7b19c7b67bf5d3adf2ac2d3885fd5d49435b6069c0656939cd1fb7bef9dc9".into(), + "0x142e14f90c49c79b4edf5f6b7acbcdb0b0f376a4311fc036f1006679bd53ca9e".into(), + ])) + } + /// Reconstructs the proof with directions as required by `semaphore-rs`. /// /// This allows us to utilise the proof verification procedure from that @@ -308,7 +409,7 @@ impl Prover { /// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] /// 32 || 256 || 256 || 256 || 256 || ... || 256 bits /// ``` - fn calculate_identity_registration_input_hash(input: &ProofInput) -> U256 { + fn calculate_identity_registration_input_hash(input: &InsertionProofInput) -> U256 { // Calculate the input hash as described by the prover. let mut hashable_bytes: Vec = vec![]; let mut buffer: [u8; size_of::()] = Default::default(); @@ -325,4 +426,37 @@ impl Prover { keccak256(hashable_bytes).into() } + + /// Calculates the input hash based on the `input` parameters to the prover. + /// + /// We keccak hash all input to save verification gas. Inputs are arranged + /// as follows: + /// ``` + /// PackedDeletionIndices || PreRoot || PostRoot + /// 32 bits * batchSize || 256 || 256 + /// ``` + pub fn compute_deletion_proof_input_hash( + packed_deletion_indices: Vec, + pre_root: U256, + post_root: U256, + ) -> U256 { + // Convert pre_root and post_root to bytes + let mut pre_root_bytes = vec![0u8; 32]; + pre_root.to_big_endian(&mut pre_root_bytes); + + let mut post_root_bytes = vec![0u8; 32]; + post_root.to_big_endian(&mut post_root_bytes); + + let mut bytes = vec![]; + + // Append packed_deletion_indices + bytes.extend_from_slice(&packed_deletion_indices); + + // Append pre_root and post_root bytes + bytes.extend_from_slice(&pre_root_bytes); + bytes.extend_from_slice(&post_root_bytes); + + // Compute and return the Keccak-256 hash + keccak256(bytes).into() + } } diff --git a/tests/delete_identity.rs b/tests/delete_identity.rs new file mode 100644 index 00000000..dbc88b48 --- /dev/null +++ b/tests/delete_identity.rs @@ -0,0 +1,160 @@ +mod common; + +use common::prelude::*; + +use crate::common::test_delete_identity; + +const SUPPORTED_DEPTH: usize = 18; +const IDLE_TIME: u64 = 7; + +#[tokio::test] +#[serial_test::serial] +async fn delete_identities() -> anyhow::Result<()> { + // Initialize logging for the test. + init_tracing_subscriber(); + info!("Starting integration test"); + + let insertion_batch_size: usize = 8; + let deletion_batch_size: usize = 3; + let batch_deletion_timeout_seconds: usize = 10; + + #[allow(clippy::cast_possible_truncation)] + let tree_depth: u8 = SUPPORTED_DEPTH as u8; + + let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); + let initial_root: U256 = ref_tree.root().into(); + + let (mock_chain, db_container, insertion_prover_map, deletion_prover_map, micro_oz) = + spawn_deps( + initial_root, + &[insertion_batch_size], + &[deletion_batch_size], + tree_depth, + ) + .await?; + + let mock_insertion_prover = &insertion_prover_map[&insertion_batch_size]; + let mock_deletion_prover = &deletion_prover_map[&deletion_batch_size]; + + let port = db_container.port(); + let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); + + let mut options = Options::try_parse_from([ + "signup-sequencer", + "--identity-manager-address", + "0x0000000000000000000000000000000000000000", // placeholder, updated below + "--database", + &db_url, + "--database-max-connections", + "1", + "--tree-depth", + &format!("{tree_depth}"), + "--prover-urls", + &format!( + "[{}, {}]", + mock_insertion_prover.arg_string_single(), + mock_deletion_prover.arg_string_single() + ), + "--batch-timeout-seconds", + "10", + "--batch-deletion-timeout-seconds", + &format!("{batch_deletion_timeout_seconds}"), + "--min-batch-deletion-size", + &format!("{deletion_batch_size}"), + "--dense-tree-prefix-depth", + "10", + "--tree-gc-threshold", + "1", + "--oz-api-key", + "", + "--oz-api-secret", + "", + "--oz-api-url", + µ_oz.endpoint(), + "--oz-address", + &format!("{:?}", micro_oz.address()), + ]) + .context("Failed to create options")?; + + options.server.server = Url::parse("http://127.0.0.1:0/").expect("Failed to parse URL"); + + options.app.contracts.identity_manager_address = mock_chain.identity_manager.address(); + options.app.ethereum.ethereum_provider = Url::parse(&mock_chain.anvil.endpoint()).expect( + " + Failed to parse Anvil url", + ); + + let (app, local_addr) = spawn_app(options.clone()) + .await + .expect("Failed to spawn app."); + + let test_identities = generate_test_identities(insertion_batch_size * 3); + let identities_ref: Vec = test_identities + .iter() + .map(|i| Hash::from_str_radix(i, 16).unwrap()) + .collect(); + + let uri = "http://".to_owned() + &local_addr.to_string(); + let client = Client::new(); + + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in 0..insertion_batch_size { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME)).await; + + // Check that we can also get these inclusion proofs back. + for i in 0..insertion_batch_size { + test_inclusion_proof( + &uri, + &client, + i, + &ref_tree, + &Hash::from_str_radix(&test_identities[i], 16) + .expect("Failed to parse Hash from test leaf"), + false, + ) + .await; + } + + // Delete enough identities to trigger a batch + for i in 0..deletion_batch_size { + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, i, false).await; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + + // Ensure that identities have been deleted + for i in 0..deletion_batch_size { + test_inclusion_proof( + &uri, + &client, + i, + &ref_tree, + &Hash::from_str_radix(&test_identities[i], 16) + .expect("Failed to parse Hash from test leaf"), + true, + ) + .await; + } + + // Expect failure when deleting an identity that has already been deleted + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 0, true).await; + + // Expect failure when deleting an identity that can not be found + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 12, true).await; + + // Shutdown the app properly for the final time + shutdown(); + app.await.unwrap(); + for (_, prover) in insertion_prover_map.into_iter() { + prover.stop(); + } + for (_, prover) in deletion_prover_map.into_iter() { + prover.stop(); + } + reset_shutdown(); + + Ok(()) +} diff --git a/tests/delete_padded_identity.rs b/tests/delete_padded_identity.rs new file mode 100644 index 00000000..298b8832 --- /dev/null +++ b/tests/delete_padded_identity.rs @@ -0,0 +1,182 @@ +mod common; + +use common::prelude::*; + +use crate::common::test_delete_identity; + +const SUPPORTED_DEPTH: u8 = 18; +const IDLE_TIME: u64 = 7; + +#[tokio::test] +#[serial_test::serial] +async fn delete_padded_identity() -> anyhow::Result<()> { + // Initialize logging for the test. + init_tracing_subscriber(); + info!("Starting integration test"); + + let insertion_batch_size: usize = 8; + let deletion_batch_size: usize = 3; + let batch_deletion_timeout_seconds: usize = 10; + + #[allow(clippy::cast_possible_truncation)] + let tree_depth: u8 = SUPPORTED_DEPTH; + + let mut ref_tree = PoseidonTree::new((SUPPORTED_DEPTH + 1).into(), ruint::Uint::ZERO); + let initial_root: U256 = ref_tree.root().into(); + + let (mock_chain, db_container, insertion_prover_map, deletion_prover_map, micro_oz) = + spawn_deps( + initial_root, + &[insertion_batch_size], + &[deletion_batch_size], + tree_depth, + ) + .await?; + + let mock_insertion_prover = &insertion_prover_map[&insertion_batch_size]; + let mock_deletion_prover = &deletion_prover_map[&deletion_batch_size]; + + let port = db_container.port(); + let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); + + let mut options = Options::try_parse_from([ + "signup-sequencer", + "--identity-manager-address", + "0x0000000000000000000000000000000000000000", // placeholder, updated below + "--database", + &db_url, + "--database-max-connections", + "1", + "--tree-depth", + &format!("{tree_depth}"), + "--prover-urls", + &format!( + "[{}, {}]", + mock_insertion_prover.arg_string_single(), + mock_deletion_prover.arg_string_single() + ), + "--batch-timeout-seconds", + "10", + "--batch-deletion-timeout-seconds", + &format!("{batch_deletion_timeout_seconds}"), + "--min-batch-deletion-size", + &format!("{deletion_batch_size}"), + "--dense-tree-prefix-depth", + "10", + "--tree-gc-threshold", + "1", + "--oz-api-key", + "", + "--oz-api-secret", + "", + "--oz-api-url", + µ_oz.endpoint(), + "--oz-address", + &format!("{:?}", micro_oz.address()), + ]) + .context("Failed to create options")?; + + options.server.server = Url::parse("http://127.0.0.1:0/").expect("Failed to parse URL"); + + options.app.contracts.identity_manager_address = mock_chain.identity_manager.address(); + options.app.ethereum.ethereum_provider = Url::parse(&mock_chain.anvil.endpoint()).expect( + " + Failed to parse Anvil url", + ); + + let (app, local_addr) = spawn_app(options.clone()) + .await + .expect("Failed to spawn app."); + + let test_identities = generate_test_identities(insertion_batch_size * 3); + let identities_ref: Vec = test_identities + .iter() + .map(|i| Hash::from_str_radix(i, 16).unwrap()) + .collect(); + + let uri = "http://".to_owned() + &local_addr.to_string(); + let client = Client::new(); + + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in 0..insertion_batch_size { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME)).await; + + // Check that we can also get these inclusion proofs back. + for i in 0..insertion_batch_size { + test_inclusion_proof( + &uri, + &client, + i, + &ref_tree, + &Hash::from_str_radix(&test_identities[i], 16) + .expect("Failed to parse Hash from test leaf"), + false, + ) + .await; + } + + // delete only the first and second identities + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 0, false).await; + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 1, false).await; + + tokio::time::sleep(Duration::from_secs( + batch_deletion_timeout_seconds as u64 * 3, + )) + .await; + + // make sure that identity 3 wasn't deleted + test_inclusion_proof( + &uri, + &client, + 2, + &ref_tree, + &Hash::from_str_radix(&test_identities[2], 16) + .expect("Failed to parse Hash from test leaf"), + false, + ) + .await; + + // Ensure that the first and second identities were deleted + test_inclusion_proof( + &uri, + &client, + 0, + &ref_tree, + &Hash::from_str_radix(&test_identities[0], 16) + .expect("Failed to parse Hash from test leaf"), + true, + ) + .await; + test_inclusion_proof( + &uri, + &client, + 1, + &ref_tree, + &Hash::from_str_radix(&test_identities[1], 16) + .expect("Failed to parse Hash from test leaf"), + true, + ) + .await; + + // Expect failure when deleting an identity that has already been deleted + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 0, true).await; + + // Expect failure when deleting an identity that can not be found + test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, 12, true).await; + + // Shutdown the app properly for the final time + shutdown(); + app.await.unwrap(); + for (_, prover) in insertion_prover_map.into_iter() { + prover.stop(); + } + for (_, prover) in deletion_prover_map.into_iter() { + prover.stop(); + } + reset_shutdown(); + + Ok(()) +} diff --git a/tests/dynamic_batch_sizes.rs b/tests/dynamic_batch_sizes.rs index c20c6068..8947b23f 100644 --- a/tests/dynamic_batch_sizes.rs +++ b/tests/dynamic_batch_sizes.rs @@ -25,10 +25,10 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); let initial_root: U256 = ref_tree.root().into(); - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size, second_batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -127,7 +127,7 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { .await; // Add a new prover for batch sizes of two. - let second_prover = spawn_mock_prover(second_batch_size).await?; + let second_prover = spawn_mock_insertion_prover(second_batch_size, tree_depth).await?; test_add_batch_size( &uri, @@ -263,7 +263,7 @@ async fn dynamic_batch_sizes() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/insert_identity_and_proofs.rs b/tests/insert_identity_and_proofs.rs index 5caaa9ef..71cfca83 100644 --- a/tests/insert_identity_and_proofs.rs +++ b/tests/insert_identity_and_proofs.rs @@ -19,10 +19,10 @@ async fn insert_identity_and_proofs() -> anyhow::Result<()> { let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); let initial_root: U256 = ref_tree.root().into(); - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -243,7 +243,7 @@ async fn insert_identity_and_proofs() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/malformed_payload.rs b/tests/malformed_payload.rs index 64d459a9..396fb093 100644 --- a/tests/malformed_payload.rs +++ b/tests/malformed_payload.rs @@ -17,10 +17,10 @@ async fn malformed_payload() -> anyhow::Result<()> { let batch_size: usize = 3; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -97,7 +97,7 @@ async fn malformed_payload() -> anyhow::Result<()> { shutdown(); app.await?; - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/multi_prover.rs b/tests/multi_prover.rs index ba282392..39f95497 100644 --- a/tests/multi_prover.rs +++ b/tests/multi_prover.rs @@ -19,11 +19,16 @@ async fn multi_prover() -> anyhow::Result<()> { let batch_size_3: usize = 3; let batch_size_10: usize = 10; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size_3, batch_size_10], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = spawn_deps( + initial_root, + &[batch_size_3, batch_size_10], + &[], + tree_depth, + ) + .await?; - let prover_mock_batch_size_3 = &prover_map[&batch_size_3]; - let prover_mock_batch_size_10 = &prover_map[&batch_size_10]; + let prover_mock_batch_size_3 = &insertion_prover_map[&batch_size_3]; + let prover_mock_batch_size_10 = &insertion_prover_map[&batch_size_10]; let prover_arg_string = format!( "[{},{}]", @@ -132,7 +137,7 @@ async fn multi_prover() -> anyhow::Result<()> { shutdown(); app.await?; - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/recover_identity.rs b/tests/recover_identity.rs new file mode 100644 index 00000000..dee53013 --- /dev/null +++ b/tests/recover_identity.rs @@ -0,0 +1,201 @@ +mod common; + +use common::prelude::*; +use signup_sequencer::identity_tree::Status; + +use crate::common::{test_inclusion_status, test_recover_identity}; +const SUPPORTED_DEPTH: usize = 18; +const IDLE_TIME: u64 = 7; + +#[tokio::test] +#[serial_test::serial] +async fn recover_identities() -> anyhow::Result<()> { + // Initialize logging for the test. + init_tracing_subscriber(); + info!("Starting integration test"); + + let insertion_batch_size: usize = 8; + let deletion_batch_size: usize = 3; + let batch_deletion_timeout_seconds: usize = 10; + + #[allow(clippy::cast_possible_truncation)] + let tree_depth: u8 = SUPPORTED_DEPTH as u8; + + let mut ref_tree = PoseidonTree::new(SUPPORTED_DEPTH + 1, ruint::Uint::ZERO); + let initial_root: U256 = ref_tree.root().into(); + + let (mock_chain, db_container, insertion_prover_map, deletion_prover_map, micro_oz) = + spawn_deps( + initial_root, + &[insertion_batch_size], + &[deletion_batch_size], + tree_depth, + ) + .await?; + + // Set the root history expirty to 15 seconds + let updated_root_history_expiry = U256::from(15); + mock_chain + .identity_manager + .method::<_, ()>("setRootHistoryExpiry", updated_root_history_expiry)? + .send() + .await? + .await?; + + let mock_insertion_prover = &insertion_prover_map[&insertion_batch_size]; + let mock_deletion_prover = &deletion_prover_map[&deletion_batch_size]; + + let port = db_container.port(); + let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); + + let mut options = Options::try_parse_from([ + "signup-sequencer", + "--identity-manager-address", + "0x0000000000000000000000000000000000000000", // placeholder, updated below + "--database", + &db_url, + "--database-max-connections", + "1", + "--tree-depth", + &format!("{tree_depth}"), + "--prover-urls", + &format!( + "[{}, {}]", + mock_insertion_prover.arg_string_single(), + mock_deletion_prover.arg_string_single() + ), + "--batch-timeout-seconds", + "10", + "--batch-deletion-timeout-seconds", + &format!("{batch_deletion_timeout_seconds}"), + "--min-batch-deletion-size", + &format!("{deletion_batch_size}"), + "--dense-tree-prefix-depth", + "10", + "--tree-gc-threshold", + "1", + "--oz-api-key", + "", + "--oz-api-secret", + "", + "--oz-api-url", + µ_oz.endpoint(), + "--oz-address", + &format!("{:?}", micro_oz.address()), + ]) + .context("Failed to create options")?; + + options.server.server = Url::parse("http://127.0.0.1:0/").expect("Failed to parse URL"); + + options.app.contracts.identity_manager_address = mock_chain.identity_manager.address(); + options.app.ethereum.ethereum_provider = Url::parse(&mock_chain.anvil.endpoint()).expect( + " + Failed to parse Anvil url", + ); + + let (app, local_addr) = spawn_app(options.clone()) + .await + .expect("Failed to spawn app."); + + let test_identities = generate_test_identities(insertion_batch_size * 3); + let identities_ref: Vec = test_identities + .iter() + .map(|i| Hash::from_str_radix(i, 16).unwrap()) + .collect(); + + let uri = "http://".to_owned() + &local_addr.to_string(); + let client = Client::new(); + + let mut next_leaf_index = 0; + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in 0..insertion_batch_size { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + + next_leaf_index += 1; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME)).await; + // Check that we can also get these inclusion proofs back. + for i in 0..insertion_batch_size { + test_inclusion_proof(&uri, &client, i, &ref_tree, &identities_ref[i], false).await; + } + + // Insert enough recoveries to trigger a batch + for i in 0..deletion_batch_size { + // Delete the identity at i and replace it with an identity at the back of the + // test identities array + // TODO: we should update to a much cleaner approach + let recovery_leaf_index = test_identities.len() - i - 1; + + test_recover_identity( + &uri, + &client, + &mut ref_tree, + &identities_ref, + i, + identities_ref[recovery_leaf_index], + next_leaf_index, + false, + ) + .await; + + next_leaf_index += 1; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + + // Ensure that identities have been deleted + for i in 0..deletion_batch_size { + let recovery_leaf_index = test_identities.len() - i - 1; + + test_inclusion_proof(&uri, &client, i, &ref_tree, &identities_ref[i], true).await; + + // Check that the replacement identity has not been inserted yet + test_inclusion_status( + &uri, + &client, + &identities_ref[recovery_leaf_index], + Status::New, + ) + .await; + } + + // Sleep for root expiry + tokio::time::sleep(Duration::from_secs(updated_root_history_expiry.as_u64())).await; + + // Insert enough identities to trigger an batch to be sent to the blockchain. + for i in insertion_batch_size..insertion_batch_size * 2 { + test_insert_identity(&uri, &client, &mut ref_tree, &identities_ref, i).await; + next_leaf_index += 1; + } + + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + + // Check that the replacement identities have been inserted + for i in 0..deletion_batch_size { + let recovery_leaf_index = test_identities.len() - i - 1; + + // Check that the replacement identity has a mined status after an insertion + // batch has completed + test_inclusion_status( + &uri, + &client, + &identities_ref[recovery_leaf_index], + Status::Mined, + ) + .await; + } + + // Shutdown the app properly for the final time + shutdown(); + app.await.unwrap(); + for (_, prover) in insertion_prover_map.into_iter() { + prover.stop(); + } + for (_, prover) in deletion_prover_map.into_iter() { + prover.stop(); + } + reset_shutdown(); + + Ok(()) +} diff --git a/tests/unavailable_prover.rs b/tests/unavailable_prover.rs index 18a852b0..db9f520c 100644 --- a/tests/unavailable_prover.rs +++ b/tests/unavailable_prover.rs @@ -16,10 +16,10 @@ async fn unavailable_prover() -> anyhow::Result<()> { let batch_size: usize = 3; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; prover_mock.set_availability(false).await; @@ -98,7 +98,7 @@ async fn unavailable_prover() -> anyhow::Result<()> { shutdown(); app.await?; - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); diff --git a/tests/validate_proofs.rs b/tests/validate_proofs.rs index 3a5b0278..5b501b37 100644 --- a/tests/validate_proofs.rs +++ b/tests/validate_proofs.rs @@ -19,10 +19,10 @@ async fn validate_proofs() -> anyhow::Result<()> { let tree_depth: u8 = SUPPORTED_DEPTH as u8; let batch_size = 3; - let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + let (mock_chain, db_container, insertion_prover_map, _, micro_oz) = + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let identity_manager = mock_chain.identity_manager.clone(); @@ -224,7 +224,7 @@ async fn validate_proofs() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); From 3058becf358383d0793330738196ea4f059a227b Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 14:03:54 -0400 Subject: [PATCH 33/45] patched validate_proof_with_age --- tests/validate_proof_with_age.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/validate_proof_with_age.rs b/tests/validate_proof_with_age.rs index db401113..5667e7f8 100644 --- a/tests/validate_proof_with_age.rs +++ b/tests/validate_proof_with_age.rs @@ -22,7 +22,7 @@ async fn validate_proof_with_age() -> anyhow::Result<()> { let batch_size = 3; let (mock_chain, db_container, prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], tree_depth).await?; + spawn_deps(initial_root, &[batch_size], &vec![], tree_depth).await?; let prover_mock = &prover_map[&batch_size]; From 5a0b57594450efbc44771c66244c06860ede34ab Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 14:04:52 -0400 Subject: [PATCH 34/45] chore: cargo fmt --- src/database/mod.rs | 9 +++++++-- src/prover/map.rs | 1 - src/prover/mod.rs | 1 - src/task_monitor/tasks/delete_identities.rs | 7 ++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 738190d5..22dbf35f 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -408,7 +408,12 @@ impl Database { let url = row.get::(1); let timeout_s = row.get::(2) as u64; let prover_type = row.get::(3); - ProverConfiguration { url, timeout_s, batch_size, prover_type } + ProverConfiguration { + url, + timeout_s, + batch_size, + prover_type, + } }) .collect::()) } @@ -771,7 +776,7 @@ mod test { use ruint::Uint; use semaphore::Field; use sqlx::types::chrono::DateTime; - use sqlx::{Row}; + use sqlx::Row; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; diff --git a/src/prover/map.rs b/src/prover/map.rs index 29263374..ba5a27c2 100644 --- a/src/prover/map.rs +++ b/src/prover/map.rs @@ -1,6 +1,5 @@ use std::collections::BTreeMap; - use tokio::sync::{RwLock, RwLockReadGuard}; use crate::prover::{Prover, ProverConfiguration, ProverType, Provers}; diff --git a/src/prover/mod.rs b/src/prover/mod.rs index e0c1b45a..42152f25 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -12,7 +12,6 @@ pub mod map; pub mod proof; use std::collections::HashSet; - use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; use std::mem::size_of; diff --git a/src/task_monitor/tasks/delete_identities.rs b/src/task_monitor/tasks/delete_identities.rs index 0af44c78..83b8a984 100644 --- a/src/task_monitor/tasks/delete_identities.rs +++ b/src/task_monitor/tasks/delete_identities.rs @@ -2,11 +2,10 @@ use std::collections::HashSet; use std::sync::Arc; use anyhow::Result as AnyhowResult; -use chrono::{Utc}; +use chrono::Utc; use tokio::sync::Notify; use tracing::info; - use crate::database::types::DeletionEntry; use crate::database::Database; use crate::identity_tree::{Hash, Latest, TreeVersion}; @@ -77,9 +76,7 @@ async fn delete_identities( || Utc::now() - last_deletion_timestamp > deletion_time_interval { // Dedup deletion entries - let deletions = deletions - .into_iter() - .collect::>(); + let deletions = deletions.into_iter().collect::>(); let (leaf_indices, previous_commitments): (Vec, Vec) = deletions .iter() From 5944bd0011eefe303a2e1ac93940b3dba92e9c13 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 14:06:40 -0400 Subject: [PATCH 35/45] chore: cargo clippy, fixed validate_proof_with_age test --- src/app.rs | 2 +- src/database/mod.rs | 2 +- src/task_monitor.rs | 6 +++--- src/task_monitor/tasks/mine_identities.rs | 2 +- tests/validate_proof_with_age.rs | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app.rs b/src/app.rs index b07e8a48..baecd9d8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::time::Instant; use anyhow::Result as AnyhowResult; -use chrono::{DateTime, Duration, Utc}; +use chrono::{Duration, Utc}; use clap::Parser; use hyper::StatusCode; use ruint::Uint; diff --git a/src/database/mod.rs b/src/database/mod.rs index 22dbf35f..e863c11f 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -775,7 +775,7 @@ mod test { use postgres_docker_utils::DockerContainerGuard; use ruint::Uint; use semaphore::Field; - use sqlx::types::chrono::DateTime; + use sqlx::Row; use super::{Database, Options}; diff --git a/src/task_monitor.rs b/src/task_monitor.rs index 85b47ebf..e0a33c9b 100644 --- a/src/task_monitor.rs +++ b/src/task_monitor.rs @@ -205,9 +205,9 @@ impl TaskMonitor { pending_identities_capacity, scanning_window_size, time_between_scans_seconds, - batch_deletion_timeout_seconds, - min_batch_deletion_size, - insert_identities_capacity, + batch_deletion_timeout_seconds: _, + min_batch_deletion_size: _, + insert_identities_capacity: _, } = *options; Self { diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs index 74f574f9..2c43c681 100644 --- a/src/task_monitor/tasks/mine_identities.rs +++ b/src/task_monitor/tasks/mine_identities.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyhow::{Context, Result as AnyhowResult}; use chrono::{DateTime, Utc}; -use ethers::types::U256; + use tracing::{info, instrument}; use crate::contracts::{IdentityManager, SharedIdentityManager}; diff --git a/tests/validate_proof_with_age.rs b/tests/validate_proof_with_age.rs index 5667e7f8..da5ef4a7 100644 --- a/tests/validate_proof_with_age.rs +++ b/tests/validate_proof_with_age.rs @@ -21,10 +21,10 @@ async fn validate_proof_with_age() -> anyhow::Result<()> { let tree_depth: u8 = SUPPORTED_DEPTH as u8; let batch_size = 3; - let (mock_chain, db_container, prover_map, micro_oz) = + let (mock_chain, db_container, insertion_prover_map, _deletion_prover_map, micro_oz) = spawn_deps(initial_root, &[batch_size], &vec![], tree_depth).await?; - let prover_mock = &prover_map[&batch_size]; + let prover_mock = &insertion_prover_map[&batch_size]; let port = db_container.port(); let db_url = format!("postgres://postgres:postgres@localhost:{port}/database"); @@ -155,7 +155,7 @@ async fn validate_proof_with_age() -> anyhow::Result<()> { // Shutdown the app properly for the final time shutdown(); app.await.unwrap(); - for (_, prover) in prover_map.into_iter() { + for (_, prover) in insertion_prover_map.into_iter() { prover.stop(); } reset_shutdown(); From fededf827a0b295edb425b5b1704238aaca633e4 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 15:57:23 -0400 Subject: [PATCH 36/45] updated logic to process roots by id instead of leaf_index --- src/database/mod.rs | 45 ++++++++++++++++------- src/task_monitor/tasks/mine_identities.rs | 1 - tests/delete_identity.rs | 2 +- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index e863c11f..3d3f957b 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -177,6 +177,25 @@ impl Database { Ok(Some(root_leaf_index as usize)) } + pub async fn get_id_by_root( + tx: impl Executor<'_, Database = Postgres>, + root: &Hash, + ) -> Result, Error> { + let root_index_query = sqlx::query( + r#" + SELECT id FROM identities WHERE root = $1 + "#, + ) + .bind(root); + + let row = tx.fetch_optional(root_index_query).await?; + + let Some(row) = row else { return Ok(None) }; + let root_id = row.get::(0); + + Ok(Some(root_id as usize)) + } + /// Marks the identities and roots from before a given root hash as mined /// Also marks following roots as pending #[instrument(skip(self), level = "debug")] @@ -187,25 +206,24 @@ impl Database { let mut tx = self.pool.begin().await?; - let root_leaf_index = Self::get_leaf_index_by_root(&mut tx, root).await?; + let root_id = Self::get_id_by_root(&mut tx, root).await?; - let Some(root_leaf_index) = root_leaf_index else { + let Some(root_id) = root_id else { return Err(Error::MissingRoot { root: *root }); }; - let root_leaf_index = root_leaf_index as i64; - + let root_id = root_id as i64; // TODO: Can I get rid of line `AND status <> $2 let update_previous_roots = sqlx::query( r#" UPDATE identities SET status = $2, mined_at = CURRENT_TIMESTAMP - WHERE leaf_index <= $1 + WHERE id <= $1 AND status <> $2 AND status <> $3 "#, ) - .bind(root_leaf_index) + .bind(root_id) .bind(<&str>::from(processed_status)) .bind(<&str>::from(mined_status)); @@ -213,10 +231,10 @@ impl Database { r#" UPDATE identities SET status = $2, mined_at = NULL - WHERE leaf_index > $1 + WHERE id > $1 "#, ) - .bind(root_leaf_index) + .bind(root_id) .bind(<&str>::from(pending_status)); tx.execute(update_previous_roots).await?; @@ -235,23 +253,23 @@ impl Database { let mut tx = self.pool.begin().await?; - let root_leaf_index = Self::get_leaf_index_by_root(&mut tx, root).await?; + let root_id = Self::get_id_by_root(&mut tx, root).await?; - let Some(root_leaf_index) = root_leaf_index else { + let Some(root_id) = root_id else { return Err(Error::MissingRoot { root: *root }); }; - let root_leaf_index = root_leaf_index as i64; + let root_id = root_id as i64; let update_previous_roots = sqlx::query( r#" UPDATE identities SET status = $2 - WHERE leaf_index <= $1 + WHERE id <= $1 AND status <> $2 "#, ) - .bind(root_leaf_index) + .bind(root_id) .bind(<&str>::from(mined_status)); tx.execute(update_previous_roots).await?; @@ -775,7 +793,6 @@ mod test { use postgres_docker_utils::DockerContainerGuard; use ruint::Uint; use semaphore::Field; - use sqlx::Row; use super::{Database, Options}; diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs index 2c43c681..b4468c96 100644 --- a/src/task_monitor/tasks/mine_identities.rs +++ b/src/task_monitor/tasks/mine_identities.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use anyhow::{Context, Result as AnyhowResult}; use chrono::{DateTime, Utc}; - use tracing::{info, instrument}; use crate::contracts::{IdentityManager, SharedIdentityManager}; diff --git a/tests/delete_identity.rs b/tests/delete_identity.rs index dbc88b48..3cf97ed6 100644 --- a/tests/delete_identity.rs +++ b/tests/delete_identity.rs @@ -123,7 +123,7 @@ async fn delete_identities() -> anyhow::Result<()> { test_delete_identity(&uri, &client, &mut ref_tree, &identities_ref, i, false).await; } - tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 8)).await; // Ensure that identities have been deleted for i in 0..deletion_batch_size { From fb1bff68beeee4297cb8fa9fea8accff349de9e4 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 16:11:54 -0400 Subject: [PATCH 37/45] patched deletion and recovery tests --- tests/{delete_identity.rs => delete_identities.rs} | 0 tests/{recover_identity.rs => recover_identities.rs} | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename tests/{delete_identity.rs => delete_identities.rs} (100%) rename tests/{recover_identity.rs => recover_identities.rs} (97%) diff --git a/tests/delete_identity.rs b/tests/delete_identities.rs similarity index 100% rename from tests/delete_identity.rs rename to tests/delete_identities.rs diff --git a/tests/recover_identity.rs b/tests/recover_identities.rs similarity index 97% rename from tests/recover_identity.rs rename to tests/recover_identities.rs index dee53013..f3e1c5da 100644 --- a/tests/recover_identity.rs +++ b/tests/recover_identities.rs @@ -34,7 +34,7 @@ async fn recover_identities() -> anyhow::Result<()> { .await?; // Set the root history expirty to 15 seconds - let updated_root_history_expiry = U256::from(15); + let updated_root_history_expiry = U256::from(30); mock_chain .identity_manager .method::<_, ()>("setRootHistoryExpiry", updated_root_history_expiry)? @@ -142,7 +142,7 @@ async fn recover_identities() -> anyhow::Result<()> { next_leaf_index += 1; } - tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 6)).await; // Ensure that identities have been deleted for i in 0..deletion_batch_size { @@ -169,7 +169,7 @@ async fn recover_identities() -> anyhow::Result<()> { next_leaf_index += 1; } - tokio::time::sleep(Duration::from_secs(IDLE_TIME * 3)).await; + tokio::time::sleep(Duration::from_secs(IDLE_TIME * 8)).await; // Check that the replacement identities have been inserted for i in 0..deletion_batch_size { From 611d06065793cb6ce862a4feb830b8e3a5eddca7 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 16:21:09 -0400 Subject: [PATCH 38/45] chore: cargo fmt --- src/prover/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/prover/mod.rs b/src/prover/mod.rs index 42152f25..c922528d 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -237,7 +237,7 @@ impl Prover { let Ok(proof) = serde_json::from_str::(&json) else { let error: ProverError = serde_json::from_str(&json)?; - return Err(anyhow::Error::msg(format!("{error}"))) + return Err(anyhow::Error::msg(format!("{error}"))); }; total_proving_time_timer.observe_duration(); @@ -293,7 +293,7 @@ impl Prover { let Ok(proof) = serde_json::from_str::(&json) else { let error: ProverError = serde_json::from_str(&json)?; - return Err(anyhow::Error::msg(format!("{error}"))) + return Err(anyhow::Error::msg(format!("{error}"))); }; total_proving_time_timer.observe_duration(); From c3c0608cbbe2930294453aa8c9c8a5230b845186 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Mon, 18 Sep 2023 16:26:13 -0400 Subject: [PATCH 39/45] chore: cargo clippy --- src/prover/mod.rs | 2 +- src/task_monitor/tasks/process_identities.rs | 4 ++-- src/utils/async_queue.rs | 8 ++++---- tests/validate_proof_with_age.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/prover/mod.rs b/src/prover/mod.rs index c922528d..25c91f52 100644 --- a/src/prover/mod.rs +++ b/src/prover/mod.rs @@ -343,7 +343,7 @@ pub fn compute_insertion_proof_input_hash( bytes.extend(pre_root_bytes.iter()); bytes.extend(post_root_bytes.iter()); - for commitment in identity_commitments.iter() { + for commitment in identity_commitments { let mut commitment_bytes: [u8; size_of::()] = Default::default(); commitment.to_big_endian(commitment_bytes.as_mut_slice()); bytes.extend(commitment_bytes.iter()); diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index 575ebe9f..f11b0ab4 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -136,7 +136,7 @@ async fn process_identities( // Also wake up if woken up due to a tick wake_up_notify.notify_one(); } - _ = wake_up_notify.notified() => { + () = wake_up_notify.notified() => { tracing::trace!("Identity batch insertion woken due to request."); // Capture the time difference since the last batch, and compute @@ -278,7 +278,7 @@ pub async fn insert_identities( .update .leaf_index; - for update in updates[1..].iter() { + for update in &updates[1..] { assert_eq!( last_index + 1, update.update.leaf_index, diff --git a/src/utils/async_queue.rs b/src/utils/async_queue.rs index 477b9e4d..b87c3605 100644 --- a/src/utils/async_queue.rs +++ b/src/utils/async_queue.rs @@ -60,8 +60,8 @@ impl AsyncQueue { // Either could trigger the pop guard to be available tokio::select! { - _ = self.inner.push_notify.notified() => {} - _ = self.inner.pop_notify.notified() => {} + () = self.inner.push_notify.notified() => {} + () = self.inner.pop_notify.notified() => {} } } } @@ -100,8 +100,8 @@ impl AsyncQueue { // Either could trigger the pop guard to be available tokio::select! { - _ = self.inner.push_notify.notified() => {} - _ = self.inner.pop_notify.notified() => {} + () = self.inner.push_notify.notified() => {} + () = self.inner.pop_notify.notified() => {} } } } diff --git a/tests/validate_proof_with_age.rs b/tests/validate_proof_with_age.rs index da5ef4a7..2d51c9dc 100644 --- a/tests/validate_proof_with_age.rs +++ b/tests/validate_proof_with_age.rs @@ -22,7 +22,7 @@ async fn validate_proof_with_age() -> anyhow::Result<()> { let batch_size = 3; let (mock_chain, db_container, insertion_prover_map, _deletion_prover_map, micro_oz) = - spawn_deps(initial_root, &[batch_size], &vec![], tree_depth).await?; + spawn_deps(initial_root, &[batch_size], &[], tree_depth).await?; let prover_mock = &insertion_prover_map[&batch_size]; From da3cfe568e491c99d304dc5be5020241dd3c73d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Tr=C4=85d?= Date: Tue, 19 Sep 2023 00:08:30 +0200 Subject: [PATCH 40/45] Dzejkop/deletion-recovery-dedup-mining (#599) * Split mainnet and secondary finalization * WIP * Fix padding issue * Bring bck commented code --- src/contracts/abi.rs | 30 +- src/contracts/mod.rs | 49 ++- src/database/mod.rs | 1 - src/identity_tree.rs | 17 + src/task_monitor.rs | 96 +----- src/task_monitor/tasks/finalize_identities.rs | 211 ++++++++---- src/task_monitor/tasks/mine_identities.rs | 219 ------------ src/task_monitor/tasks/mod.rs | 1 - src/task_monitor/tasks/process_identities.rs | 92 +---- src/utils.rs | 2 +- src/utils/async_queue.rs | 314 ------------------ src/utils/index_packing.rs | 39 +++ 12 files changed, 299 insertions(+), 772 deletions(-) delete mode 100644 src/task_monitor/tasks/mine_identities.rs delete mode 100644 src/utils/async_queue.rs create mode 100644 src/utils/index_packing.rs diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index 0353373b..32f7e7aa 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -2,13 +2,41 @@ use ethers::prelude::abigen; +/// The `TreeChanged` event emitted by the `IdentityManager` contract. +/// Maps to the following enum in the contract code: +/// +/// ```sol +/// enum TreeChange { +/// Insertion, +/// Deletion, +/// Update +/// } +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TreeChangeKind { + Insertion, + Deletion, + Update, +} + +impl From for TreeChangeKind { + fn from(value: u8) -> Self { + match value { + 0 => Self::Insertion, + 1 => Self::Deletion, + 2 => Self::Update, + _ => panic!("Invalid value for TreeChangeKind: {}", value), + } + } +} + abigen!( WorldId, r#"[ struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid } event TreeChanged(uint256 indexed preRoot, uint8 indexed kind, uint256 indexed postRoot) function registerIdentities(uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot) public virtual - function deleteIdentities(uint256[8] calldata deletionProof, uint32 batchSize, bytes calldata packedDeletionIndices, uint256 preRoot, uint256 postRoot) public virtual + function deleteIdentities(uint256[8] calldata deletionProof, uint32 batchSize, bytes calldata packedDeletionIndices, uint256 preRoot, uint256 postRoot) public virtual function latestRoot() public view virtual returns (uint256 root) function owner() public view virtual returns (address) function queryRoot(uint256 root) public view virtual returns (RootInfo memory) diff --git a/src/contracts/mod.rs b/src/contracts/mod.rs index 03cc0430..aa0719ab 100644 --- a/src/contracts/mod.rs +++ b/src/contracts/mod.rs @@ -5,15 +5,15 @@ pub mod scanner; use std::collections::HashMap; use std::sync::Arc; -use anyhow::anyhow; +use anyhow::{anyhow, Context}; use clap::Parser; use ethers::providers::Middleware; -use ethers::types::{Address, U256}; +use ethers::types::{Address, H256, U256}; use semaphore::Field; use tokio::sync::RwLockReadGuard; use tracing::{error, info, instrument, warn}; -use self::abi::{BridgedWorldId, WorldId}; +use self::abi::{BridgedWorldId, DeleteIdentitiesCall, WorldId}; use crate::ethereum::write::TransactionId; use crate::ethereum::{Ethereum, ReadProvider}; use crate::prover::identity::Identity; @@ -21,6 +21,7 @@ use crate::prover::map::{DeletionProverMap, InsertionProverMap, ReadOnlyInsertio use crate::prover::{Proof, Prover, ProverConfiguration, ProverType, ReadOnlyProver}; use crate::serde_utils::JsonStrWrapper; use crate::server::error::Error as ServerError; +use crate::utils::index_packing::unpack_indices; /// Configuration options for the component responsible for interacting with the /// contract. @@ -360,6 +361,48 @@ impl IdentityManager { Ok(latest_root) } + /// Fetches the identity commitments from a + /// `deleteIdentities` transaction by tx hash + #[instrument(level = "debug", skip_all)] + pub async fn fetch_deletion_indices_from_tx( + &self, + tx_hash: H256, + ) -> anyhow::Result> { + let provider = self.ethereum.provider(); + + let tx = provider + .get_transaction(tx_hash) + .await? + .context("Missing tx")?; + + use ethers::abi::AbiDecode; + let delete_identities = DeleteIdentitiesCall::decode(&tx.input)?; + + let packed_deletion_indices: &[u8] = delete_identities.packed_deletion_indices.as_ref(); + let indices = unpack_indices(packed_deletion_indices); + + tracing::error!("unpacked = {indices:?}"); + + let padding_index = 2u32.pow(self.tree_depth as u32); + + Ok(indices + .into_iter() + .filter(|idx| *idx != padding_index) + .map(|x| x as usize) + .collect()) + } + + #[instrument(level = "debug", skip_all)] + pub async fn is_root_mined(&self, root: U256) -> anyhow::Result { + let (root_on_mainnet, ..) = self.abi.query_root(root).call().await?; + + if root_on_mainnet.is_zero() { + return Ok(false); + } + + Ok(true) + } + #[instrument(level = "debug", skip_all)] pub async fn is_root_mined_multi_chain(&self, root: U256) -> anyhow::Result { let (root_on_mainnet, ..) = self.abi.query_root(root).call().await?; diff --git a/src/database/mod.rs b/src/database/mod.rs index 3d3f957b..a94d92bb 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -793,7 +793,6 @@ mod test { use postgres_docker_utils::DockerContainerGuard; use ruint::Uint; use semaphore::Field; - use sqlx::Row; use super::{Database, Options}; use crate::identity_tree::{Hash, Status}; diff --git a/src/identity_tree.rs b/src/identity_tree.rs index fc99df00..3533c3a0 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -516,6 +516,23 @@ impl TreeVersion { } } +impl TreeVersion +where + T: Version, +{ + pub fn commitments_by_indices(&self, indices: &[usize]) -> Vec { + let tree = self.get_data(); + + let mut commitments = vec![]; + + for idx in indices { + commitments.push(tree.tree.get_leaf(*idx)); + } + + commitments + } +} + /// Public API for working with versions that have a successor. Such versions /// only allow peeking and applying updates from the successor. pub trait TreeWithNextVersion { diff --git a/src/task_monitor.rs b/src/task_monitor.rs index e0a33c9b..25f130d8 100644 --- a/src/task_monitor.rs +++ b/src/task_monitor.rs @@ -3,7 +3,6 @@ use std::time::Duration; use anyhow::Result as AnyhowResult; use clap::Parser; -use ethers::types::U256; use once_cell::sync::Lazy; use prometheus::{linear_buckets, register_gauge, register_histogram, Gauge, Histogram}; use tokio::sync::{broadcast, Notify, RwLock}; @@ -13,19 +12,15 @@ use tracing::{info, instrument, warn}; use self::tasks::delete_identities::DeleteIdentities; use self::tasks::finalize_identities::FinalizeRoots; use self::tasks::insert_identities::InsertIdentities; -use self::tasks::mine_identities::MineIdentities; use self::tasks::process_identities::ProcessIdentities; use crate::contracts::SharedIdentityManager; use crate::database::Database; -use crate::ethereum::write::TransactionId; use crate::identity_tree::TreeState; -use crate::utils::async_queue::AsyncQueue; pub mod tasks; const PROCESS_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const FINALIZE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); -const MINE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const INSERT_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); const DELETE_IDENTITIES_BACKOFF: Duration = Duration::from_secs(5); @@ -34,60 +29,6 @@ struct RunningInstance { shutdown_sender: broadcast::Sender<()>, } -#[derive(Debug, Clone)] -pub struct PendingBatchInsertion { - transaction_id: TransactionId, - pre_root: U256, - post_root: U256, - start_index: usize, -} - -impl PendingBatchInsertion { - pub fn new( - transaction_id: TransactionId, - pre_root: U256, - post_root: U256, - start_index: usize, - ) -> Self { - Self { - transaction_id, - pre_root, - post_root, - start_index, - } - } -} - -#[derive(Debug, Clone)] -pub struct PendingBatchDeletion { - transaction_id: TransactionId, - pre_root: U256, - commitments: Vec, - post_root: U256, -} - -impl PendingBatchDeletion { - pub fn new( - transaction_id: TransactionId, - pre_root: U256, - commitments: Vec, - post_root: U256, - ) -> Self { - Self { - transaction_id, - pre_root, - commitments, - post_root, - } - } -} - -#[derive(Debug, Clone)] -pub enum PendingBatchSubmission { - Insertion(PendingBatchInsertion), - Deletion(PendingBatchDeletion), -} - static PENDING_IDENTITIES: Lazy = Lazy::new(|| { register_gauge!("pending_identities", "Identities not submitted on-chain").unwrap() }); @@ -152,11 +93,6 @@ pub struct Options { #[clap(long, env, default_value = "100")] pub insert_identities_capacity: usize, - /// How many transactions can be sent "at once" to the blockchain via the - /// write provider. - #[clap(long, env, default_value = "1")] - pub pending_identities_capacity: usize, - /// The maximum number of windows to scan for finalization logs #[clap(long, env, default_value = "100")] pub scanning_window_size: u64, @@ -177,12 +113,11 @@ pub struct TaskMonitor { /// when shutdown is called we want to be able to gracefully /// await the join handles - which requires ownership of the handle and by /// extension the instance. - instance: RwLock>, - database: Arc, - identity_manager: SharedIdentityManager, - tree_state: TreeState, - batch_insert_timeout_secs: u64, - pending_identities_capacity: usize, + instance: RwLock>, + database: Arc, + identity_manager: SharedIdentityManager, + tree_state: TreeState, + batch_insert_timeout_secs: u64, // Finalization params scanning_window_size: u64, @@ -202,7 +137,6 @@ impl TaskMonitor { ) -> Self { let Options { batch_timeout_seconds, - pending_identities_capacity, scanning_window_size, time_between_scans_seconds, batch_deletion_timeout_seconds: _, @@ -216,7 +150,6 @@ impl TaskMonitor { identity_manager: contracts, tree_state, batch_insert_timeout_secs: batch_timeout_seconds, - pending_identities_capacity, scanning_window_size, time_between_scans: Duration::from_secs(time_between_scans_seconds), batch_deletion_timeout_seconds: options.batch_deletion_timeout_seconds, @@ -240,8 +173,6 @@ impl TaskMonitor { // in the database wake_up_notify.notify_one(); - let pending_batch_submissions_queue = AsyncQueue::new(self.pending_identities_capacity); - let mut handles = Vec::new(); // Finalize identities task @@ -262,29 +193,12 @@ impl TaskMonitor { handles.push(finalize_identities_handle); - // Mine identities task - let mine_identities = MineIdentities::new( - self.database.clone(), - self.identity_manager.clone(), - self.tree_state.get_processed_tree(), - pending_batch_submissions_queue.clone(), - ); - - let mine_identities_handle = crate::utils::spawn_monitored_with_backoff( - move || mine_identities.clone().run(), - shutdown_sender.clone(), - MINE_IDENTITIES_BACKOFF, - ); - - handles.push(mine_identities_handle); - // Process identities task let process_identities = ProcessIdentities::new( self.database.clone(), self.identity_manager.clone(), self.tree_state.get_batching_tree(), self.batch_insert_timeout_secs, - pending_batch_submissions_queue, wake_up_notify.clone(), ); diff --git a/src/task_monitor/tasks/finalize_identities.rs b/src/task_monitor/tasks/finalize_identities.rs index 92837d88..71716e6c 100644 --- a/src/task_monitor/tasks/finalize_identities.rs +++ b/src/task_monitor/tasks/finalize_identities.rs @@ -2,18 +2,20 @@ use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; -use anyhow::Result as AnyhowResult; +use anyhow::{Context, Result as AnyhowResult}; +use chrono::{DateTime, Utc}; use ethers::abi::RawLog; use ethers::contract::EthEvent; use ethers::providers::Middleware; use ethers::types::{Address, Log, Topic, ValueOrArray, U256}; use tracing::{info, instrument}; -use crate::contracts::abi::{BridgedWorldId, RootAddedFilter, TreeChangedFilter}; +use crate::contracts::abi::{BridgedWorldId, RootAddedFilter, TreeChangeKind, TreeChangedFilter}; use crate::contracts::scanner::BlockScanner; use crate::contracts::{IdentityManager, SharedIdentityManager}; use crate::database::Database; use crate::identity_tree::{Canonical, Intermediate, TreeVersion, TreeWithNextVersion}; +use crate::task_monitor::TaskMonitor; pub struct FinalizeRoots { database: Arc, @@ -76,37 +78,26 @@ async fn finalize_roots_loop( let mainnet_address = mainnet_abi.address(); loop { - let all_roots = fetch_logs( - &mut mainnet_scanner, - &mut secondary_scanners, - mainnet_address, - ) - .await?; + let mainnet_logs = fetch_mainnet_logs(&mut mainnet_scanner, mainnet_address).await?; - finalize_roots( - database, - identity_manager, - processed_tree, - finalized_tree, - all_roots, - ) - .await?; + finalize_mainnet_roots(database, identity_manager, processed_tree, &mainnet_logs).await?; + + let mut roots = extract_roots_from_mainnet_logs(mainnet_logs); + roots.extend(fetch_secondary_logs(&mut secondary_scanners).await?); + + finalize_secondary_roots(database, identity_manager, finalized_tree, roots).await?; tokio::time::sleep(time_between_scans).await; } } -#[instrument(level = "info", skip_all)] -async fn fetch_logs( - mainnet_scanner: &mut BlockScanner, - secondary_scanners: &mut HashMap>, +async fn fetch_mainnet_logs( + mainnet_scanner: &mut BlockScanner, mainnet_address: Address, -) -> anyhow::Result> +) -> anyhow::Result> where - A: Middleware, - ::Error: 'static, - B: Middleware, - ::Error: 'static, + M: Middleware, + ::Error: 'static, { let mainnet_topics = [ Some(Topic::from(TreeChangedFilter::signature())), @@ -115,6 +106,22 @@ where None, ]; + let mainnet_address = Some(ValueOrArray::Value(mainnet_address)); + + let mainnet_logs = mainnet_scanner + .next(mainnet_address, mainnet_topics.clone()) + .await?; + + Ok(mainnet_logs) +} + +async fn fetch_secondary_logs( + secondary_scanners: &mut HashMap>, +) -> anyhow::Result> +where + M: Middleware, + ::Error: 'static, +{ let bridged_topics = [ Some(Topic::from(RootAddedFilter::signature())), None, @@ -122,11 +129,6 @@ where None, ]; - let mainnet_address = Some(ValueOrArray::Value(mainnet_address)); - - let mainnet_logs = mainnet_scanner - .next(mainnet_address, mainnet_topics.clone()) - .await?; let mut secondary_logs = vec![]; for (address, scanner) in secondary_scanners { @@ -137,42 +139,74 @@ where secondary_logs.extend(logs); } - let mut roots = extract_root_from_mainnet_logs(&mainnet_logs); - roots.extend(extract_roots_from_secondary_logs(&secondary_logs)); + let roots = extract_roots_from_secondary_logs(&secondary_logs); Ok(roots) } #[instrument(level = "info", skip_all)] -async fn finalize_roots( +async fn finalize_mainnet_roots( database: &Database, identity_manager: &IdentityManager, processed_tree: &TreeVersion, - finalized_tree: &TreeVersion, - all_roots: Vec, + logs: &[Log], ) -> Result<(), anyhow::Error> { - for root in all_roots { - info!(?root, "Finalizing root"); + for log in logs { + let Some(event) = raw_log_to_tree_changed(log) else { + continue; + }; - let is_root_finalized = identity_manager.is_root_mined_multi_chain(root).await?; + let pre_root = event.pre_root; + let post_root = event.post_root; + let kind = TreeChangeKind::from(event.kind); - if is_root_finalized { - // What can sometimes happen is that this finalize roots function is faster - // than the mine_identities task. In which case we'll try to finalize a given - // root, but it's not yet present in the processed tree. - // - // In that case we can safely apply updates to the processed tree as well. - processed_tree.apply_updates_up_to(root.into()); + info!(?pre_root, ?post_root, ?kind, "Mining batch"); - // We also need to run this update to mark the root as processed - // and apply a mined_at timestamp - database.mark_root_as_processed(&root.into()).await?; + // Double check + if !identity_manager.is_root_mined(post_root).await? { + continue; + } - finalized_tree.apply_updates_up_to(root.into()); - database.mark_root_as_mined(&root.into()).await?; + database.mark_root_as_processed(&post_root.into()).await?; - info!(?root, "Root finalized"); + info!(?pre_root, ?post_root, ?kind, "Batch mined"); + + if kind == TreeChangeKind::Deletion { + // NOTE: We must do this before updating the tree + // because we fetch commitments from the processed tree + // before they are deleted + update_eligible_recoveries(database, identity_manager, processed_tree, &log).await?; } + + let updates_count = processed_tree.apply_updates_up_to(post_root.into()); + + info!(updates_count, ?pre_root, ?post_root, "Mined tree updated"); + + TaskMonitor::log_identities_queues(database).await?; + } + + Ok(()) +} + +#[instrument(level = "info", skip_all)] +async fn finalize_secondary_roots( + database: &Database, + identity_manager: &IdentityManager, + finalized_tree: &TreeVersion, + roots: Vec, +) -> Result<(), anyhow::Error> { + for root in roots { + info!(?root, "Finalizing root"); + + // Check if mined on all L2s + if !identity_manager.is_root_mined_multi_chain(root).await? { + continue; + } + + database.mark_root_as_mined(&root.into()).await?; + finalized_tree.apply_updates_up_to(root.into()); + + info!(?root, "Root finalized"); } Ok(()) @@ -200,19 +234,26 @@ where Ok(secondary_scanners) } -fn extract_root_from_mainnet_logs(logs: &[Log]) -> Vec { +fn extract_roots_from_mainnet_logs(mainnet_logs: Vec) -> Vec { let mut roots = vec![]; + for log in mainnet_logs { + let Some(event) = raw_log_to_tree_changed(&log) else { + continue; + }; - for log in logs { - let raw_log = RawLog::from((log.topics.clone(), log.data.to_vec())); - if let Ok(event) = TreeChangedFilter::decode_log(&raw_log) { - roots.push(event.post_root); - } - } + let post_root = event.post_root; + roots.push(post_root); + } roots } +fn raw_log_to_tree_changed(log: &Log) -> Option { + let raw_log = RawLog::from((log.topics.clone(), log.data.to_vec())); + + TreeChangedFilter::decode_log(&raw_log).ok() +} + fn extract_roots_from_secondary_logs(logs: &[Log]) -> Vec { let mut roots = vec![]; @@ -225,3 +266,57 @@ fn extract_roots_from_secondary_logs(logs: &[Log]) -> Vec { roots } + +use crate::identity_tree::Hash; + +async fn update_eligible_recoveries( + database: &Database, + identity_manager: &IdentityManager, + processed_tree: &TreeVersion, + log: &Log, +) -> anyhow::Result<()> { + let tx_hash = log.transaction_hash.context("Missing tx hash")?; + let commitments = identity_manager + .fetch_deletion_indices_from_tx(tx_hash) + .await + .context("Could not fetch deletion indices from tx")?; + + let commitments = processed_tree.commitments_by_indices(&commitments); + let commitments: Vec = commitments.into_iter().map(|c| c.into()).collect(); + + // Check if any deleted commitments correspond with entries in the + // recoveries table and insert the new commitment into the unprocessed + // identities table with the proper eligibility timestamp + let recoveries = database + .get_recoveries() + .await? + .iter() + .map(|f| (f.existing_commitment, f.new_commitment)) + .collect::>(); + + // Fetch the root history expiry time on chain + let root_history_expiry = identity_manager.root_history_expiry().await?; + + // Use the root history expiry to calcuate the eligibility timestamp for the new + // insertion + let eligibility_timestamp = DateTime::from_utc( + chrono::NaiveDateTime::from_timestamp_opt( + Utc::now().timestamp() + root_history_expiry.as_u64() as i64, + 0, + ) + .context("Could not convert eligibility timestamp to NaiveDateTime")?, + Utc, + ); + + // For each deletion, if there is a corresponding recovery, insert a new + // identity with the specified eligibility timestamp + for prev_commitment in commitments { + if let Some(new_commitment) = recoveries.get(&prev_commitment.into()) { + database + .insert_new_identity(*new_commitment, eligibility_timestamp) + .await?; + } + } + + Ok(()) +} diff --git a/src/task_monitor/tasks/mine_identities.rs b/src/task_monitor/tasks/mine_identities.rs deleted file mode 100644 index b4468c96..00000000 --- a/src/task_monitor/tasks/mine_identities.rs +++ /dev/null @@ -1,219 +0,0 @@ -use std::collections::HashMap; -use std::sync::Arc; - -use anyhow::{Context, Result as AnyhowResult}; -use chrono::{DateTime, Utc}; -use tracing::{info, instrument}; - -use crate::contracts::{IdentityManager, SharedIdentityManager}; -use crate::database::Database; -use crate::identity_tree::{Hash, Intermediate, TreeVersion, TreeWithNextVersion}; -use crate::task_monitor::{ - PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, -}; -use crate::utils::async_queue::AsyncQueue; - -pub struct MineIdentities { - database: Arc, - identity_manager: SharedIdentityManager, - mined_tree: TreeVersion, - pending_batch_submissions_queue: AsyncQueue, -} - -impl MineIdentities { - pub fn new( - database: Arc, - identity_manager: SharedIdentityManager, - mined_tree: TreeVersion, - pending_batch_submissions_queue: AsyncQueue, - ) -> Arc { - Arc::new(Self { - database, - identity_manager, - mined_tree, - pending_batch_submissions_queue, - }) - } - - pub async fn run(self: Arc) -> anyhow::Result<()> { - mine_identities_loop( - &self.database, - &self.identity_manager, - &self.mined_tree, - &self.pending_batch_submissions_queue, - ) - .await - } -} - -async fn mine_identities_loop( - database: &Database, - identity_manager: &IdentityManager, - mined_tree: &TreeVersion, - pending_batch_submissions_queue: &AsyncQueue, -) -> AnyhowResult<()> { - loop { - let pending_identity = pending_batch_submissions_queue.pop().await; - - match pending_identity.read().await { - PendingBatchSubmission::Insertion(pending_identity_insertion) => { - mine_insertions( - pending_identity_insertion, - database, - identity_manager, - mined_tree, - ) - .await?; - } - PendingBatchSubmission::Deletion(pending_identity_deletion) => { - mine_deletions( - pending_identity_deletion, - database, - identity_manager, - mined_tree, - ) - .await?; - } - } - - pending_identity.commit().await; - } -} - -#[instrument(level = "info", skip_all)] -async fn mine_insertions( - pending_identity: PendingBatchInsertion, - database: &Database, - identity_manager: &IdentityManager, - mined_tree: &TreeVersion, -) -> AnyhowResult<()> { - let PendingBatchInsertion { - transaction_id, - pre_root, - post_root, - start_index, - } = pending_identity; - - info!( - start_index, - ?pre_root, - ?post_root, - ?transaction_id, - "Mining batch" - ); - - if !identity_manager - .mine_identities(transaction_id.clone()) - .await? - { - panic!( - "Transaction {} failed on chain - sequencer will crash and restart", - transaction_id - ); - } - - // With this done, all that remains is to mark them as submitted to the - // blockchain in the source-of-truth database, and also update the mined tree to - // agree with the database and chain. - database.mark_root_as_processed(&post_root.into()).await?; - - info!(start_index, ?pre_root, ?post_root, "Batch mined"); - - let updates_count = mined_tree.apply_updates_up_to(post_root.into()); - - info!( - start_index, - updates_count, - ?pre_root, - ?post_root, - "Mined tree updated" - ); - - TaskMonitor::log_identities_queues(database).await?; - - Ok(()) -} - -#[instrument(level = "info", skip_all)] -async fn mine_deletions( - pending_identity_deletion: PendingBatchDeletion, - database: &Database, - identity_manager: &IdentityManager, - mined_tree: &TreeVersion, -) -> AnyhowResult<()> { - let PendingBatchDeletion { - transaction_id, - pre_root, - post_root, - commitments, - } = pending_identity_deletion; - - info!( - ?pre_root, - ?post_root, - ?transaction_id, - "Mining deletion batch" - ); - - if !identity_manager - .mine_identities(transaction_id.clone()) - .await? - { - panic!( - "Transaction {} failed on chain - sequencer will crash and restart", - transaction_id - ); - } - - // With this done, all that remains is to mark them as submitted to the - // blockchain in the source-of-truth database, and also update the mined tree to - // agree with the database and chain. - database.mark_root_as_processed(&post_root.into()).await?; - - // Update the latest deletion - database.update_latest_deletion(Utc::now()).await?; - - info!(?pre_root, ?post_root, "Deletion batch mined"); - - let updates_count = mined_tree.apply_updates_up_to(post_root.into()); - - info!(updates_count, ?pre_root, ?post_root, "Mined tree updated"); - - // Check if any deleted commitments correspond with entries in the - // recoveries table and insert the new commitment into the unprocessed - // identities table with the proper eligibility timestamp - let recoveries = database - .get_recoveries() - .await? - .iter() - .map(|f| (f.existing_commitment, f.new_commitment)) - .collect::>(); - - // Fetch the root history expiry time on chain - let root_history_expiry = identity_manager.root_history_expiry().await?; - - // Use the root history expiry to calcuate the eligibility timestamp for the new - // insertion - let eligibility_timestamp = DateTime::from_utc( - chrono::NaiveDateTime::from_timestamp_opt( - Utc::now().timestamp() + root_history_expiry.as_u64() as i64, - 0, - ) - .context("Could not convert eligibility timestamp to NaiveDateTime")?, - Utc, - ); - - // For each deletion, if there is a corresponding recovery, insert a new - // identity with the specified eligibility timestamp - for prev_commitment in commitments { - if let Some(new_commitment) = recoveries.get(&prev_commitment.into()) { - database - .insert_new_identity(*new_commitment, eligibility_timestamp) - .await?; - } - } - - TaskMonitor::log_identities_queues(database).await?; - - Ok(()) -} diff --git a/src/task_monitor/tasks/mod.rs b/src/task_monitor/tasks/mod.rs index 8db72a66..b3f3569b 100644 --- a/src/task_monitor/tasks/mod.rs +++ b/src/task_monitor/tasks/mod.rs @@ -1,5 +1,4 @@ pub mod delete_identities; pub mod finalize_identities; pub mod insert_identities; -pub mod mine_identities; pub mod process_identities; diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index f11b0ab4..ecd13b8f 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -3,8 +3,6 @@ use std::time::{Duration, SystemTime}; use anyhow::{Context, Result as AnyhowResult}; use ethers::types::U256; -use once_cell::sync::Lazy; -use prometheus::{register_histogram, Histogram}; use ruint::Uint; use semaphore::merkle_tree::Proof; use semaphore::poseidon_tree::Branch; @@ -19,30 +17,19 @@ use crate::identity_tree::{ }; use crate::prover::identity::Identity; use crate::prover::{Prover, ReadOnlyProver}; -use crate::task_monitor::{ - PendingBatchDeletion, PendingBatchInsertion, PendingBatchSubmission, TaskMonitor, -}; -use crate::utils::async_queue::AsyncQueue; +use crate::task_monitor::TaskMonitor; +use crate::utils::index_packing::pack_indices; /// The number of seconds either side of the timer tick to treat as enough to /// trigger a forced batch insertion. const DEBOUNCE_THRESHOLD_SECS: u64 = 1; -static PENDING_IDENTITIES_CHANNEL_CAPACITY: Lazy = Lazy::new(|| { - register_histogram!( - "pending_identities_channel_capacity", - "Pending identities channel capacity" - ) - .unwrap() -}); - pub struct ProcessIdentities { - database: Arc, - identity_manager: SharedIdentityManager, - batching_tree: TreeVersion, + database: Arc, + identity_manager: SharedIdentityManager, + batching_tree: TreeVersion, batch_insert_timeout_secs: u64, - pending_batch_submissions_queue: AsyncQueue, - wake_up_notify: Arc, + wake_up_notify: Arc, } impl ProcessIdentities { @@ -51,7 +38,6 @@ impl ProcessIdentities { identity_manager: SharedIdentityManager, batching_tree: TreeVersion, batch_insert_timeout_secs: u64, - pending_batch_submissions_queue: AsyncQueue, wake_up_notify: Arc, ) -> Arc { Arc::new(Self { @@ -59,7 +45,6 @@ impl ProcessIdentities { identity_manager, batching_tree, batch_insert_timeout_secs, - pending_batch_submissions_queue, wake_up_notify, }) } @@ -70,7 +55,6 @@ impl ProcessIdentities { &self.identity_manager, &self.batching_tree, &self.wake_up_notify, - &self.pending_batch_submissions_queue, self.batch_insert_timeout_secs, ) .await @@ -82,7 +66,6 @@ async fn process_identities( identity_manager: &IdentityManager, batching_tree: &TreeVersion, wake_up_notify: &Notify, - pending_batch_submissions_queue: &AsyncQueue, timeout_secs: u64, ) -> AnyhowResult<()> { info!("Awaiting for a clean slate"); @@ -127,7 +110,6 @@ async fn process_identities( database, identity_manager, batching_tree, - pending_batch_submissions_queue, &updates, ).await?; @@ -178,7 +160,6 @@ async fn process_identities( database, identity_manager, batching_tree, - pending_batch_submissions_queue, &updates, ).await?; @@ -199,7 +180,6 @@ async fn commit_identities( database: &Database, identity_manager: &IdentityManager, batching_tree: &TreeVersion, - pending_batch_submissions_queue: &AsyncQueue, updates: &[AppliedTreeUpdate], ) -> AnyhowResult<()> { // If the update is an insertion @@ -220,15 +200,7 @@ async fn commit_identities( prover.batch_size() ); - insert_identities( - database, - identity_manager, - batching_tree, - pending_batch_submissions_queue, - updates, - prover, - ) - .await?; + insert_identities(database, identity_manager, batching_tree, updates, prover).await?; } else { let prover = identity_manager .get_suitable_deletion_prover(updates.len()) @@ -240,15 +212,7 @@ async fn commit_identities( prover.batch_size() ); - delete_identities( - database, - identity_manager, - batching_tree, - pending_batch_submissions_queue, - updates, - prover, - ) - .await?; + delete_identities(database, identity_manager, batching_tree, updates, prover).await?; } Ok(()) @@ -259,7 +223,6 @@ pub async fn insert_identities( database: &Database, identity_manager: &IdentityManager, batching_tree: &TreeVersion, - pending_batch_submissions_queue: &AsyncQueue, updates: &[AppliedTreeUpdate], prover: ReadOnlyProver<'_, Prover>, ) -> AnyhowResult<()> { @@ -388,14 +351,6 @@ pub async fn insert_identities( ) .await?; - #[allow(clippy::cast_precision_loss)] - PENDING_IDENTITIES_CHANNEL_CAPACITY.observe(pending_batch_submissions_queue.len().await as f64); - - // This queue's capacity provides us with a natural back-pressure mechanism - // to ensure that we don't overwhelm the identity manager with too many - // identities to mine. - let permit = pending_batch_submissions_queue.reserve().await; - info!( start_index, ?pre_root, @@ -427,13 +382,6 @@ pub async fn insert_identities( "Insertion batch submitted" ); - // The transaction will be awaited on asynchronously - permit - .send(PendingBatchSubmission::Insertion( - PendingBatchInsertion::new(transaction_id, pre_root, post_root, start_index), - )) - .await; - // Update the batching tree only after submitting the identities to the chain batching_tree.apply_updates_up_to(post_root.into()); @@ -448,7 +396,6 @@ pub async fn delete_identities( database: &Database, identity_manager: &IdentityManager, batching_tree: &TreeVersion, - pending_batch_submissions_queue: &AsyncQueue, updates: &[AppliedTreeUpdate], prover: ReadOnlyProver<'_, Prover>, ) -> AnyhowResult<()> { @@ -555,10 +502,7 @@ pub async fn delete_identities( identity_manager.validate_merkle_proofs(&identity_commitments)?; - let mut packed_deletion_indices = vec![]; - for &index in &deletion_indices { - packed_deletion_indices.extend_from_slice(&index.to_be_bytes()); - } + let packed_deletion_indices = pack_indices(&deletion_indices); // We prepare the proof before reserving a slot in the pending identities let proof = IdentityManager::prepare_deletion_proof( @@ -570,14 +514,6 @@ pub async fn delete_identities( ) .await?; - #[allow(clippy::cast_precision_loss)] - PENDING_IDENTITIES_CHANNEL_CAPACITY.observe(pending_batch_submissions_queue.len().await as f64); - - // This queue's capacity provides us with a natural back-pressure mechanism - // to ensure that we don't overwhelm the identity manager with too many - // identities to mine. - let permit = pending_batch_submissions_queue.reserve().await; - info!(?pre_root, ?post_root, "Submitting deletion batch"); // With all the data prepared we can submit the identities to the on-chain @@ -603,16 +539,6 @@ pub async fn delete_identities( "Deletion batch submitted" ); - // The transaction will be awaited on asynchronously - permit - .send(PendingBatchSubmission::Deletion(PendingBatchDeletion::new( - transaction_id, - pre_root, - commitments, - post_root, - ))) - .await; - // Update the batching tree only after submitting the identities to the chain batching_tree.apply_updates_up_to(post_root.into()); diff --git a/src/utils.rs b/src/utils.rs index cd5cb489..0734e973 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,7 +8,7 @@ use tokio::sync::broadcast; use tokio::task::JoinHandle; use tracing::{error, info}; -pub mod async_queue; +pub mod index_packing; pub trait Any { fn any(self) -> AnyhowResult; diff --git a/src/utils/async_queue.rs b/src/utils/async_queue.rs deleted file mode 100644 index b87c3605..00000000 --- a/src/utils/async_queue.rs +++ /dev/null @@ -1,314 +0,0 @@ -use std::collections::VecDeque; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; - -use tokio::sync::{Mutex, Notify}; - -#[derive(Clone)] -pub struct AsyncQueue { - inner: Arc>, -} - -struct AsyncQueueInner { - items: Mutex>, - capacity: usize, - push_notify: Notify, - pop_notify: Notify, - pop_guard_exists: AtomicBool, - push_guard_exists: AtomicBool, -} - -impl AsyncQueue { - pub fn new(capacity: usize) -> Self { - AsyncQueue { - inner: Arc::new(AsyncQueueInner { - capacity, - items: Mutex::new(VecDeque::with_capacity(capacity)), - push_notify: Notify::new(), - pop_notify: Notify::new(), - pop_guard_exists: AtomicBool::new(false), - push_guard_exists: AtomicBool::new(false), - }), - } - } - - pub async fn len(&self) -> usize { - self.inner.items.lock().await.len() - } - - /// Creates a guard that will block any other producer from submitting to - /// this queue - /// - /// Blocks until the queue has space for a new item. - /// - /// If there exists another guard at that time - blocks. - /// - /// Doesn't yet send the item, instead the caller should call - /// `guard.send(value)` to send the item. - pub async fn reserve(&self) -> AsyncPushGuard<'_, T> { - loop { - let items = self.inner.items.lock().await; - - let another_guard_exists = self.inner.push_guard_exists.load(Ordering::SeqCst); - - if !another_guard_exists && items.len() < self.inner.capacity { - self.inner.push_guard_exists.store(true, Ordering::SeqCst); - return AsyncPushGuard { queue: self }; - } - - drop(items); - - // Either could trigger the pop guard to be available - tokio::select! { - () = self.inner.push_notify.notified() => {} - () = self.inner.pop_notify.notified() => {} - } - } - } - - /// Pushes an item to the queue - /// - /// Blocks until the queue has space for a new item - pub async fn _push(&self, item: T) { - loop { - let mut items = self.inner.items.lock().await; - - if items.len() < self.inner.capacity { - items.push_back(item); - - self.inner.push_notify.notify_one(); - - return; - } - - drop(items); - - self.inner.pop_notify.notified(); - } - } - - pub async fn pop(&self) -> AsyncPopGuard { - loop { - let no_other_guards_exist = !self.inner.pop_guard_exists.load(Ordering::SeqCst); - let queue_is_not_empty = self.inner.items.lock().await.front().is_some(); - - if no_other_guards_exist && queue_is_not_empty { - self.inner.pop_guard_exists.store(true, Ordering::SeqCst); - - return AsyncPopGuard { queue: self }; - } - - // Either could trigger the pop guard to be available - tokio::select! { - () = self.inner.push_notify.notified() => {} - () = self.inner.pop_notify.notified() => {} - } - } - } -} - -pub struct AsyncPopGuard<'a, T> { - queue: &'a AsyncQueue, -} - -impl<'a, T> AsyncPopGuard<'a, T> -where - T: Clone, -{ - pub async fn read(&self) -> T { - let items = self.queue.inner.items.lock().await; - items.front().unwrap().clone() - } - - pub async fn commit(self) { - let mut items = self.queue.inner.items.lock().await; - self.queue.inner.pop_notify.notify_one(); - items.pop_front(); - } -} - -impl<'a, T> Drop for AsyncPopGuard<'a, T> { - fn drop(&mut self) { - self.queue - .inner - .pop_guard_exists - .store(false, Ordering::Relaxed); - } -} - -pub struct AsyncPushGuard<'a, T> { - queue: &'a AsyncQueue, -} - -impl<'a, T> AsyncPushGuard<'a, T> { - pub async fn send(self, value: T) { - let mut items = self.queue.inner.items.lock().await; - items.push_back(value); - self.queue.inner.push_notify.notify_one(); - } -} - -impl<'a, T> Drop for AsyncPushGuard<'a, T> { - fn drop(&mut self) { - self.queue - .inner - .push_guard_exists - .store(false, Ordering::Relaxed); - } -} - -#[cfg(test)] -mod tests { - use tokio::time::{timeout, Duration}; - - use super::*; - - #[tokio::test] - async fn pop_on_empty_queue() { - let queue: AsyncQueue = AsyncQueue::new(2); - - let pop_guard = timeout(Duration::from_secs_f32(0.5), queue.pop()).await; - - assert!(pop_guard.is_err(), "Pop on empty queue should timeout"); - } - - #[tokio::test] - async fn read_and_commit_single_item() { - let queue: AsyncQueue = AsyncQueue::new(2); - - queue._push(1).await; - - let pop_guard = queue.pop().await; - - queue._push(2).await; - - assert_eq!(pop_guard.read().await, 1); - - pop_guard.commit().await; - - let pop_guard = queue.pop().await; - - assert_eq!(pop_guard.read().await, 2); - } - - #[tokio::test] - async fn drop_without_commit_does_not_remove_item() { - let queue: AsyncQueue = AsyncQueue::new(2); - - queue._push(1).await; - - let pop_guard = queue.pop().await; - - queue._push(2).await; - - assert_eq!(pop_guard.read().await, 1); - - // Drop without committing - drop(pop_guard); - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 1); - } - - #[tokio::test] - async fn only_a_single_pop_guard_can_exist() { - let queue: AsyncQueue = AsyncQueue::new(2); - - queue._push(1).await; - - let first_guard = queue.pop().await; - assert_eq!(first_guard.read().await, 1); - - let second_guard = timeout(Duration::from_secs_f32(0.5), queue.pop()).await; - - assert!(second_guard.is_err(), "Pop on empty queue should timeout"); - - drop(first_guard); - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 1); - } - - #[tokio::test] - async fn pushing_over_capacity_blocks() { - let queue: AsyncQueue = AsyncQueue::new(2); - - queue._push(1).await; - queue._push(2).await; - - let result = timeout(Duration::from_secs_f32(0.5), queue._push(3)).await; - - assert!(result.is_err(), "Push on full queue should timeout"); - } - - #[tokio::test] - async fn reserve_blocks_until_queue_has_space() { - let queue: AsyncQueue = AsyncQueue::new(2); - - queue._push(1).await; - queue._push(2).await; - - let reserve_guard = timeout(Duration::from_secs_f32(0.5), queue.reserve()).await; - assert!( - reserve_guard.is_err(), - "Reserve on full queue should timeout" - ); - - queue.pop().await.commit().await; - - let reserve_guard = queue.reserve().await; - reserve_guard.send(3).await; - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 2); - - pop_guard.commit().await; - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 3); - } - - #[tokio::test] - async fn queue_is_fifo() { - let queue: AsyncQueue = AsyncQueue::new(2); - - queue._push(1).await; - queue._push(2).await; - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 1); - pop_guard.commit().await; - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 2); - } - - #[tokio::test] - async fn only_one_push_guard_can_exist() { - let queue: AsyncQueue = AsyncQueue::new(2); - - let push_guard = queue.reserve().await; - - let result = timeout(Duration::from_secs_f32(0.5), queue.reserve()).await; - - assert!( - result.is_err(), - "Reserve when another guard exists should timeout" - ); - - drop(push_guard); - - let push_guard = queue.reserve().await; - push_guard.send(1).await; - - let push_guard = queue.reserve().await; - push_guard.send(2).await; - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 1); - pop_guard.commit().await; - - let pop_guard = queue.pop().await; - assert_eq!(pop_guard.read().await, 2); - } -} diff --git a/src/utils/index_packing.rs b/src/utils/index_packing.rs new file mode 100644 index 00000000..7873a40b --- /dev/null +++ b/src/utils/index_packing.rs @@ -0,0 +1,39 @@ +pub fn pack_indices(indices: &[u32]) -> Vec { + let mut packed = Vec::with_capacity(indices.len() * 4); + + for index in indices { + packed.extend_from_slice(&index.to_be_bytes()); + } + + packed +} + +pub fn unpack_indices(packed: &[u8]) -> Vec { + let mut indices = Vec::with_capacity(packed.len() / 4); + + for packed_index in packed.chunks_exact(4) { + let index = u32::from_be_bytes(packed_index.try_into().expect("Invalid index length")); + + indices.push(index); + } + + indices +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pack_indices() { + let indices = vec![1, 2, 3, 4, 5, 6, 7, 8]; + + let packed = pack_indices(&indices); + + assert_eq!(packed.len(), 32); + + let unpacked = unpack_indices(&packed); + + assert_eq!(unpacked, indices); + } +} From d5e5d512462c7f84bf64daa40198d871b0fe89b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Tr=C4=85d?= Date: Tue, 19 Sep 2023 14:53:43 +0200 Subject: [PATCH 41/45] Minor fixes (#600) --- src/database/mod.rs | 19 ------------------- src/identity_tree.rs | 4 ++-- src/task_monitor/tasks/finalize_identities.rs | 2 +- src/task_monitor/tasks/process_identities.rs | 10 +++------- 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index a94d92bb..3388e2de 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -158,25 +158,6 @@ impl Database { Ok(()) } - pub async fn get_leaf_index_by_root( - tx: impl Executor<'_, Database = Postgres>, - root: &Hash, - ) -> Result, Error> { - let root_leaf_index_query = sqlx::query( - r#" - SELECT leaf_index FROM identities WHERE root = $1 - "#, - ) - .bind(root); - - let row = tx.fetch_optional(root_leaf_index_query).await?; - - let Some(row) = row else { return Ok(None) }; - let root_leaf_index = row.get::(0); - - Ok(Some(root_leaf_index as usize)) - } - pub async fn get_id_by_root( tx: impl Executor<'_, Database = Postgres>, root: &Hash, diff --git a/src/identity_tree.rs b/src/identity_tree.rs index 3533c3a0..21d2bca9 100644 --- a/src/identity_tree.rs +++ b/src/identity_tree.rs @@ -520,13 +520,13 @@ impl TreeVersion where T: Version, { - pub fn commitments_by_indices(&self, indices: &[usize]) -> Vec { + pub fn commitments_by_indices(&self, indices: impl IntoIterator) -> Vec { let tree = self.get_data(); let mut commitments = vec![]; for idx in indices { - commitments.push(tree.tree.get_leaf(*idx)); + commitments.push(tree.tree.get_leaf(idx)); } commitments diff --git a/src/task_monitor/tasks/finalize_identities.rs b/src/task_monitor/tasks/finalize_identities.rs index 71716e6c..0159cb8d 100644 --- a/src/task_monitor/tasks/finalize_identities.rs +++ b/src/task_monitor/tasks/finalize_identities.rs @@ -281,7 +281,7 @@ async fn update_eligible_recoveries( .await .context("Could not fetch deletion indices from tx")?; - let commitments = processed_tree.commitments_by_indices(&commitments); + let commitments = processed_tree.commitments_by_indices(commitments.iter().copied()); let commitments: Vec = commitments.into_iter().map(|c| c.into()).collect(); // Check if any deleted commitments correspond with entries in the diff --git a/src/task_monitor/tasks/process_identities.rs b/src/task_monitor/tasks/process_identities.rs index ecd13b8f..e35493d9 100644 --- a/src/task_monitor/tasks/process_identities.rs +++ b/src/task_monitor/tasks/process_identities.rs @@ -416,13 +416,9 @@ pub async fn delete_identities( .map(|f| f.update.leaf_index as u32) .collect::>(); - // TODO: note that using `batching_tree.get_leaf()` locks the tree every time - // to speed this up we could write a new function that takes an input array, - // locks it once and gets all the commitments - let mut commitments = deletion_indices - .iter() - .map(|i| batching_tree.get_leaf(*i as usize).into()) - .collect::>(); + let commitments = + batching_tree.commitments_by_indices(deletion_indices.iter().map(|x| *x as usize)); + let mut commitments: Vec = commitments.into_iter().map(U256::from).collect(); let latest_tree_from_updates = updates .last() From a1f2e86e464962ed4d34b4459d0a8d7783f04e42 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Tue, 19 Sep 2023 10:40:37 -0400 Subject: [PATCH 42/45] fix: compare timestamps for database tests --- src/database/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 3388e2de..7a984f30 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1043,8 +1043,8 @@ mod test { assert_eq!(unprocessed_commitments.len(), 1); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); assert_eq!( - unprocessed_commitments[0].eligibility_timestamp, - eligibility_timestamp_0 + unprocessed_commitments[0].eligibility_timestamp.timestamp(), + eligibility_timestamp_0.timestamp() ); Ok(()) @@ -1074,8 +1074,8 @@ mod test { assert_eq!(unprocessed_commitments.len(), 1); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); assert_eq!( - unprocessed_commitments[0].eligibility_timestamp, - eligibility_timestamp_0 + unprocessed_commitments[0].eligibility_timestamp.timestamp(), + eligibility_timestamp_0.timestamp() ); Ok(()) @@ -1601,7 +1601,7 @@ mod test { // Assert values let new_entry = db.get_latest_deletion().await?; - assert_eq!(new_entry.timestamp, new_timestamp); + assert_eq!(new_entry.timestamp.timestamp(), new_timestamp.timestamp()); Ok(()) } From 2d5bc88120be5f41f1f68d1c51d57d2a21138fbe Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Tue, 19 Sep 2023 11:19:31 -0400 Subject: [PATCH 43/45] fix: patched test_latest_deletion_root --- src/database/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 7a984f30..4dc09e16 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1601,7 +1601,7 @@ mod test { // Assert values let new_entry = db.get_latest_deletion().await?; - assert_eq!(new_entry.timestamp.timestamp(), new_timestamp.timestamp()); + assert!((new_entry.timestamp.timestamp() - new_timestamp.timestamp()) <= 1); Ok(()) } From 8beeabcb00896ab69c656c5a393f751d2593955d Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Tue, 19 Sep 2023 12:19:11 -0400 Subject: [PATCH 44/45] fix: timestamp comparison for test --- src/database/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index 4dc09e16..fd0d3988 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1591,7 +1591,7 @@ mod test { // Assert values let initial_entry = db.get_latest_deletion().await?; - assert_eq!(initial_entry.timestamp, initial_timestamp); + assert!(initial_entry.timestamp.timestamp() - initial_timestamp.timestamp() <= 1); // Update with a new timestamp let new_timestamp = chrono::Utc::now(); From 4fc0ac8c44df79efd9b037d5f8f2e9c6a0cc4d50 Mon Sep 17 00:00:00 2001 From: 0xKitsune <0xKitsune@protonmail.com> Date: Tue, 19 Sep 2023 12:21:18 -0400 Subject: [PATCH 45/45] fix: updated timestamp comparison for test_get_eligible_unprocessed_commitments --- src/database/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/database/mod.rs b/src/database/mod.rs index fd0d3988..cba83032 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1042,9 +1042,10 @@ mod test { assert_eq!(unprocessed_commitments.len(), 1); assert_eq!(unprocessed_commitments[0].commitment, commitment_0); - assert_eq!( - unprocessed_commitments[0].eligibility_timestamp.timestamp(), - eligibility_timestamp_0.timestamp() + assert!( + unprocessed_commitments[0].eligibility_timestamp.timestamp() + - eligibility_timestamp_0.timestamp() + <= 1 ); Ok(())